import platform, os, sys
from config import Package, packages, cc

conf_success_file='.config_success'
# remove 'success' file
if os.path.exists(conf_success_file):
    os.remove(conf_success_file)
#
# Add options to be passed on to build.
#

options = [
    ('--prefix', 'prefix', 'Installation prefix.', None),
    ('--build-dir', 'build_dir', 'Sandbox location.', 'build'),
    ('--with-debugging', 'with_debugging', 'Build with debugging (default 1)', eval(os.getenv('WITH_DEBUGGING','1')), 'int'),
    ('--with-profiling', 'with_profiling', 'Build with profiling', eval(os.getenv('WITH_PROFILING','0')), 'int'),
    ('--optimisation-flag', 'optimisation_flag', 'Choose flag for optimisation', 'default', None),
    ('--with-warnings', 'with_warnings', 'Print all warnings at compile time (default 1)', eval(os.getenv('WITH_WARNINGS','1')), 'int'),
    ('--lib-type', 'lib_type', 'Library type: shared or static (default shared)', 'shared'),
    ('--cc', 'CC', 'C compiler', None),
    ('--cxx', 'CXX', 'C++ compiler', None),
    ('--cflags', 'CFLAGS', 'Flags for the C compiler', None),
    ('--cxxflags', 'CXXFLAGS', 'Flags for the C compiler', '-std=c++11'),
    ('--eptiming', 'eptiming', 'Enable Entry point timings: \'1\' will enable profiling for proc 0 only \'2\' will enable profiling per proc (previous setup)', 0, 'int'),
    ('--with-cautious-mode', 'with_cautious_mode', 'Enable extra checking on heavily used functions', 0, 'int'),
]

#
# Setup the environment.
#

env = Environment(ENV=os.environ)
env.Tool('config', toolpath=['config'], options=options)

#
# Definition of our error function
#

def UWExit( self ):
    print('''
*********************************************
Error configuring Underworld2.
If you require assistance, please create
an issue at the Underworld github page:
https://github.com/underworldcode/underworld2
*********************************************
    ''')
    env.Exit(1)

env.AddMethod( UWExit )

#
# Declare which packages we're going to use.
#

env.UsePackage(packages.libm)
env.UsePackage(packages.libXML2)
env.UsePackage(packages.Mpi4pyPk)
env.UsePackage(packages.H5py)
env.UsePackage(packages.Python)
env.UsePackage(packages.NumpyPk)
env.UsePackage(packages.MPI)
env.UsePackage(packages.PETSc)

# this flag is required to prevent possible issues with AssertMacro.h defining 'check' 
if platform.system() == 'Darwin':
    env.MergeFlags('-D__ASSERT_MACROS_DEFINE_VERSIONS_WITHOUT_UNDERSCORES=0')


#
# Perform configuration.
#

