#! /usr/bin/env perl
use strict;
use Cwd;

if ($#ARGV == -1) {
    die " ERROR cam.buildexe: must specify a caseroot input argument";
}
my ($CASEROOT) = @ARGV;
chdir "${CASEROOT}";

my @dirs = ("$CASEROOT/Tools");
unshift @INC, @dirs;
require SetupTools;
my $sysmod; 

my $ATM_GRID		= `./xmlquery  ATM_GRID			-value`;
my $ATM_NCPL		= `./xmlquery  ATM_NCPL			-value`;
my $BUILD_COMPLETE	= `./xmlquery  BUILD_COMPLETE		-value`;
my $CAM_CONFIG_OPTS	= `./xmlquery  CAM_CONFIG_OPTS		-value`;
my $CAM_NAMELIST_OPTS	= `./xmlquery  CAM_NAMELIST_OPTS	-value`;
my $CAM_NML_USE_CASE	= `./xmlquery  CAM_NML_USE_CASE		-value`;
my $CAM_DYCORE		= `./xmlquery  CAM_DYCORE		-value`;
my $CASEBUILD		= `./xmlquery  CASEBUILD		-value`;
my $CCSM_CO2_PPMV	= `./xmlquery  CCSM_CO2_PPMV		-value`;
my $CCSMROOT		= `./xmlquery  CCSMROOT			-value`;
my $COMP_INTERFACE	= `./xmlquery  COMP_INTERFACE		-value`;
my $COMP_OCN		= `./xmlquery  COMP_OCN			-value`;
my $DEBUG		= `./xmlquery  DEBUG			-value`;
my $DIN_LOC_ROOT	= `./xmlquery  DIN_LOC_ROOT		-value`;
my $EXEROOT		= `./xmlquery  EXEROOT 		        -value`;
my $MPILIB		= `./xmlquery  MPILIB			-value`;
my $NTHRDS_ATM		= `./xmlquery  NTHRDS_ATM		-value`;
my $NTASKS_ATM		= `./xmlquery  NTASKS_ATM		-value`;
my $NINST_ATM		= `./xmlquery  NINST_ATM		-value`;
my $PTS_MODE		= `./xmlquery  PTS_MODE			-value`;
my $PTS_LON		= `./xmlquery  PTS_LON			-value`;
my $PTS_LAT		= `./xmlquery  PTS_LAT			-value`;
my $RUNDIR		= `./xmlquery  RUNDIR			-value`;
my $RUN_TYPE		= `./xmlquery  RUN_TYPE			-value`;
my $RUN_STARTDATE	= `./xmlquery  RUN_STARTDATE		-value`;
my $RUN_REFCASE	        = `./xmlquery  RUN_REFCASE		-value`;
my $RUN_REFDATE	        = `./xmlquery  RUN_REFDATE		-value`;
my $RUN_REFTOD	        = `./xmlquery  RUN_REFTOD		-value`;
my $UTILROOT		= `./xmlquery  UTILROOT			-value`;
my $DOCN_MODE		= `./xmlquery  DOCN_MODE		-value`;
my $COMPILER		= `./xmlquery  COMPILER                 -value`; # for chem preprocessor 

if (! -d "$CASEBUILD/camconf" ) {
    $sysmod = "mkdir $CASEBUILD/camconf";
    system($sysmod) == 0 or die "ERROR cam.buildnml: $sysmod failed: $?\n";
}
chdir "$CASEBUILD/camconf";

#--------------------------------------------------------------------
# Invoke cam configure - output will go in $CASEBUILD/camconf
#--------------------------------------------------------------------

if ($BUILD_COMPLETE eq 'FALSE') {

    # Some settings for single column mode.
    my $scm = "";
    if ($PTS_MODE eq 'TRUE') {$scm = "-scam -nosmp";}
    my $spmd = '-spmd';
    if ($MPILIB eq 'mpi-serial') {$spmd = "-nospmd";}
    my $smp = '-smp';
    if ($NTHRDS_ATM == 1) {$smp = "-nosmp";}

    # The ocean component setting is only used by CAM to do attribute matching for
    # setting default tuning parameter values.  In SOM mode we want to use the same
    # tunings as the fully coupled B compset, so set the ocean component to pop in
    # that case.
    my $ocn = $COMP_OCN;
    if ($DOCN_MODE eq 'som') {$ocn = "pop";}
    my $comp;
    if ($COMP_INTERFACE eq 'MCT' ) {$comp = "mct";}
    if ($COMP_INTERFACE eq 'ESMF') {$comp = "esmf";}
    my $CAM_LIB_DIRS = "";
    if ("$CAM_CONFIG_OPTS" =~ /.*cosp.*/) {
	$CAM_LIB_DIRS = "-cosp_libdir $EXEROOT/atm/obj/cosp";
    }
    # level information for CAM is part of the atm grid name - and must be stripped out
    my $nlev=""; 
    if ($ATM_GRID =~ /(.+)(L)(.+)/) {
	$ATM_GRID = $1;
	$nlev="-nlev $3";
    }
    $sysmod = "$CCSMROOT/components/cam/bld/configure -s -fc_type $COMPILER -ccsm_seq -ice none " .
              " -ocn $ocn -comp_intf $comp $scm -spmd $spmd -smp $smp -dyn $CAM_DYCORE "          .
              " -res $ATM_GRID $nlev $CAM_LIB_DIRS $CAM_CONFIG_OPTS"                              ;
    system($sysmod) == 0 or die "ERROR cam.buildnml: $sysmod failed: $?\n";

} else {

    # Verify that we have a config_cache file.
    if (! -e "$CASEBUILD/camconf/config_cache.xml") {
	die "ERROR cam.buildnml: Build is complete but config_cache.xml is missing \n".
            " Cannot run build-namelist; try cleaning build and building again.";
    }
}

