#!/bin/bash
# -----------------------------------------------------------------------------
# Script     : mkweb_sc_bal_mapping_list.sh.
# Description: Creates spacecraft ballistic mapping data files in ASCII format
#              for Earth, STEREO-Ahead and STEREO-Behind. Observation data may
#              be obtained if necessary.
# -----------------------------------------------------------------------------

# Fink
#. /sw/bin/init.sh

# Fortran
#export PATH="/usr/local/gfortran/bin:${PATH}"
#export DYLD_LIBRARY_PATH="/usr/local/gfortran/lib:${DYLD_LIBRARY_PATH}"

# Tools
#export PS_TOOLS_HOME="/usr/local/ps_tools"
#test -r ${PS_TOOLS_HOME}/init.sh && . ${PS_TOOLS_HOME}/init.sh

# Miscellaneous scripts
#export PATH="${HOME}/Projects/scripts/csh:${PATH}"
#export PATH="${HOME}/Projects/scripts/sh:${PATH}"


declare -ir STATUS_OK=0
declare -ir STATUS_ERROR=1

declare -r UNDEFINED_ENV_VAR_ERRMSG="\
Undefined environment variable: %s."
declare -r INVALID_ARG_ERRMSG="\
Invalid input argument: %s."
declare -r FAILED_CREATE_SC_MAPS_ERRMSG="\
Failed creating spacecraft mapping data: %s."
declare -r INVALID_DIR_PERMISSIONS_ERRMSG="\
Invalid permissions on directory: %s."
declare -r FAILED_CREATE_DIR_ERRMSG="\
Unable to create directory: %s."

declare -r MULTI_SC_DATA_EXIST_WARNING_MSG="
WARNING: Multiple spacecraft observation data exist. Use %s.
"
declare -r NO_SC_DATA_CREATED_WARNING_MSG="
WARNING: No spacecraft observation data file created: %s.
"
declare -r MULTI_SC_DATA_CREATED_WARNING_MSG="
WARNING: Multiple spacecraft observation data files created: %s.
"

declare -ar RUNS_HOME_LIST=(
  "/Volumes/shadow-2/Users/janvier/Projects/mas_mas_std_0101_runs"
  "/Volumes/shadow-2/Users/janvier/Projects/mas_mas_std_0201_runs"
  "/Volumes/shadow-2/Users/janvier/Projects/corhel_5.0.0_runs"
  "/Volumes/shadow-2/Users/janvier/Projects/corhel_5.1.0_runs"
  "/Volumes/shadow-2/Users/janvier/Projects/mas_mas_misc_runs"
  "/Volumes/shadow-2/Users/janvier/Projects/riptide/runs"
)

declare -ar SC_CODE_LIST=(
  "omni_m"
  "stereoa"
  "stereob"
)

if [[ -z "${SC_MAPS_HOME}" ]]; then
  ps_print_err.sh "$0" "$(printf "${UNDEFINED_ENV_VAR_ERRMSG}" "SC_MAPS_HOME")"
  exit ${STATUS_ERROR}
fi

if [[ -z "${SC_DATA_HOME}" ]]; then
  ps_print_err.sh "$0" "$(printf "${UNDEFINED_ENV_VAR_ERRMSG}" "SC_DATA_HOME")"
  exit ${STATUS_ERROR}
fi

# -----------------------------------------------------------------------------

function print_usage_msg {
  printf "
 Script     : mkweb_sc_bal_mapping_list.sh.
 Description: Creates spacecraft ballistic mapping data files in ASCII format
              for Earth, STEREO-Ahead and STEREO-Behind. Observation data may
              be obtained if necessary.

 Usage: mkweb_sc_bal_mapping_list.sh
            -cr_num <seq_of_ints> -res <str> -name <seq_of_strs>

 cr_num: Carrington rotation number(s).
 res   : Resolution.
 name  : Simulation name(s).
 \n"
}

