#!/bin/bash
#set -x
set -o posix
#set -u
#set -e
#+
#
# ===============
# makenemo
# ===============
#
# --------------------------
# Compile NEMO
# --------------------------
#
# SYNOPSIS
# ========
#
# ::
#
#  $ makenemo
#
#
# DESCRIPTION
# ===========
#
#
# This script aims :
#
# - to choose MYCONFIG
# - to choose compiler options
# - to create the CONFIG/MYCONFIG/WORK directory
# - to compile this configuration
#
#  Variables used :
#
#  From user input
#
# - NEW_CONF    : configuration to be created
# - REF_CONF    : reference configuration to build the new one from
# - CMP_NAM     : compiler name
# - NBR_PRC     : number of processes used to compile
# - USP_CONF    : unsupported (external) configuration to build the new one from
# - NEM_SUBDIR  : NEMO subdirectory used (specified)
#
#  Locally defined :
#
# - TAB         : NEMO subdirectory used (read)
# - MAIN_DIR    : self explaining
# - CONFIG_DIR  :   "    "    "
# - MODELES_DIR :   "    "    "
# - TOOLS_DIR   :   "    "    "
# - NEMO_DIR    :   "    "    "
# - REMOTE_CTL  : URL link to a remote resource list for an external configuration 
#                 which is not part of the reference suite
# - LOCAL_REF   : Nearest reference configuration to an external configuration 
#                 which is not part of the reference suite
#                 (used to populate work directories if remote access is not available)
#
# EXAMPLES
# ========
#
# ::
#
#  $ ./makenemo -m ifort_osx - j3 -n ORCA2_LIM
#
#
# TODO
# ====
#
# option debug
#
#
# EVOLUTIONS
# ==========
#
# $Id$
#
#
#
#   * creation
#
#-

#-
#- Initialization of the options ---
x_d="";
x_h="";
x_n="";
x_r="";
x_u="";
x_m="";
x_t="";
x_c="";
x_j=1;
x_e="none";
x_s=NEMO;
x_v=1;

#- Local variables ---
b_n=$(basename ${0})
OPTIND=1
MAIN_DIR=$(cd $(dirname "$0"); pwd)
MAIN_DIR=${MAIN_DIR%/SETTE*}
MAIN_DIR=${MAIN_DIR%/TOOLS*}
MAIN_DIR=${MAIN_DIR%/CONFIG*}
export MAIN_DIR
#
export CONFIG_DIR=${MAIN_DIR}/CONFIG
export TOOLS_DIR=${MAIN_DIR}/TOOLS
export COMPIL_DIR=${MAIN_DIR}/TOOLS/COMPILE
export NEMO_DIR=${MAIN_DIR}/${x_s}
export AGRIFUSE=10
declare -a TAB
declare -a REMOTE_CTL
declare -a LOCAL_REF
list_key=0
chk_key=1
#-
#- FCM and functions location ---
export PATH=${MAIN_DIR}/EXTERNAL/fcm/bin:$PATH

