#!/usr/bin/env sh

set -o errexit
set -o pipefail
set -o nounset

source ${CI_PROJECT_DIR}/ci/stack_env.sh

mkdir -p ${STACK_LOCATION}
cd ${STACK_LOCATION}

echo "Setting up spack"
if [ ! -d spack/.git ]; then
  git clone https://github.com/spack/spack.git
else
  git -C spack fetch
#  git -C spack pull
fi
git -C spack checkout $SPACK_VERSION


echo "Adding spack system config file"

if [ ! -e ${SPACK_SYSTEM_CONFIG_PATH}/spack.yaml ]
then
  spack/bin/spack \
    --color=always \
    env create \
    --without-view ${environment}
fi

declare -A file_mapping
file_mapping["_common"]=""
file_mapping["_stack"]="_stack"
file_mapping["_acc_${acc_type}"]="_accel"
file_mapping["_${environment}"]="_env"

replace_placholders() {
  dst=$1
  declare -A placeholders
  placeholders["{target}"]="${target}"
  placeholders["{gcc_version}"]=$(jq -Mrc '.stack.compilers.gcc.version' ${STACK_CONFIG})
  if [ "${accelerator}" != "none" ]
  then
    placeholders["{${acc_type}_arch}"]="${acc_arch}"
  fi

  for ph in ${!placeholders[@]}
  do
    rep=${placeholders[$ph]}
    sed -i -e "s/$ph/$rep/g" "$dst"
  done
}


echo "Copying cp ${STACK_CONFIG_PATH}/spack.yaml to ${SPACK_SYSTEM_CONFIG_PATH}/"
cp ${STACK_CONFIG_PATH}/spack.yaml ${SPACK_SYSTEM_CONFIG_PATH}

replace_placholders ${SPACK_SYSTEM_CONFIG_PATH}/spack.yaml

for file in mirrors packages concretizer config definitions modules
do
  for suffix in ${!file_mapping[@]}
  do
    src=${STACK_CONFIG_PATH}/${file}${suffix}.yaml
    dst=${SPACK_SYSTEM_CONFIG_PATH}/${file}"${file_mapping[$suffix]}".yaml
    if [ -e "${src}" ]
    then
      echo "Copying $src to $dst"
      cp "$src" "$dst"

      replace_placholders ${dst}
    fi
  done
done

if [ -d cp -r "${STACK_CONFIG_PATH}/templates" ${SPACK_SYSTEM_CONFIG_PATH} ]
then
   cp -r "${STACK_CONFIG_PATH}/templates" ${STACK_LOCATION}/spack/share/spack
fi

if [ -d "${STACK_CONFIG_PATH}/licenses" ]
then
  cp -r "${STACK_CONFIG_PATH}/licenses/*" ${STACK_LOCATION}/spack/etc/spack
fi


cat <<EOF > ${SPACK_SYSTEM_CONFIG_PATH}/modules_stack.yaml
modules:
  default:
    roots:
      lmod: ${STACK_LOCATION}/spack/share/spack/lmod/${environment}
      tcl: ${STACK_LOCATION}/spack/share/spack/modules/${environment}
EOF

$STACK_LOCATION/spack/bin/spack config \
  --scope defaults \
  rm \
  'modules:default:lmod:hierarchy'