if not (GetOption('help') or GetOption('clean')):

    if env.get('CC', None) is not None:
        cc.apply_cc(env, env['CC'])

    # Switch off auto compilers if we were given one.
    if '--cc' in ARGUMENTS:
        env['packages'][packages.MPI].try_compilers = False

    if env.get('prefix', None) is None:
        env['prefix'] = env.GetLaunchDir()
    else:
        env['prefix'] = os.path.join(env.get('prefix'),'underworld')

    # time profiling of entry points:
    # 2 - for profiling per proc
    # 1 - for profiling proc 0 only
    if env.get('eptiming', None) == 1:
        env.MergeFlags('-DENABLE_STGERMAIN_LOG=1')
    elif env.get('eptiming', None) == 2:
        env.MergeFlags('-DENABLE_STGERMAIN_LOG=2')


    # confirm with_geothermal configure
    if env.get('with_geothermal', None):
        if os.path.isdir("Geothermal"):
            print("Checking for Geothermal... yes");
        else:
            print("Geothermal not found");
            env.Exit()


    # confirm with_importers configure
    if env.get('with_importers', None):
        if os.path.isdir("ImportersToolbox"):
            print("Checking for Importers toolbox... yes");
        else:
            print("Importers toolbox not found");
            env.Exit()

    # confirm with_solvers configure
    if env.get('with_solvers', None):
        if os.path.isdir("Solvers"):
            print("Checking for Solvers... yes");
        else:
            print("Solvers not found");
            env.Exit()


    # confirm with_spherical configure
    if env.get('with_spherical', None):
        if os.path.isdir("Spherical"):
            print("Checking for Spherical... yes");
        else:
            print("Spherical not found");
            env.Exit()

    # confirm with_viscoelastic configure
    if env.get('with_viscoelastic', None):
        if os.path.isdir("Viscoelastic"):
            print("Checking for Viscoelastic... yes");
        else:
            print("Viscoelastic not found");
            env.Exit()

    if env.get('with_cautious_mode', None):
        env.MergeFlags('-DCAUTIOUS')

    env['save_vars'] += ['shared_libs', 'static_libs']
    if env.get('lib_type', None) == 'shared':
        env['shared_libs'] = 1
        env['static_libs'] = 0
    elif env.get('lib_type', None) == 'static':
        env['shared_libs'] = 0
        env['static_libs'] = 1
        #env.MergeFlags('-static')
        #env.AppendUnique(LINKFLAGS=['-static'])
        Package.static = True
    else:
        print(""" 
              **** ERROR ****
              Invalid option \'--lib-type\' """)
        env.UWExit()

    # enable all warnings.
    if env.get('with_warnings', None):    
        env.MergeFlags('-Wall')
    if env.get('CC', None) == 'icc':
        env.MergeFlags('-wd869 -wd1419')

    # Copies base environment
    base_env = env.Clone()

    env.ConfigurePackage(packages.libm, required=False)
    env.ConfigurePackage(packages.libXML2)
    env.ConfigurePackage(packages.MPI)
    env.ConfigurePackage(packages.Python, required=True)
    env.ConfigurePackage(packages.PETSc)
    env.ConfigurePackage(packages.NumpyPk, required=True)
    env.ConfigurePackage(packages.Mpi4pyPk, required=True)
    env.ConfigurePackage(packages.H5py, required=True)

    #Squelch swig memory warnings
    env.MergeFlags('-DSWIG_PYTHON_SILENT_MEMLEAK')

    #Set debug and optimise settings last to override any from PETSc
    if env.get('optimisation_flag', None) == 'default':
       if env.get('with_debugging', None):
           env.MergeFlags('-g -DDEBUG -O0')
       else:
           env.MergeFlags('-O2 -DNDEBUG')
    else:
       if env.get('with_debugging', None):
           env.MergeFlags('-g -DDEBUG '+env.get('optimisation_flag', None))
       else:
           env.MergeFlags('-DNDEBUG '+env.get('optimisation_flag', None))

    if env.get('with_profiling'):
      env.MergeFlags('-DUSE_PROFILE -DENABLE_STGERMAIN_LOG')

    # Save environment
    uw_env = env

    # Export the environments
    uw_env.SaveConfig()
    
#
# Create a test file. This file is the indicator of a successful build
#
open(conf_success_file, 'w').close()

#
# Create an installation ID file if it doesn't already exist.
#

idfile = "../_uwid.py"
if not os.path.isfile(idfile):
    import uuid
    with open(idfile,"w+") as f:
        f.write("uwid = \'" + str(uuid.uuid4())  + "\'" )

print(
'''
*****************************************************************
* Successfully configured.                                      *
*                                                               *
* Note that basic usage metrics are dispatched when you use     *
* Underworld.                                                   *
* To opt out, set the UW_NO_USAGE_METRICS environment variable. *
* See PRIVACY.md for full details.                              *
*                                                               *
* Now run \'./compile.py\' to build.                            *
*****************************************************************
''')
