#! /usr/bin/env python3

"""
Namelist creator for E3SM's Land Model component
"""

import os, sys

_CIMEROOT = os.path.join(os.path.dirname(os.path.abspath(__file__)), "..","..","..","cime")
sys.path.append(os.path.join(_CIMEROOT, "scripts", "Tools"))

from standard_script_setup import *
from CIME.case import Case
from CIME.utils import expect, run_cmd_no_fail, safe_copy
from CIME.buildnml import create_namelist_infile, parse_input

logger = logging.getLogger(__name__)

###############################################################################
def buildnml(case, caseroot, compname):
###############################################################################
    expect(compname == "elm", compname)

    os.chdir(caseroot)

    srcroot             = case.get_value("SRCROOT")
    compset             = case.get_value("COMPSET")
    atm_flux_method     = case.get_value("ATM_FLUX_INTEGRATION_METHOD")
    atm_gustiness       = case.get_value("ATM_SUPPLIES_GUSTINESS")
    ccsm_co2_ppmv       = case.get_value("CCSM_CO2_PPMV")
    elm_co2_type        = case.get_value("ELM_CO2_TYPE")
    elm_usrdat_name     = case.get_value("ELM_USRDAT_NAME")
    elm_config_opts     = case.get_value("ELM_CONFIG_OPTS")
    elm_namelist_opts   = case.get_value("ELM_NAMELIST_OPTS")
    elm_bldnml_opts     = case.get_value("ELM_BLDNML_OPTS")
    elm_nml_use_case    = case.get_value("ELM_NML_USE_CASE")
    elm_force_coldstart = case.get_value("ELM_FORCE_COLDSTART")
    comp_interface      = case.get_value("COMP_INTERFACE")
    comp_glc            = case.get_value("COMP_GLC")
    din_loc_root        = case.get_value("DIN_LOC_ROOT")
    glc_nec             = case.get_value("GLC_NEC")
    lnd_grid            = case.get_value("LND_GRID")
    lnd_ncpl            = case.get_value("LND_NCPL")
    rof_ncpl            = case.get_value("ROF_NCPL")
    lnd_domain_path     = case.get_value("LND_DOMAIN_PATH")
    lnd_domain_file     = case.get_value("LND_DOMAIN_FILE")
    mask_grid           = case.get_value("MASK_GRID")
    ncpl_base_period    = case.get_value("NCPL_BASE_PERIOD")
    ninst_lnd           = case.get_value("NINST_LND")
    rundir              = case.get_value("RUNDIR")
    run_type            = case.get_value("RUN_TYPE")
    run_startdate       = case.get_value("RUN_STARTDATE")
    run_refcase         = case.get_value("RUN_REFCASE")
    run_refdate         = case.get_value("RUN_REFDATE")
    run_reftod          = case.get_value("RUN_REFTOD")
    casebuild		= case.get_value("CASEBUILD")

    elmconf_dir = os.path.join(casebuild, "elmconf")

    if not os.path.isdir(elmconf_dir): os.mkdir(elmconf_dir)

    #--------------------------------------------------------------------
    # Invoke clm configure - output will go in CASEROOT/Buildconf/elmconf
    #--------------------------------------------------------------------

    # The following translation is hard-wired for backwards compatibility
    # to support the differences between how the scripts specify the land grid
    # and how it is specified internally

    if lnd_grid == 'T31':  lnd_grid = "48x96"
    if lnd_grid == 'T42':  lnd_grid = "64x128"
    if lnd_grid == 'T85':  lnd_grid = "128x256"
    if lnd_grid == 'T341': lnd_grid = "512x1024"


    config_opts = ""
    resolution = ""
    clmusr = ""
    if mask_grid != "reg":
        config_opts = " "
        resolution = lnd_grid
        clmusr     = ""

    if mask_grid == "reg" and lnd_grid != "ELM_USRDAT":
        config_opts = "-sitespf_pt {}".format(lnd_grid)
        resolution  = lnd_grid
        clmusr      = ""

    if lnd_grid == "ELM_USRDAT":
        config_opts = " "
        resolution = elm_usrdat_name
        clmusr     = " -clm_usr_name {}".format(elm_usrdat_name)

    if "1PT" in compset:
        config_opts = " -sitespf_pt reg"

    # TODO: clm/bld/configure needs to be converted to python
    sysmod = "{}/components/elm/bld/configure".format(srcroot)
    sysmod += "  {} -comp_intf {} {}".format(config_opts, comp_interface, elm_config_opts)
    sysmod += " -usr_src {}/SourceMods/src.elm".format(caseroot)
    run_cmd_no_fail(sysmod, from_dir=elmconf_dir)

    #--------------------------------------------------------------------
    # Invoke clm build-namelist - output will go in CASEROOT/Buildconf/elmconf
    #--------------------------------------------------------------------

    startfiletype = "finidat"
    start_type = "default"
    if run_type == "startup":
        if elm_force_coldstart == "on": start_type = "cold"
    else:
        if run_type == "hybrid":
            start_type = "startup"
        else:
            start_type = run_type

    if run_type == "branch": startfiletype = "nrevsn"

    inst_string = ""
    for inst_counter in range(1, ninst_lnd + 1):

        # -----------------------------------------------------
        # determine instance string
        # -----------------------------------------------------

        inst_string = ""
        if ninst_lnd > 1:
            inst_string = "_{0:04d}".format(inst_counter)

            # If multi-instance case does not have restart file, use single-case restart
            # for each instance
            if not os.path.exists(os.path.join(rundir, "rpointer.lnd{}".format(inst_string))) and \
                   os.path.exists(os.path.join(rundir, "rpointer.lnd")):
                safe_copy(os.path.join(rundir, "rpointer.lnd"),
                          os.path.join(rundir, "rpointer.lnd{}".format(inst_string)))


        # -----------------------------------------------------
        # create elmconf/namelist
        # -----------------------------------------------------

        if inst_counter ==1:
            if os.path.exists("{}/Buildconf/elm.input_data_list".format(caseroot)):
                os.remove("{}/Buildconf/elm.input_data_list".format(caseroot))

        elmicfile = ""
        elm_startfile = ""
        if run_type == "hybrid" or run_type == "branch":
            elm_startfile = "{}.elm{}.r.{}-{}.nc".format(run_refcase, inst_string, run_refdate, run_reftod)
            if not os.path.exists(os.path.join(rundir, elm_startfile)):
                elm_startfile = "{}.elm.r.{}-{}.nc".format(run_refcase, run_refdate, run_reftod)

            elmicfile = " {} = '{}'".format(startfiletype, elm_startfile)

        infile_text = ""
        if elmicfile: infile_text = "{} = '{}' \n".format(startfiletype, elm_startfile)

        if atm_flux_method == 'implicit_stress':
            implicit_stress = True
        else:
            implicit_stress = False

        if implicit_stress: infile_text += " implicit_stress = .true. \n"
        if atm_gustiness: infile_text += " atm_gustiness = .true. \n"

        create_namelist_infile(case,
                               "{}/user_nl_elm{}".format(caseroot, inst_string),
                               "{}/namelist".format(elmconf_dir),
                               infile_text=infile_text)

        # -----------------------------------------------------
        # call build-namelist
        # -----------------------------------------------------

        glc_opts = ""
        if comp_glc != "sglc":
            glc_smb = str(case.get_value("GLC_SMB")).lower()
            glc_opts = "-glc_present -glc_smb .{}. ".format(glc_smb)

        usecase = " "
        if elm_nml_use_case != "UNSET": usecase = "-use_case {}".format(elm_nml_use_case)

        start_ymd = run_startdate.replace("-", "")

        # change to always ignore_ic_year to allow more flexibility in specifying IC for different start date of year
        # ignore = "-ignore_ic_year" if ("-01-01" in run_startdate or "-09-01" in run_startdate) else "-ignore_ic_date"
        ignore = "-ignore_ic_year"

        sysmod =  "{}/components/elm/bld/build-namelist -infile {}/Buildconf/elmconf/namelist ".format(srcroot, caseroot)
        sysmod += " -csmdata {} -inputdata {}/Buildconf/elm.input_data_list {}".format(din_loc_root, caseroot, ignore)
        sysmod += ' -namelist " &elm_inparm  start_ymd={} {} /"'.format(start_ymd, elm_namelist_opts)
        sysmod += " {} {} -res {} {} -clm_start_type {}".format(usecase, glc_opts, resolution, clmusr, start_type)
        sysmod += " -envxml_dir {} -l_ncpl {} -r_ncpl {} -lnd_frac {}/{}".format(caseroot, lnd_ncpl, rof_ncpl, lnd_domain_path, lnd_domain_file)
        sysmod += " -glc_nec {} -co2_ppmv {} -co2_type {} ".format(glc_nec, ccsm_co2_ppmv, elm_co2_type)
        sysmod += " -ncpl_base_period {} ".format(ncpl_base_period)
        sysmod += " -config {}/config_cache.xml {}".format(elmconf_dir, elm_bldnml_opts)
        if mask_grid != "reg":
            sysmod += " -mask {}".format(mask_grid)

        # check if the case still attempts to use user_nl_clm, stop proceeding if detected
        if os.path.exists(os.path.join(caseroot, "user_nl_clm")):
           sys.exit("\n *** STOP: It appears you are still using user_nl_clm, please change it to user_nl_elm. ***\n")

        # TODO: clm/bld/build-namelist needs to be converted to python
        run_cmd_no_fail(sysmod, from_dir=elmconf_dir)

        # -----------------------------------------------------
        # move lnd_in to $RUNDIR
        # -----------------------------------------------------

        if os.path.isdir(rundir):
            safe_copy(os.path.join(elmconf_dir, "lnd_in"), os.path.join(rundir, "lnd_in{}".format(inst_string)))

	# Only copy drv_flds_in namelist file if one doesn't already exist
        if not os.path.exists(os.path.join(rundir, "drv_flds_in")) and os.path.exists(os.path.join(elmconf_dir, "drv_flds_in")):
            safe_copy(os.path.join(elmconf_dir, "drv_flds_in"), os.path.join(rundir, "drv_flds_in"))

###############################################################################
def _main_func():
###############################################################################
    caseroot = parse_input(sys.argv)
    with Case(caseroot) as case:
        buildnml(case, caseroot, "elm")

if __name__ == "__main__":
    _main_func()