mirrors=$(jq -Mrc '
.spack.mirrors
  | to_entries
  | map(select(.value.type="relative"))
  | map("  \(.key): \(env.MOUNT_POINT)/\(.value.url)")
  | .[]
' ${STACK_CONFIG})

cat <<EOF > ${SPACK_SYSTEM_CONFIG_PATH}/mirrors.yaml
mirrors:
${mirrors}
EOF


echo "Setting up packages"

if [ -e ${SPACK_SYSTEM_CONFIG_PATH}/packages.yaml ]
then
  mv ${SPACK_SYSTEM_CONFIG_PATH}/packages.yaml packages.yaml.old
fi

echo "packages:" > ${SPACK_SYSTEM_CONFIG_PATH}/packages.yaml

export system_compiler=$(jq -Mrc '
.stack
 | .system_compiler
 | to_entries
 | .[].value
 | "\(.compiler)@\(.version)"
' ${STACK_CONFIG})

export system_arch=$(jq -Mrc '
.stack.system_arch
' ${STACK_CONFIG})

jq -Mrc '
.stack.system_packages
 | map("  \(.):\n    require:\n    - \"%\(env.system_compiler)\"\n    - \"\(env.system_arch)\"")
 | .[]
' ${STACK_CONFIG} >> ${SPACK_SYSTEM_CONFIG_PATH}/packages.yaml

if [ -e packages.yaml.old ]
then
  yq eval-all --inplace 'select(fileIndex==0) *+ select(fileIndex==1)' \
    ${SPACK_SYSTEM_CONFIG_PATH}/packages.yaml packages.yaml.old
  rm packages.yaml.old
fi

echo "Setting up extra repos"

EXTERNAL_REPOS=$(jq -r '.spack.repos | keys[]' ${STACK_CONFIG})
spack_external_repos="${STACK_LOCATION}/external_repos"
mkdir -p ${spack_external_repos}

echo "repos:" > ${SPACK_SYSTEM_CONFIG_PATH}/repos.yaml

for repo in ${EXTERNAL_REPOS}
do
  repo_branch=$(jq -r ".spack.repos.\"${repo}\".branch" ${STACK_CONFIG})

  echo " - ${spack_external_repos}/${repo}"
  echo " - ${spack_external_repos}/${repo}" >> ${SPACK_SYSTEM_CONFIG_PATH}/repos.yaml
  if [ ! -d ${spack_external_repos}/${repo} ]; then
    echo "Cloning repo: ${repo}"
    url_branch=$(jq -r ".spack.repos.\"${repo}\".url" ${STACK_CONFIG})
    git clone -b ${repo_branch} ${url_branch} ${spack_external_repos}/${repo}

  else
    echo "Update repo: ${repo}"
    git -C ${spack_external_repos}/$repo fetch
    git -C ${spack_external_repos}/$repo checkout ${repo_branch}
    git -C ${spack_external_repos}/$repo pull
  fi
done

for file in mirrors packages concretizer config modules repos
do
  if [ -e "${SPACK_SYSTEM_CONFIG_PATH}/${file}.yaml" ]
  then
    cp "${SPACK_SYSTEM_CONFIG_PATH}/${file}.yaml" spack/etc/spack
  fi
done


echo "Setting up buildcache"

spack/bin/spack \
  --color=always \
  gpg trust \
  $GPG_PRIVATE_KEY

if [ ! -d ${MOUNT_POINT}/buildcache/${environment}/build_cache ]; then
  spack/bin/spack \
    --color=always \
    gpg publish \
    -d ${MOUNT_POINT}/buildcache/${environment}
fi

if ! spack/bin/spack mirror list | grep buildcache; then
  echo "Add buildcache in mirrors"
  spack/bin/spack  \
    --color=always \
    mirror add \
    --type binary \
    --scope system \
    buildcache file://${MOUNT_POINT}/buildcache/${environment}
fi

spack/bin/spack \
    --color=always \
    buildcache keys \
    --install \
    --trust

_compilers=$(jq -Mrc '.stack
  | .system_arch as $arch
  | .compilers
  | to_entries
  | .[]
  | {name: .key, arch: $arch} + .value
  | select((.constraint == null) or (.constraint? | index(env.environment)))
' ${STACK_CONFIG})

compilers_names="$(echo ${_compilers} | jq -Mrs '. | map("\(.name)") | .[]' | egrep -v '^gcc$')"

echo "List compilers:"
echo ${_compilers} | jq -C '.'

main_env_path=${STACK_LOCATION}/spack/var/spack/environments/${environment}

for name in ${compilers_names}
do
  source ${CI_PROJECT_DIR}/ci/stack_env.sh ${name}

  echo "Configure compiler environment for ${name}"

  if [ ! -e ${SPACK_SYSTEM_CONFIG_PATH} ]
  then
    echo "${SPACK_SYSTEM_CONFIG_PATH} does not exist, creating env"
    ${STACK_LOCATION}/spack/bin/spack --color=always env create --without-view ${full_environment}
  fi

  if [ ${SPACK_SYSTEM_CONFIG_PATH} != ${main_env_path} ]
  then
    for file in mirrors packages concretizer config definitions modules repos
    do
      cp ${main_env_path}/${file}*.yaml ${SPACK_SYSTEM_CONFIG_PATH}
    done
  fi

  if [ -e ${STACK_CONFIG_PATH}/spack_${name}.yaml ]
  then
    cp ${STACK_CONFIG_PATH}/spack_${name}.yaml ${SPACK_SYSTEM_CONFIG_PATH}/spack.yaml
    replace_placholders ${SPACK_SYSTEM_CONFIG_PATH}/spack.yaml
  fi
done