#!/bin/bash

set -e

version=$(cat /etc/ngcp_version)
date=$(date +"%Y%m%d-%H%M")
output_file="/tmp/diff_customtt_${version}_${date}_files.txt"
error_file="/tmp/diff_customtt_${version}_${date}_errors.txt"
archive_file="/tmp/diff_customtt_${version}_${date}_archive.tar"
tmp_tt2_dir=""
check_patchtt=false
failed_patchtt=false

# --- help -----
help_menu () {
  echo "$0 - Script to fetch current customtt on the system and to help you to merge current customtt to the TT2 templates of your target release."
  echo " "
  echo "Usage: $0 [option]"
  echo " "
  echo "Option:
    -h|--help:                Print this help
    -t|--tar-new-customtt:    Tar the new customtt in a tar file
    -d|--download-target:     Download templates for your target version
    -c|--check-ngcp-update:   Check current patchtt against latest templates for ngcp-update procedure
    no option:                Script will show you (and tar for you) current customtt.tt2 in the system"
  exit 0
}

get_new_customtts () {

  local ver_folder=()
  local tar_opts=()
  local target_version
  local customtts
  local patchtts
  local customtt_files
  local patchtt_files
  local tmp_tar_dir

  mapfile -t ver_folder < <(find /tmp -name "tt2_mr*")

  if [ "${#ver_folder[@]}" -gt 1 ]; then
    echo "You have more than one folder where to TAR the new customtt files from."
    echo "Remove the obsolete folders and re-run the command!"
    printf '%s\n' "${ver_folder[@]}"
    exit 1
  fi

  if [ "${#ver_folder[@]}" -lt 1 ]; then
    echo "The script did not find a /tmp/tt2_mr* folder where to TAR the new customtt files from."
    echo "Download the default templates for your target release and put your customtt files there:"
    echo "Run '$0 -d' to download templates for your target release!"
    exit 1
  fi

  echo "Getting an archive with the new templates from ${ver_folder[0]}."
  target_version=$(find /tmp -name "tt2_mr*" | cut -d"_" -f2)
  cd "${ver_folder[0]}"
  mapfile -t customtts < <(find "${ver_folder[0]}" -name "*customtt.tt2*")
  mapfile -t patchtts < <(find "${ver_folder[0]}" -name "*patchtt.tt2*")

  if [[ "${#customtts[@]}" -lt 1 && "${#patchtts[@]}" -lt 1 ]]; then
    echo "No customtt/patchtt in ${ver_folder[0]} for version ${target_version} to archive."
    echo "Merge your ${version} customtt to the new ${target_version} version!"
    exit 1
  fi
  if [ "${#customtts[@]}" -gt 0 ]; then
    echo "The following customtt files for ${target_version} have been found:"
    echo ""
    printf '%s\n' "${customtts[@]}"
  fi
  if [ "${#patchtts[@]}" -gt 0 ]; then
    echo -e "\n\nThe following patchtt files have been found. Make sure they are still relevant in the new release:"
    echo ""
    printf '%s\n' "${patchtts[@]}"
  fi

  echo -e "\nArchiving customtt and patchtt files for ${target_version}"
  echo "Note: Only customtt and patchtt that were found in ${ver_folder[0]} were added to the archive!"

  mapfile -t customtt_files < <(find "${ver_folder[0]}" -name "*customtt.tt2*" -type f -printf '%P\n')
  mapfile -t patchtt_files < <(find "${ver_folder[0]}" -name "*patchtt.tt2*" -type f -printf '%P\n')
  for i in "${customtt_files[@]}"; do
    tar_opts+=("$i")
  done

  for i in "${patchtt_files[@]}"; do
    tar_opts+=("$i")
  done

  tmp_tar_dir=$(mktemp -d "/tmp/tar_new_customtt_${target_version}.XXXXXX") || { echo -e "\nFailed to create temp file"; exit 1; }

  if tar -cf "${tmp_tar_dir}/new_customtt_${target_version}.tar" "${tar_opts[@]}" 2>> "${error_file}" >/dev/null ; then
    echo -e "\nDone.\n"
  else
    echo "Failed to archive the customtt."
    exit 1
  fi

  echo "Please find your new customtt and preserved patchtt files in '${tmp_tar_dir}/new_customtt_${target_version}.tar'"
}