#-
#- Choice of the options ---
while getopts :hd:n:r:u:m:j:e:s:v:t:k: V
do
    case $V in
	(h) x_h=${OPTARG};
        echo "Usage	 : "${b_n} \
	    " [-h] [-n name] [-m arch] [-d "dir1 dir2"] [-r conf] [-u conf] [-s Path] [-e Path] [-j No] [-v No] [-k 0/1]";
	echo " -h	        : help";
	echo " -h institute : specific help for consortium members";
	echo " -n name      : config name, [-n help] to list existing configurations";
	echo " -m arch      : choose compiler, [-m help] to list existing compilers";
	echo " -d dir       : choose NEMO sub-directories";
	echo " -r conf      : choose reference configuration";
	echo " -u conf      : choose an unsupported (external) configuration";
        echo " -s Path      : choose alternative location for NEMO main directory";
        echo " -e Path      : choose alternative location for MY_SRC directory";
        echo " -j No        : number of processes used to compile (0=nocompilation)";
        echo " -v No        : set verbosity level for compilation [0-3]";
        echo " -k 0/1       : used cpp keys check (default = 1 -> check activated)";
	echo " -t dir       : temporary directory for compilation"
	echo "";
	echo "Example to install a new configuration MY_CONFIG";
	echo "with OPA_SRC and LIM_SRC_2 ";
	echo "makenemo -n MY_CONFIG -d \"OPA_SRC LIM_SRC_2\"";
	echo "";
	echo "Available configurations :"; cat ${CONFIG_DIR}/cfg.txt;
	echo "";
        echo "Available unsupported (external) configurations :"; cat ${CONFIG_DIR}/uspcfg.txt;
	echo "";
	echo "Example to remove bad configuration ";
	echo "./makenemo -n MY_CONFIG clean_config";
	echo "";
	echo "Example to clean ";
	echo "./makenemo clean";
	echo "";
	echo "Example to list the available keys of a CONFIG ";
	echo "./makenemo list_key";
	echo "";
	echo "Example to add and remove keys";
	echo "./makenemo add_key \"key_iomput key_mpp_mpi\" del_key \"key_agrif\" ";
	echo "";
	echo "Example to add and remove keys for a new configuration, and do not compile";
	echo "./makenemo -n MY_CONFIG -j0 add_key \"key_iomput key_mpp_mpi\" del_key \"key_agrif\" ";
	echo "";
	. ${COMPIL_DIR}/Flist_archfile.sh ${x_h}  ;
	echo "";
	echo "Default : previous configuration and compiler";
	exit 0;;
	(d)  x_d=${OPTARG};;
	(n)  x_n=${OPTARG};;
	(r)  x_r=${OPTARG};;
	(u)  x_u=${OPTARG};;
	(m)  x_m=${OPTARG};;
	(j)  x_j=${OPTARG};;
	(t)  x_t=${OPTARG};;
	(e)  x_e=${OPTARG};;
	(s)  x_s=${OPTARG};;
	(v)  x_v=${OPTARG};;
	(k)  chk_key=${OPTARG};;
	(:)  echo ${b_n}" : -"${OPTARG}" option : missing value" 1>&2;
	exit 2;;
	(\?) echo ${b_n}" : -"${OPTARG}" option : not supported" 1>&2;
	exit 2;;
    esac
done
shift $(($OPTIND-1));

while [ ${#1} -gt 0 ]   # Get clean, clean_config options
do
    case "$1" in
	clean)
	    x_c="--$1"
	    ;;
	clean_config)
	    . ${COMPIL_DIR}/Fclean_config.sh
	    exit
	    ;;
	add_key)
	    # Checking void argument
	    [ ! -z $2 ] && { list_add_key=$2; export ${list_add_key}; }
	    shift
	    ;;
	del_key)
	    # Checking void argument
	    [ ! -z $2 ] && { list_del_key=$2; export ${list_del_key}; }
	    shift
	    ;;
	list_key)
	    list_key=1
	    ;;
	*)
	    echo " \"$1\" BAD OPTION"
	    exit
	    ;;

    esac
    shift
done


#-
#- Go to NEMOGCM/config directory ---
cd ${CONFIG_DIR}

#-
#- Initialisation from input ---
export NEW_CONF=${x_n}
NBR_PRC=${x_j}
CMP_NAM=${x_m}
NEM_SUBDIR=${x_d}
REF_CONF=${x_r}
USP_CONF=${x_u}
NEMO_TDIR=${x_t:-$NEMO_TDIR}
export NEMO_TDIR=${NEMO_TDIR:-$CONFIG_DIR}
export NEMO_DIR=${MAIN_DIR}/${x_s}

#- Check if the tool or the compiler exist or list it
if [ "${NEW_CONF}" == help ] ; then
    echo "Available configurations :"
    cat ${CONFIG_DIR}/cfg.txt
    echo
    echo "Available unsupported (external) configurations :" 
    cat ${CONFIG_DIR}/uspcfg.txt
    exit
