#!/bin/bash

#$1 is an action, like install
#$2 is app name, like Arduino

DIRECTORY="$(readlink -f "$(dirname "$0")")"

function error {
  echo -e "\e[91m$1\e[39m"
  exit 1
}

if [ -z "$1" ];then
  error "You need to specify an operation, and in most cases, which app to operate on."
fi

mkdir -p "${DIRECTORY}/data/status"

if [ "$1" == 'install' ];then
  #INSTALL
  #for this operation, a program name must be specified.
  if [ -z "$2" ];then
    error "For this operation, you must specify which app to operate on."
  elif [ ! -d "${DIRECTORY}/apps/$2" ];then
    error "${DIRECTORY}/apps/$2 does not exist!"
  fi
  #ensure an install script is not already running
  if ps -C install ;then       
    echo "An install script is already running.
Pi-Apps will wait until that one finishes before installing $2." | yad --text-info \
    --title="Waiting" --window-icon="${DIRECTORY}/icons/logo.png" --center --width=500 --height=100 \
    --button=OK!"${DIRECTORY}/icons/check.png":0 --fontname=12 --timeout=10 --timeout-indicator=top
    while ps -C install ;do sleep 1; done
  fi
  
  #if already installed then ask for confirmation
  if [ "$(cat "${DIRECTORY}/data/status/${2}" )" == 'installed' ];then
    yad --text="$2 is already installed. Are you sure you want to install it again?" \
    --text-align=center --center --title='Quick question' --window-icon="${DIRECTORY}/icons/logo.png" \
    --button=No!"${DIRECTORY}/icons/exit.png":1 --button=Yes!"${DIRECTORY}/icons/check.png":0 || exit 0
  fi
  
  lxterminal --title="Installing $2" -e "
    cd $HOME
    echo 'corrupted' > \"${DIRECTORY}/data/status/${2}\"
    if \"${DIRECTORY}/apps/${2}/install\" ; then
      echo 'installed' > \"${DIRECTORY}/data/status/${2}\"
      echo -en '\n\e[42m\e[30mCommand succeeded.\e[39m\e[49m\nClosing in 10 seconds.'
      sleep 10
    else
      echo 'corrupted' > \"${DIRECTORY}/data/status/${2}\"
      echo -en '\n\e[41m\e[30mCommand failed!\e[39m\e[49m\nClose this window to exit.'
      read enter #technically you could press Enter to exit.
    fi"
  #wait until script is done before this command exits
  sleep 2
  while ps -C install >/dev/null;do sleep 1; done
  
elif [ "$1" == 'uninstall' ];then
  #UNINSTALL
  #for this operation, a program name must be specified.
  if [ -z "$2" ];then
    error "For this operation, you must specify which app to operate on."
  elif [ ! -d "${DIRECTORY}/apps/$2" ];then
    error "${DIRECTORY}/apps/$2 does not exist!"
  fi
  #ensure an uninstall script is not already running
  if ps -C uninstall ;then       
    echo "An uninstall script is already running.
Pi-Apps will wait until that one finishes before starting this one." | yad --text-info \
    --title="Waiting" --window-icon="${DIRECTORY}/icons/logo.png" --center --width=500 --height=100 \
    --button=OK!"${DIRECTORY}/icons/check.png":0 --fontname=12 --timeout=10 --timeout-indicator=top
    while ps -C uninstall ;do sleep 1; done
  fi
  
  #if already uninstalled then ask for confirmation
  if [ "$(cat "${DIRECTORY}/data/status/${2}" )" == 'uninstalled' ];then
    yad --text="$2 is already uninstalled. Are you sure you want to uninstall it again?" \
    --text-align=center --center --title='Quick question' --window-icon="${DIRECTORY}/icons/logo.png" \
    --button=No!"${DIRECTORY}/icons/exit.png":1 --button=Yes!"${DIRECTORY}/icons/check.png":0 || exit 0
  fi
  
  lxterminal --title="Uninstalling $2" -e "
    cd $HOME
    echo 'corrupted' > \"${DIRECTORY}/data/status/${2}\"
    if \"${DIRECTORY}/apps/${2}/uninstall\" ; then
      echo 'uninstalled' > \"${DIRECTORY}/data/status/${2}\"
      echo -en '\n\e[42m\e[30mCommand succeeded.\e[39m\e[49m\nClosing in 10 seconds..'
      sleep 10
    else
      echo 'corrupted' > \"${DIRECTORY}/data/status/${2}\"
      echo -en '\n\e[41m\e[30mCommand failed!\e[39m\e[49m\nClose this window to exit.'
      read enter #technically you could press Enter to exit.
    fi"
  #wait until script is done before this command exits
  sleep 2
  while ps -C uninstall >/dev/null;do sleep 1; done
