#!/usr/bin/env python

"""
build cime component model library.   This buildlib script is used by all CDEPS components.
"""

import sys, os

_CIMEROOT = os.environ.get("CIMEROOT")
if _CIMEROOT is None:
    raise SystemExit("ERROR: must set CIMEROOT environment variable")
sys.path.append(os.path.join(_CIMEROOT, "scripts", "Tools"))

_LIBDIR = os.path.join(_CIMEROOT, "scripts", "Tools")
sys.path.append(_LIBDIR)

from standard_script_setup import *
from CIME.buildlib import parse_input
from CIME.case import Case
from CIME.utils import run_cmd, symlink_force, expect
from CIME.build import get_standard_cmake_args
from CIME.XML.machines import Machines
from CIME.XML.compilers import Compilers

logger = logging.getLogger(__name__)

def buildlib(bldroot, libroot, case, compname=None):
    if bldroot.endswith("obj") and not compname:
        compname = os.path.basename(os.path.abspath(os.path.join(bldroot,os.pardir)))

    if case.get_value("DEBUG"):
        strdebug = "debug"
    else:
        strdebug = "nodebug"
    if case.get_value("BUILD_THREADED"):
        strthread = "threads"
    else:
        strthread = "nothreads"
    mpilib = case.get_value("MPILIB")

    sharedpath = os.path.join(case.get_value("COMPILER"),mpilib,
                              strdebug, strthread, "nuopc")


    if compname:
        s, o, e = run_cmd("make d{}".format(compname), from_dir=bldroot, verbose=True)
        libname = "lib{}.a".format(compname)
        dlibname = "libd{}.a".format(compname)
        dlibpath = os.path.join(bldroot, dlibname)
        if os.path.exists(dlibpath):
            symlink_force(os.path.join(bldroot,dlibname), os.path.join(libroot,libname))
        else:
            expect(False, "ERROR in {} build {} {}".format(compname,o,e))
    else:
        logger.info("Running cmake for CDEPS")
        srcpath = os.path.join(case.get_value("SRCROOT"),"components","cdeps")

        cmake_flags = get_standard_cmake_args(case, os.path.join(sharedpath,"cdeps"), shared_lib=True)
        ccomp, cxxcomp, fcomp = get_compiler_names(case)

        cmake_flags += " -DCMAKE_C_COMPILER={} -DCMAKE_CXX_COMPILER={} -DCMAKE_Fortran_COMPILER={}".format(ccomp, cxxcomp, fcomp)
        cmake_flags += " -DCMAKE_INSTALL_PREFIX={} ".format(libroot)
        cmake_flags += " -DLIBROOT={} ".format(libroot) + srcpath
        cmake_flags += " -DMPILIB={} ".format(mpilib)
        cmake_flags += " -DPIO_C_LIBRARY={path}/lib -DPIO_C_INCLUDE_DIR={path}/include ".format(path=os.path.join(case.get_value("EXEROOT"),sharedpath))
        cmake_flags += " -DPIO_Fortran_LIBRARY={path}/lib -DPIO_Fortran_INCLUDE_DIR={path}/include ".format(path=os.path.join(case.get_value("EXEROOT"),sharedpath))

        logger.info("cmake_flags {}".format(cmake_flags))
        s,o,e = run_cmd("cmake {} ".format(cmake_flags), from_dir=bldroot, verbose=True)
        expect(not s,"ERROR from cmake output={}, error={}".format(o,e))

        s,o,e = run_cmd("make install", from_dir=bldroot, verbose=True)
        expect(not s,"ERROR from make output={}, error={}".format(o,e))


        # Link the CDEPS component directories to the location expected by cime
        for comp in ("atm", "lnd", "ice", "ocn", "rof", "wav"):
            compname = case.get_value("COMP_{}".format(comp.upper()))
            comppath = os.path.join(case.get_value("EXEROOT"),comp,"obj")
            if compname == "d"+comp:
                if not os.path.islink(comppath):
                    os.rmdir(comppath)
                symlink_force(os.path.join(bldroot,compname), comppath)


def get_compiler_names(case):
    machobj = Machines(machine=case.get_value("MACH"))
    compobj = Compilers(machobj)
    if case.get_value("MPILIB") == 'mpi-serial':
        ccomp = compobj.get_value("SCC").strip()
        cxxcomp = compobj.get_value("SCXX").strip()
        fcomp = compobj.get_value("SFC").strip()
    else:
        ccomp = compobj.get_value("MPICC").strip()
        cxxcomp = compobj.get_value("MPICXX").strip()
        fcomp = compobj.get_value("MPIFC").strip()

    return ccomp, cxxcomp, fcomp


def _main_func(args):
    caseroot, libroot, bldroot = parse_input(args)
    with Case(caseroot) as case:
        buildlib(bldroot, libroot, case)

if __name__ == "__main__":
    _main_func(sys.argv)