function parse_cli_args {
  declare args=""
  declare -i i=1

  while [[ ${i} -le $# ]]; do
    arg="${!i}"
    i=$((i + 1))

    if [[ "${arg}" = "-cr_num" ]]; then
      cr_nums="${!i}"
    elif [[ "${arg}" = "-res" ]]; then
      res="${!i}"
    elif [[ "${arg}" = "-name" ]]; then
      names="${!i}"
    else
      ps_print_err.sh "$0" "$(printf "${INVALID_ARG_ERRMSG}" "${arg}")"
      return ${STATUS_ERROR}
    fi
    i=$((i + 1))
  done

  if [[ -z "${cr_nums}" || -z "${res}" ]]; then
    print_usage_msg
    return ${STATUS_ERROR}
  fi

  return ${STATUS_OK}
}

function get_valid_run_dirpaths {
  declare cr_num="$1"
  declare res="$2"

  declare -r name_regex1="*_mas_mas_std_[0-9][0-9][0-9][0-9]"
  declare -r name_regex2="*_mas?_mas_std_[0-9][0-9][0-9][0-9]"

  declare path=""
  declare name=""
  declare -a temp_path_list=( )
  declare -a name_list=( )
  declare -a path_list=( )

  for path in ${RUNS_HOME_LIST[@]}; do
    path="${path}/cr${cr_num}-${res}"
    if [[ ! -d "${path}" ]]; then
      continue
    fi

    temp_path_list=(
        $(ls -1d ${path}/${name_regex1} 2> /dev/null)
        $(ls -1d ${path}/${name_regex2} 2> /dev/null)
    )

    for path in ${temp_path_list[@]}; do
      name="$(basename "${path}")"
      if [[ ${#name_list[@]} -eq 0 ||\
            $(ps_get_item_index.sh "${name}" ${name_list[@]}) -eq -1 ]]; then
        name_list=( ${name_list[@]} "${name}" )
        path_list=( ${path_list[@]} "${path}" )
      fi
    done
  done

  printf "%s\n" "${path_list[@]}"
}

function get_run_desc {
  declare name="$1"

  declare desc=""
  # WARNING: Uses '==' comparison operator and avoids double quotes ("")
  #          around indicate pattern matching.
  if [[ ${name} = *_mas_mas_std_0101 ]]; then
    desc="standard medium res. coronal MAS polytropic run"
  elif [[ ${name} = *_mas_mas_std_0201  ||\
          ${name} = *_masp_mas_std_0201 ]]; then
    desc="standard high res. coronal MAS polytropic run"
  elif [[ ${name} = *_mast_mas_std_0101 ]]; then
    desc="standard medium res. coronal MAS thermodynamic run with heating"
    desc="${desc} model 1"
  elif [[ ${name} = *_mast_mas_std_0201 ]]; then
    desc="standard medium res. coronal MAS thermodynamic run with heating"
    desc="${desc} model 2"
  elif [[ ${name} = *_mas_mas_mstev_* ]]; then
    desc="custom high res. coronal MAS polytropic run"
  fi

  printf "%s\n" "${desc}"
}

# Creates a directory for writing purposes. If the directory already exists,
# checks its file permissions.
function create_output_dir {
  declare dirpath="$1"

  if [[ -d "${dirpath}" ]]; then
    if [[ ! -r "${dirpath}" || ! -w "${dirpath}" || ! -x "${dirpath}" ]]; then
      ps_print_err.sh "$0"\
          "$(printf "${INVALID_DIR_PERMISSIONS_ERRMSG}" "${dirpath}")"
      return ${STATUS_ERROR}
    fi
  else
    mkdir -m 0755 -p "${dirpath}"
    if [[ $? -ne ${STATUS_OK} ]]; then
      ps_print_err.sh "$0"\
          "$(printf "${FAILED_CREATE_DIR_ERRMSG}" "${dirpath}")"
      return ${STATUS_ERROR}
    fi
  fi

  return ${STATUS_OK}
}

function create_sc_maps {
  declare runs_home="$1"
  declare cr_num="$2"
  declare res="$3"
  declare name="$4"

  declare -r sc_data_dirpath="${SC_DATA_HOME}/cr${cr_num}"
  declare -r sc_maps_dirpath="${SC_MAPS_HOME}/cr${cr_num}-${res}/${name}"

  echo "creating dir..."
  echo "${sc_data_dirpath}"
  create_output_dir "${sc_data_dirpath}"
  [[ $? -ne ${STATUS_OK} ]] && return ${STATUS_ERROR}

  declare -r yrmmdd_regex="[0-9][0-9][0-9][0-9][0-9][0-9][0-9][0-9]"
  declare -r suffix_regex="-${yrmmdd_regex}-${yrmmdd_regex}.dat"
  declare -a path_list=( )

  declare desc=""
  desc="$(get_run_desc "${name}")"

  declare sc=""
  declare sc_data_filepath=""
  declare sc_data_arg=""

  for sc in ${SC_CODE_LIST[@]}; do
    path_list=( $(ls -1 ${sc_data_dirpath}/${sc}${suffix_regex} 2> /dev/null) )
    if [[ ${#path_list[@]} -eq 0 ]]; then
      sc_data_filepath=""
      sc_data_arg=""
    else
      sc_data_filepath="${path_list[0]}"
      sc_data_arg="-sc_data ${sc_data_filepath}"
      if [[ ${#path_list[@]} -gt 1 ]]; then
        printf "${MULTI_SC_DATA_EXIST_WARNING_MSG}" "${sc_data_filepath}"
      fi
    fi

    ps_create_cr_sc_r0_bal_mapping_list.sh\
        -runs ${runs_home}\
        -cr_num ${cr_num} -res ${res} -name ${name} -periodic\
        -sc ${sc} ${sc_data_arg} -interval 1 -r1 30.0\
        -desc "${desc}" -output ${sc_maps_dirpath}/sc_${sc}.dat
    stat=$?
    if [[ $stat -ne ${STATUS_OK} ]]; then
      ps_print_err.sh "$0"\
          "$(printf "${FAILED_CREATE_SC_MAPS_ERRMSG}"\
          "${sc_maps_dirpath:${#SC_MAPS_HOME}}/sc_${sc}.dat {$stat}")"
      return ${STATUS_ERROR}
    fi

    if [[ -n "${sc_data_filepath}" ]]; then
      continue
    fi

    path_list=( $(ls -1 ${sc_maps_dirpath}/${sc}${suffix_regex} 2> /dev/null) )
    if [[ ${#path_list[@]} -eq 0 ]]; then
      printf "${NO_SC_DATA_CREATED_WARNING_MSG}" \
          "${sc_maps_dirpath:${#SC_MAPS_HOME}+1}"
    elif [[ ${#path_list[@]} -gt 1 ]]; then
      printf "${MULTI_SC_DATA_CREATED_WARNING_MSG}" \
          "${sc_maps_dirpath:${#SC_MAPS_HOME}+1}"
    else
      mv "${path_list[0]}" "${sc_data_dirpath}"
      [[ $? -ne ${STATUS_OK} ]] && return ${STATUS_ERROR}
    fi
  done

  return ${STATUS_OK}
}

function main {
  declare cr_nums=""
  declare res=""
  declare names=""

  parse_cli_args "$@"
  [[ $? -ne ${STATUS_OK} ]] && return ${STATUS_ERROR}

  declare -a cr_num_list=( $(ps_print_seq_num.sh "${cr_nums}") )
  declare -a name_list=( ${names//,/ } )

  declare cr_num=""
  declare path=""
  declare name=""

  for cr_num in ${cr_num_list[@]}; do
    for path in $(get_valid_run_dirpaths "${cr_num}" "${res}"); do
      name="$(basename "${path}")"
      if [[ ${#name_list[@]} -gt 0 &&\
            $(ps_get_item_index.sh "${name}" ${name_list[@]}) -eq -1 ]]; then
        continue
      fi

      create_sc_maps \
          "$(dirname "$(dirname "${path}")")" "${cr_num}" "${res}" "${name}"
    done
  done

  return ${STATUS_OK}
}

# -----------------------------------------------------------------------------

main "$@"
exit $?