#--------------------------------------------------------------------
# Invoke cam build-namelist - output will go in $CASEBUILD/camconf
#--------------------------------------------------------------------

my $ignore = "-ignore_ic_date";
if (($RUN_STARTDATE =~ /.*-01-01.*/) || ($RUN_STARTDATE =~ /.*-09-01.*/)) { $ignore = "-ignore_ic_year";}

my $usecase = "-use_case $CAM_NML_USE_CASE";
if ($CAM_NML_USE_CASE eq 'UNSET') { $usecase = " ";}

my $inst_string;
my $inst_counter = 1;
while ($inst_counter <= $NINST_ATM) {

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

    $inst_string = "";       
    if ($NINST_ATM > 1) {
	$inst_string = `printf _%04d $inst_counter`;

	# If multi-instance case does not have restart file, use single-case restart
	# for each instance
	if ( (! -e "$RUNDIR/rpointer.atm${inst_string}") && (-e "$RUNDIR/rpointer.atm") ) {
	    $sysmod = "cp -v $RUNDIR/rpointer.atm $RUNDIR/rpointer.atm${inst_string}";
	    system($sysmod) == 0 or die "ERROR cam.buildnml: $sysmod failed: $?\n";
	}
    }

    # -----------------------------------------------------
    # create camconf/cesm_namelist
    # -----------------------------------------------------

    my $ncdata;
    if ($RUN_TYPE eq 'hybrid') {
	if (-e "${RUN_REFCASE}.cam${inst_string}.i.${RUN_REFDATE}-${RUN_REFTOD}.nc") {
	    $ncdata = "\'${RUN_REFCASE}.cam${inst_string}.i.${RUN_REFDATE}-${RUN_REFTOD}.nc\'";
	} else  {
	    $ncdata = "\'${RUN_REFCASE}.cam.i.${RUN_REFDATE}-${RUN_REFTOD}.nc\'";
	}
	if ($inst_string != "") {print "WARNING: $ncdata is being used\n"};
    }
    my $cam_branch_file;
    if ($RUN_TYPE eq 'branch') {
	if (-e "${RUNDIR}/${RUN_REFCASE}.cam${inst_string}.r.${RUN_REFDATE}-${RUN_REFTOD}.nc") {
	    $cam_branch_file = "\'${RUNDIR}/${RUN_REFCASE}.cam${inst_string}.r.${RUN_REFDATE}-${RUN_REFTOD}.nc\'";
	} else {
	    $cam_branch_file = "\'${RUNDIR}/${RUN_REFCASE}.cam.r.${RUN_REFDATE}-${RUN_REFTOD}.nc\'";
	    if ($inst_string) {	print "WARNING: $cam_branch_file is being used \n";}
	}
    }

    my $dtime = ( 3600 * 24 ) / $ATM_NCPL;
    my $start_ymd = `echo $RUN_STARTDATE | sed s/-//g `;
    my $ntasks = $NTASKS_ATM/$NINST_ATM;

    my $infile_text = "";
    $infile_text .= " dtime = $dtime \n";
    $infile_text .= " co2vmr = ${CCSM_CO2_PPMV}e-6\n";
    $infile_text .= " start_ymd = $start_ymd";
    if ($ncdata)          {$infile_text .= " ncdata = $ncdata \n";}
    if ($cam_branch_file) {$infile_text .= " cam_branch_file = $cam_branch_file \n";}
    if ($DEBUG eq 'TRUE') {$infile_text .= " state_debug_checks = .true. \n"}

    SetupTools::create_namelist_infile("$CASEROOT", 
				       "$CASEROOT/user_nl_cam${inst_string}", 
				       "$CASEBUILD/camconf/cesm_namelist", 
				       "$infile_text");

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

    if (-e "$CASEBUILD/cam.input_data_list") {
	$sysmod = "rm $CASEBUILD/cam.input_data_list";
	system($sysmod) == 0 or die "ERROR cam.buildnml: $sysmod failed: $?\n";
    }

    $sysmod = "$CCSMROOT/components/cam/bld/build-namelist ";
    $sysmod = "$sysmod -infile $CASEBUILD/camconf/cesm_namelist ";
    $sysmod = "$sysmod -csmdata $DIN_LOC_ROOT $ignore $usecase ";
    $sysmod = "$sysmod -inputdata $CASEBUILD/cam.input_data_list";
    $sysmod = "$sysmod -ntasks $ntasks";
    $sysmod = "$sysmod -namelist \" \&atmexp $CAM_NAMELIST_OPTS \/\" ";
    system($sysmod) == 0 or die "ERROR cam.buildnml: $sysmod failed: $?\n";

    # -----------------------------------------------------
    # move atm_in to $RUNDIR
    # -----------------------------------------------------

    if (-d ${RUNDIR}) {
	$sysmod = "cp $CASEBUILD/camconf/atm_in  ${RUNDIR}/atm_in${inst_string}";
	system($sysmod) == 0 or die "ERROR cam.buildnml: $sysmod failed: $?\n";

	$sysmod = "cp $CASEBUILD/camconf/drv_flds_in ${RUNDIR}/drv_flds_in";
	system($sysmod) == 0 or die "ERROR cam.buildnml: $sysmod failed: $?\n";
    }

    # -----------------------------------------------------
    # increment instance counter
    # -----------------------------------------------------

    $inst_counter = $inst_counter + 1;
}

exit(0);

