import os.path
import re
from glob import glob

import scons

DolfinVersion = "0.6.2"

env = Environment(PATH=os.environ["PATH"], HOME=os.environ["PATH"], CPPDEFINES={"PACKAGE_VERSION": r'\"%s\"' % (DolfinVersion,)}, \
    CXXFLAGS="-Wall")

options = [
        scons.PathOption("prefix", "Installation prefix", "/usr/local"),
        # scons.PathOption("binDir", "Executable installation directory", "$prefix/bin"),
        scons.PathOption("libDir", "Library installation directory", "$prefix/lib"),
        scons.PathOption("includeDir", "C/C++ header installation directory", "$prefix/include"),
        BoolOption("enablePetsc", "Compile with support for PETSc linear algebra", "no"),
        scons.PathOption("petscDir", "Specify path to PETSc", "/usr/local/lib/petsc"),
        BoolOption("enableCurses", "Enable the curses interface", "yes"),
        BoolOption("enableDebug", "Compile with debug information", "yes"),
        BoolOption("enableOptimize", "Compile with optimization", "no"),
        ]
configure = scons.Configure(env, ARGUMENTS, options)
prefix, libDir, includeDir, enablePetsc, petscDir, enableCurses, enableDebug, enableOptimize = configure.finish()
if enableDebug:
    env.Append(CXXFLAGS=["-g"])
if enableOptimize:
    env.Append(CXXFLAGS=["-O2"])

cppDefines = {}
cppPath = []
shlibLibs = []
shlibLibPath = []

# Enable/disable PETSc
if enablePetsc:
    mkFile = os.path.join(petscDir, "bmake", "common", "base")
    if os.path.isfile(mkFile):
        f = os.popen("make -f petsc.conf get_petsc_include PETSC_DIR=%s" % (petscDir,))
        petscCFlags = f.read()
        f.close()
        f = os.popen("make -f petsc.conf get_petsc_libs PETSC_DIR=%s" % (petscDir,))
        petscLibs = f.read()
        f.close()
        cppPath += re.findall(r"-I\s*(\S+)", petscCFlags)
        shlibLibs += re.findall(r"-l\s*(\S+)", petscLibs)
        shlibLibPath += re.findall(r"-L\s*(\S+)", petscLibs)
    else:
        print """*** Unable to find PETSc on your system.
*** Use --with-petsc-dir=<path> to specify the correct path for PETSc,
*** or set the environment variable PETSC_DIR to the correct path.
*** PETSc is available at http://www-unix.mcs.anl.gov/petsc/petsc-2/
"""
        Exit(1)

    cppDefines["HAVE_PETSC_H"] = 1
else:
    # Compile without PETSc
        print "* Disabling PETSc (some demos may not compile)"

# Enable/disable curses
if enableCurses:
    shlibLibs.append("ncurses")
else:
    cppDefines["NO_CURSES"] = 1
    print "* Disabling curses"

# CPP defines and path are common
env.Prepend(CPPDEFINES=cppDefines)
env.Prepend(CPPPATH=cppPath)

subDirs = [os.path.join("src", x) for x in ("kernel",)]

# Create library from object files
objects, hdrDirs = env.SConscript(dirs=subDirs, exports=["env",])
#shlibEnv = env.Copy()
env.Prepend(LIBS=shlibLibs)
env.Prepend(LIBPATH=shlibLibPath)
shlib = env.SharedLibrary(target=os.path.join("build", "dolfin"), source=objects)

assert isinstance(hdrDirs, list),  "SCons expects values of the list type"
demoEnv = env.Copy()
demoEnv.Prepend(CPPPATH=hdrDirs, LIBPATH=["#/build"])
demoEnv.SConscript(os.path.join("src", "demo", "SConscript"), exports={"env": demoEnv})

# Register installation targets

env.Install(libDir, shlib)
hdrs = []
for d in hdrDirs:
    hdrs += glob(os.path.join(d.path, "dolfin", "*.h"))
env.Install(os.path.join(includeDir, "dolfin"), hdrs)

# Create "install" target
env.Alias("install", [libDir, includeDir])