customtt_helper() {

  local file_find=()
  local original
  local not_exist
  local file_counter=0

  rm -f "${output_file}" "${error_file}" "${archive_file}"

  #Retrieving existing customtt.tt2 files
  while IFS=  read -r -d $'\0'; do
    file_find+=("$REPLY")
  done < <(find /etc/ngcp-config/templates/ -regextype egrep -regex '^.*\.customtt\.tt2(|\.sp[1-9]|\.(|web|db|lb|slb|prx)[0-9]{2}(|[a-i]))$' -print0)


  if [ "${#file_find[@]}" -eq 0 ] ; then
    echo -e "There are no customtt.tt2 files in the system"
    return 0
  fi

  #Printing found customtt.tt2 files
  {
    echo -e "\nFound the following customtt.tt2 files"
    echo -e "************************************************"
    for customtt in "${file_find[@]}" ; do
      echo -e "${customtt}"
    done
  } | tee -a "${output_file}"

  #Loop on found customtt.tt2 files to check diff with the original ones
  echo -e "\nChecking diff between the original templates and the corresponding customtt files:"
  echo -e "************************************************"
  for customtt in "${file_find[@]}" ; do
    not_exist=""

    #If there is a more specific tt2 file (i.e. tt2.sp1, tt2.web01, etc...), we need to compare the customtt with that one
    original="${customtt/customtt.tt2/tt2}"
    if [ ! -f "${original}" ]; then
      not_exist="\nNote: The specific template '${original}' does not exist in /etc/ngcp-config!"
      original="${customtt/customtt.tt2*/tt2}"
    fi
    file_counter=$((file_counter + 1))
    echo -e "\n***${file_counter}***"
    echo -e "${original}"
    echo -e "${customtt}"

    {
      echo -e "\n\n\n\n************************************************"
      echo -e "Creating diff for ${customtt}"
      echo -e "************************************************\n"
    } >> "${output_file}"

    if [ -n "${not_exist}" ]; then
      echo -e "${not_exist}\n"  | tee -a "${output_file}"
    fi

    if [ -f "${original}" ]; then
      set +e
      diff -suN "${original}" "${customtt}" 2>> "${error_file}" >> "${output_file}"
      set -e
    else
      echo -e "Note: The general template '${original}' does not exist in /etc/ngcp-config as well!" | tee -a "${output_file}"
    fi
  done


  #Create an archive file with the customtt.tt2 files and the diff files
  echo -e "\nCreating the tar archive with all customtt.tt2 files"
  echo -e "************************************************"

  # shellcheck disable=SC2261
  tar -cf "${archive_file}" "${file_find[@]}" 2>> "${error_file}" 2>/dev/null
}

patchtt_helper() {
  local file_find=()
  local original
  local not_exist
  local file_counter=0
  local patch_opts=()
  local patch_opts+=(-F0 -N)              # set fuzz factor to zero to match "ngcpcfg patch"
  local patch_opts+=(--dry-run)


  #Retrieving existing patchtt.tt2 files
  while IFS=  read -r -d $'\0'; do
    file_find+=("$REPLY")
  done < <(find /etc/ngcp-config/templates/ -regextype egrep -regex '^.*\.patchtt\.tt2(|\.sp[1-9]|\.(|web|db|lb|slb|prx)[0-9]{2}(|[a-i]))$' -print0)

  if [ "${#file_find[@]}" -eq 0 ] ; then
    echo -e "There are no patchtt files in the system"
    return 0
  fi

  if ! "${check_patchtt}" ; then
    #Ask if patchtt should be checked
    while true ; do
      echo -e "\nAt least one patchtt file has been found!"
      echo -e "\nWould you like to check whether patchtt files in your current /etc/ngcp-config folder could be applied to the target release?"
      echo -e "For this, the default template files for the target release will be downloaded to /tmp/. Check patchtt (y/n)? "
      read -r choice
      case "${choice}" in
        y|Y ) break;;
        n|N ) echo -e "Skipping your current patchtt files check. Note that they will _NOT_ be added to the final archive!\n"; echo -e "\nPatchtt files were NOT checked and _NOT_ added to the archive!\n" >> "${output_file}"  && return 0;;
        * )   echo "Invalid choice. Enter y or n, please";;
      esac
    done
  fi

  #Downloading templates from the target release to test patch files against them.
  download_target_release

  #Printing found patchtt files
  {
    echo -e "\n\nFound the following patchtt files:"
    echo -e "************************************************"
    for patchtt in "${file_find[@]}" ; do
      echo -e "${patchtt}"
    done
    echo -e "************************************************"
  }  | tee -a "${output_file}"

  #Loop on found patchtt.tt2 files to check if they can still apply
  {
    echo -e "\nChecking if patchtt files can be automatically applied to the new templates\n"
  } | tee -a "${output_file}"
  for patchtt in "${file_find[@]}" ; do
    not_exist=""

    #set +e
    file_counter=$((file_counter + 1))
    echo -e "***${file_counter}***" | tee -a "${output_file}"

    #If there is a more specific tt2 file (i.e. tt2.sp1, tt2.web01, etc...), we need to compare the patchtt with that one
    original="${patchtt/patchtt.tt2/tt2}"
    if [ ! -f "${original}" ]; then
      not_exist="Note: The specific template '${original}' does not exist in /etc/ngcp-config!"
      original="${patchtt/patchtt.tt2*/tt2}"
      echo -e "${not_exist}\n" | tee -a "${output_file}"
      echo -e "${patchtt} cannot be applied without a default tt2 file. Take care of this!\n" | tee -a "${output_file}"
      failed_patchtt=true
    elif patch "${patch_opts[@]}" "${tmp_tt2_dir}${original}" "${patchtt}" >> "${error_file}"; then
      echo -e "${patchtt} would be successfully applied\n"  | tee -a "${output_file}"
    else
      echo -e "${patchtt} cannot be applied to the new template file. Take care of this!" | tee -a "${output_file}"
      failed_patchtt=true
    fi

    #set -e
  done

  #Append patchtt files to the tar archive
  echo -e "\nAppending the tar archive with the patchtt files"
  echo -e "************************************************"

  # shellcheck disable=SC2261
  tar -rf "${archive_file}" "${file_find[@]}" 2>> "${error_file}" 2>/dev/null
}