fi
[ "${CMP_NAM}" ==  help ] && . ${COMPIL_DIR}/Flist_archfile.sh all && exit

#-
#- Choose a default configuration if needed ---
#- ORCA2_LIM or last one used ---
. ${COMPIL_DIR}/Fcheck_config.sh cfg.txt ${NEW_CONF} || exit

if [ ${#NEW_CONF} -eq 0 ] ; then
    if [ ${#NEM_SUBDIR} -eq 0 ] && [ ${#REF_CONF} -eq 0 ] && [ ${#USP_CONF} -eq 0 ] ; then
	echo "You are installing a new default (ORCA2_LIM) configuration"
	ind=0
	. ${COMPIL_DIR}/Fread_dir.sh OPA_SRC	 YES
	. ${COMPIL_DIR}/Fread_dir.sh LIM_SRC_2   YES
	. ${COMPIL_DIR}/Fread_dir.sh LIM_SRC_3   NO
	. ${COMPIL_DIR}/Fread_dir.sh TOP_SRC	 NO
	. ${COMPIL_DIR}/Fread_dir.sh NST_SRC	 YES
	. ${COMPIL_DIR}/Fread_dir.sh OFF_SRC	 NO
	REF_CONF=ORCA2_LIM
    elif [ ${#NEM_SUBDIR} -gt 0 ] && [ ${#REF_CONF} -eq 0 ] && [ ${#USP_CONF} -eq 0 ] ; then
	echo "You are  installing a new configuration based on ORCA2_LIM"
	TAB=( ${NEM_SUBDIR} )
	REF_CONF=ORCA2_LIM
    elif [ ${#NEM_SUBDIR} -eq 0 ] && [ ${#REF_CONF} -gt 0 ]; then
	echo "You are  installing a new configuration based on ${REF_CONF}"
	. ${COMPIL_DIR}/Fcopy_dir.sh ${REF_CONF}
    elif [ ${#NEM_SUBDIR} -eq 0 ] && [ ${#USP_CONF} -gt 0 ]; then
	echo "You are  installing a new configuration based on the unsupported (external) ${USP_CONF}"
	. ${COMPIL_DIR}/Fcopy_extdir.sh ${USP_CONF}  
        #echo "TTT " ${TAB}
        #echo "RRR " ${REMOTE_CTL}
        #echo "LLL " ${LOCAL_REF}
    fi
    NEW_CONF=${x_n}

    if [ ${#USP_CONF} -gt 0 ]; then
      . ${COMPIL_DIR}/Fmake_extconfig.sh ${NEW_CONF} ${LOCAL_REF}
      . ${COMPIL_DIR}/Ffetch_extdir.sh ${NEW_CONF} ${REMOTE_CTL}  
    else
      . ${COMPIL_DIR}/Fmake_config.sh ${NEW_CONF} ${REF_CONF}
    fi
else
    sed -e "/${NEW_CONF} /d"  ${CONFIG_DIR}/cfg.txt >  ${COMPIL_DIR}/cfg.tmp
    \mv  ${COMPIL_DIR}/cfg.tmp  ${CONFIG_DIR}/cfg.txt
fi

#-
#- Save new configuration and directories names ---
echo ${NEW_CONF} ${TAB[*]} >> ${CONFIG_DIR}/cfg.txt

#-
#- Create the WORK ---
#- Clean links and librairies ---
#- Creating the good links, at first on OPA_SRC ---
. ${COMPIL_DIR}/Fmake_WORK.sh ${x_e} ${NEW_CONF} ${TAB[*]} || exit

. ${COMPIL_DIR}/Fmake_bld.sh ${CONFIG_DIR} ${NEW_CONF}  ${NEMO_TDIR} || exit

# build the complete list of the cpp keys of this configuration
if [ $chk_key -eq 1 ] ; then
    for i in $( grep "^ *#.* key_" ${NEW_CONF}/WORK/* ) 
    do
	echo $i | grep key_ | sed -e "s/=.*//"
    done | sort -d | uniq > ${COMPIL_DIR}/full_key_list.txt
    if [ $list_key -eq 1 ]; then
	cat ${COMPIL_DIR}/full_key_list.txt
	exit 0
    fi
fi

#- At this stage new configuration has been added, we add or remove keys
[ ! -z ${list_add_key} ] && { . ${COMPIL_DIR}/Fadd_keys.sh ${NEW_CONF} add_key ${list_add_key}; }
[ ! -z ${list_del_key} ] && { . ${COMPIL_DIR}/Fdel_keys.sh ${NEW_CONF} del_key ${list_del_key}; }
exit

#- check that all keys are really existing...
if [ $chk_key -eq 1 ] ; then
    for kk in $( cat ${NEW_CONF}/cpp_${NEW_CONF}.fcm )
    do
	if [ "$( echo $kk | cut -c 1-4 )" == "key_" ]; then
	    kk=${kk/=*/}
	    nb=$( grep -c $kk ${COMPIL_DIR}/full_key_list.txt )
	    if [ $nb -eq 0 ]; then
		echo
		echo "E R R O R : key "$kk" is not found in ${NEW_CONF}/WORK routines..."
		echo "we stop..."
		echo
		exit 1
	    fi
	fi
    done
fi

#- At this stage cpp keys have been updated. we can check the arch file
#- When used for the first time, choose a compiler ---
. ${COMPIL_DIR}/Fcheck_archfile.sh arch_nemo.fcm cpp.fcm ${CMP_NAM} || exit

#- At this stage the configuration has beeen chosen
#- We coose the default light file
export USEBLD=bldxag.cfg

#- We look after agrif
grep key_agrif ${COMPIL_DIR}/cpp.fcm && export AGRIFUSE=1 && export USEBLD=${USEBLD/xag/}
. ${COMPIL_DIR}/Fprep_agrif.sh ${NEW_CONF} ${NEMO_TDIR} || exit

#-
#_ END OF CONFIGURATION PHASE
#_

#-
#- Compile ---

if [ "${NBR_PRC}" -gt 0 ]; then
    cd ${NEMO_TDIR}/${NEW_CONF} || cd -

#if AGRIF we do a first preprocessing
    if [ ${#x_c} -eq 0 ]; then
       if [ "$AGRIFUSE" == 1 ]; then 
          fcm build --ignore-lock  -j 1 ${COMPIL_DIR}/bld_preproagr.cfg ||{ cd - ; exit ;}
          echo ""
          echo "---------------------------------"
          echo "CONV preprocessing successfull !!"
          echo "---------------------------------"
          echo ""
       fi
    fi
    fcm build ${x_c} --ignore-lock -v ${x_v} -j ${NBR_PRC} ${COMPIL_DIR}/$USEBLD || cd -
    [ -f ${NEMO_TDIR}/${NEW_CONF}/BLD/bin/nemo.exe ] && ln -sf ${NEMO_TDIR}/${NEW_CONF}/BLD/bin/nemo.exe  ${CONFIG_DIR}/${NEW_CONF}/EXP00/opa

#add remove for clean option
    if  [ ${#x_c} -ne 0 ]; then
        rm -rf ${NEMO_TDIR}/${NEW_CONF}/OPAFILES
        rm -rf ${NEMO_TDIR}/${NEW_CONF}/WORK
        rm -rf ${NEMO_TDIR}/${NEW_CONF}/BLD
        rm -rf ${NEMO_TDIR}/${NEW_CONF}/EXP00/opa
        rm -f ${COMPIL_DIR}/*history ${COMPIL_DIR}/*fcm ${COMPIL_DIR}/*txt
        echo "cleaning ${NEW_CONF} WORK, BLD"
    fi

fi

#- Come back to original directory ---
cd -

#-
#- Unset variables
${COMPIL_DIR}/Fclean_var.sh