elif [ "$1" == 'update' ];then
  #UPDATE
  #for this operation, a program name must be specified.
  if [ -z "$2" ];then
    error "For this operation, you must specify which app to operate on."
  fi
  
  #HIDDEN FEATURE - if $3 equals nofetch, then don't download github repo. Useful for updating multiple apps at maximum speed
  if [ "$3" == 'nofetch' ] && [ -d "${DIRECTORY}/update" ];then
    true
  else
    rm -rf "${DIRECTORY}/update" && mkdir "${DIRECTORY}/update" && cd "${DIRECTORY}/update" || error "failed to enter the update directory!"
    git clone https://github.com/Botspot/pi-apps || error "failed to clone repository!"
  fi
  
  newhash=$(find "${DIRECTORY}/update/pi-apps/apps/${2}" -type f -print0  | xargs -0 sha1sum | awk '{print $1}' | sha1sum | awk '{print $1}')
  oldhash=$(find "${DIRECTORY}/apps/${2}" -type f -print0  | xargs -0 sha1sum | awk '{print $1}' | sha1sum | awk '{print $1}')
  
  echo -e "newhash: $newhash\noldhash: $oldhash"
  
  if [ "$newhash" == "$oldhash" ];then
    echo "$2 is identical to the online version. Nothing to do!"
    exit 0
  else
    echo "$2 is not identical to the online version. Reinstalling..."
  fi
  #else
  #if installed already
  if [ "$(cat "${DIRECTORY}/data/status/${2}")" == 'installed' ];then
    installback=yes
    #uninstall it using a recursive script instance
    "${DIRECTORY}/manage" uninstall "$2"
  else
    installback=no
  fi
  
  #move old program to trash
  gio trash "${DIRECTORY}/apps/${2}" 2>/dev/null
  
  #failsafe
  [ -d "${DIRECTORY}/apps/${2}" ] && error "${DIRECTORY}/apps/${2} still exists, despite trying to delete it!"
  
  #copy new version to apps/
  cp -rf "${DIRECTORY}/update/pi-apps/apps/${2}" "${DIRECTORY}/apps/${2}"
  
  if [ "$installback" == 'yes' ];then
    echo "$2 was originally installed before updating. Reinstalling the new version now."
    #install it using a recursive script instance
    "${DIRECTORY}/manage" install "$2"
  fi
  echo -e '\e[92m${2} was updated successfully.\e[39m'
elif [ "$1" == 'check-all' ];then
  #CHECK-ALL
  #for this operation, a program name cannot be specified.
  
  rm -rf "${DIRECTORY}/update" && mkdir "${DIRECTORY}/update" && cd "${DIRECTORY}/update" || error "failed to enter the update directory!"
  git clone https://github.com/Botspot/pi-apps || error "failed to clone repository!"
  
  updatable=''

  PREIFS="$IFS"
  IFS="|"
  newapps="$(echo -e "$(ls "${DIRECTORY}/update/pi-apps/apps")\n$(ls "${DIRECTORY}/apps")" | grep -v 'template' | sort | uniq | tr '\n' '|')"
  for newapp in $newapps
  do
    #echo "newapp: $newapp"
    newhash=$(find "${DIRECTORY}/update/pi-apps/apps/${newapp}" -type f -print0 2>/dev/null | xargs -0 sha1sum | awk '{print $1}' | sha1sum | awk '{print $1}')
    oldhash=$(find "${DIRECTORY}/apps/${newapp}" -type f -print0 2>/dev/null | xargs -0 sha1sum | awk '{print $1}' | sha1sum | awk '{print $1}')
    #echo -e "newhash: $newhash\noldhash: $oldhash"
    
    if [ "$newhash" == "$oldhash" ];then
      echo -e "${newapp} is identical\e[90m to the online version. Nothing to do!\e[39m"
      echo 'latest' > "${DIRECTORY}/data/update-status/${newapp}"
    else
      if [ ! -d "${DIRECTORY}/apps/${newapp}" ];then
        echo -e "\e[97m${newapp} does not exist locally.\e[39m Adding to updatable list."
        echo 'new' > "${DIRECTORY}/data/update-status/${newapp}"
        #in this case, add to updatable list
        updatable="${updatable}|${newapp}"
      elif [ ! -d "${DIRECTORY}/update/pi-apps/apps/${newapp}" ];then
        echo -e "\e[97m${newapp} only exists locally.\e[39m Will not add to updatable list."
        echo 'local' > "${DIRECTORY}/data/update-status/${newapp}"
        #in this case, do not add to updatable list
      else
        echo -e "\e[97m${newapp} exists in both locations, but online version is newer\e[39m. Adding to updatable list."
        echo 'updatable' > "${DIRECTORY}/data/update-status/${newapp}"
        #in this case, add to updatable list
        updatable="${updatable}|${newapp}"
      fi
      
    fi
  done 
  IFS="$PREIFS"
  
  #remove initial '|' character
  updatable="${updatable:1}"
  
  echo -e "\e[97mThese apps can be updated:\n${updatable}"
elif [ "$1" == 'update-all' ];then
  #UPDATE-ALL
  #for this operation, a program name cannot be specified.
  PREIFS="$IFS"
  IFS='|'
  updatable="$("${DIRECTORY}/manage" check-all | tail -1)"
  echo "Updatable: ${updatable}EOU"
  for updateapp in $updatable
  do
    echo "updating $updateapp"
    #update it using a recursive script instance
    echo "${DIRECTORY}/manage update $updateapp"
    "${DIRECTORY}/manage" update "$updateapp" || exit 1
  done 
  IFS="$PREIFS"
  echo -e '\e[92mOperation completed successfully!\e[39m'
else
  error "Did not understand ${1}. It must be either "\'"install"\'", "\'"uninstall"\'", "\'"update"\'", "\'"check-all"\'", or "\'"update-all"\'"."
fi