summarize_results() {
  #Summarizing results
  echo -e "\nExecution completed"
  echo -e "************************************************"
  if [ -f "${output_file}" ]; then
    echo -e "Output file: ${output_file}"
  fi
  if [ -f "${error_file}" ]; then
    echo -e "Error file: ${error_file}"
  fi
  if [ -f "${archive_file}" ]; then
    echo -e "Archive file: ${archive_file}\n"
  fi
  if ${failed_patchtt} ; then
    echo -e "\033[1;31mERROR: One or more 'patchtt' cannot be properly applied to the new template file.\033[0m"
    echo -e "\033[1;31mERROR: Please check the error file: ${error_file}\033[0m"
  fi
  return 0
}

download_target_release() {
  local tmp_deb_dir
  local package_name
  local repo
  local package_version

  #Download new tt2 files section
  echo -e "\nDownload new tt2 files"
  echo -e "************************************************"

  if ! "${check_patchtt}" ; then
    while true ; do
      read -r -p "What is your release target version (e.g. mr6.5.1) or template package target version (e.g. 6.5.1.1)? " choice_ver
      case "${choice_ver}" in
        [0-9\.]* )
          package_version=${choice_ver}
          choice_ver="mr${choice_ver%.*}"
          break;;
        mr* )
          break;;
        * )
          echo "Invalid choice. Enter target version, please";;
      esac
    done
  else
    choice_ver=${version}
  fi

  # shellcheck disable=SC1091
  . /etc/default/ngcp-roles
  if [ -z "${NGCP_TYPE}" ] ; then
    echo "Error: missing NGCP_TYPE in /etc/default/ngcp-roles, cannot continue!" >&2
    exit 1
  fi

  case "${NGCP_TYPE}" in
    spce )
      repo_path="https://deb.sipwise.com/spce/${choice_ver}/pool/main/n/ngcp-templates/"
      platform="ce"
      package="ce"
      ;;
    sppro|carrier )
      repo_path="https://deb.sipwise.com/sppro/${choice_ver}/pool/main/n/ngcp-templates/"
      platform="pro"
      package="pro"
      ;;
    * )
      echo "Error: wrong value of NGCP_TYPE in /etc/default/ngcp-roles, cannot continue!" >&2
      exit 1
  esac

  tmp_deb_dir=$(mktemp -d "/tmp/deb_${choice_ver}_temp.XXXXXX")
  tmp_tt2_dir=$(mktemp -d "/tmp/tt2_${choice_ver}_temp.XXXXXX")


  #Download tt2 for the target release
  cd "${tmp_deb_dir}"

  if ! wget -q --no-parent "${repo_path}" -O "ngcp-templates_all" ; then
    echo -e "ERROR: Failed to download packages from ${repo_path}"
    echo -e "Please check target version or the connection to the Sipwise repository.\n"
    exit 1
  fi

  (grep -Po '(?<=href=")[^"]*.deb' ngcp-templates_all | grep "${package}") > ngcp-templates_list
  if [ -z "${package_version}" ] ; then
    package_name=$(sort -uVr ngcp-templates_list | head -n1)
  else
    if [ ${platform} = ce ] ; then
      package_name="ngcp-templates-ce_${package_version}+0~mr${package_version}_all.deb"
    else
      package_name="ngcp-templates-pro_${package_version}+0~mr${package_version}_all.deb"
    fi
  fi

  repo="${repo_path}${package_name}"

  echo -e "\nDownloading package:  ${repo}"
  wget -q -nc "${repo}"


  #Extracting tt2 for the target release and platform
  echo -e "\nExtracting ${platform} package:  ${package_name} in ${tmp_tt2_dir}"
  dpkg -x "${package_name}" "${tmp_tt2_dir}"


  #Deleting debian temp folder
  rm -rf "${tmp_deb_dir}"

  #End
  echo -e "\nExtraction completed"
  echo -e "************************************************"
  echo -e "Check your brand new .tt2 for target ${NGCP_TYPE} release ${choice_ver} inside '${tmp_tt2_dir}'"
  echo -e ""

}


#main
case "$1" in
  -h|--help)
    help_menu
    ;;
  -t|--tar-new-customtt)
    get_new_customtts
    exit 0
    ;;
  -d|--download-target)
    download_target_release
    exit 0
    ;;
  -c|--check-patchtt)
    echo -e "\nChecking current patchtt against latest ${version} templates in preparation for the ngcp-update procedure."
    check_patchtt=true
    patchtt_helper
    summarize_results
    exit 0
    ;;
  "")
    customtt_helper
    patchtt_helper
    summarize_results
    exit 0
    ;;
  *)
    echo "Invalid Option. See '$0 --help'"
    exit 1
    ;;
esac

