#!/bin/bash

# NOTE: For methods below, they follow these rules:
# An exit code of 0 is considered success
# An exit code of 1 is considered error

# Flags "--check_asllrp" and "--check_outdated" will exit early after doing their respective checks

# set configurations
SIGNBANK_FN='globalSignBank.xml'
SIGNBANK_URL='http://dai.cs.rutgers.edu/SignBank/download/'"$SIGNBANK_FN"

SIGNBANK_LICENSE_FN='LICENSE-SignBank.txt'
SIGNBANK_LICENSE_URL='http://dai.cs.rutgers.edu/SignBank/'"$SIGNBANK_LICENSE_FN"

SIGNSTREAM_PROCESS_NAME='SignStream3'

ORIG_DIR="$( pwd )"

DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )"

INFO_FILE="$DIR"'/SignStream3.app/Contents/Resources/info.txt'
SIGNBANK_DIR="$DIR"'/SignStream3.app/Contents/Resources/signbank'

CMD="$( basename "$0" )"
PROCID="$$"

POST_3_0_0_BLANK_GLOBAL_SIGNBANK_FILE_CONTENTS="<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<SIGNBANK AUTHOR=\"\" DATE_CREATED=\"\" DATE_MODIFIED=\"\" REDIRECT=\"\"/>"

POST_3_2_10_BLANK_GLOBAL_SIGNBANK_FILE_CONTENTS="<?xml version='1.0' encoding='utf-8'?>\n<SIGNBANK DATA_VERSION='' SCHEMA_VERSION='' AUTHOR='' DATE_CREATED='' DATE_MODIFIED='' REDIRECT=''/>"

IS_CURRENTLY_BOSTON_FILE=false
  
SS3_WAS_RUNNING=`osascript -e 'tell application "System Events"
(get name of every application process) contains "'"$SIGNSTREAM_PROCESS_NAME"'"
end tell
'`

TERMINAL_NAME="$CMD""$PROCID"

set_terminal_name(){
  echo -n -e "\033]0;""$1""\007" # changes the running Terminal name for use when closing below
}


usage () {
  # Could add some more variations later if we want (i.e. --from_signstream3_update --noconfirm, etc..)
  echo "Usage: $0"
  echo "Usage: $0 --noconfirm"
  echo "Usage: $0 --autoclose"
  echo "Usage: $0 --from_signstream3_update"
  echo "Usage: $0 --check_asllrp"
  echo "Usage: $0 --check_outdated"
  echo "Usage: $0 --uninstall"
}

close() {
  echo ""

  if [ -e "$ORIG_DIR" ]; then
    cd "$ORIG_DIR"
  fi

  if [ "x""$AUTOCLOSE" != 'xtrue' ]; then
    echo "You can now close this window (click 'X', or press enter, to close)."
    read junk
  fi

  if [ "x""FROM_SS3_UPDATE" != 'xtrue' ]; then
    $( while pgrep -f "$CMD" | grep '^'"$PROCID"'$' &>/dev/null; do sleep 1; done; osascript -e 'tell application "Terminal" to close (first window whose name contains "'"$TERMINAL_NAME"'")' &> /dev/null ) &
  fi

  exit $1
}

#defaults and usage
CONFIRMED='false'
AUTOCLOSE='false'
FROM_SS3_UPDATE='false'
CHECK_ASLLRP='false'
CHECK_OUTDATED='false'
UNINSTALL='false'

if [ "x""$1" == "x" ]; then
  set_terminal_name "$TERMINAL_NAME"
elif [ "x""$1" == "x--noconfirm" ]; then
  set_terminal_name "$TERMINAL_NAME"
  CONFIRMED='true'
elif [ "x""$1" == "x--autoclose" ]; then
  set_terminal_name "$TERMINAL_NAME"
  AUTOCLOSE='true'
elif [ "x""$1" == "x--from_signstream3_update" ]; then
  FROM_SS3_UPDATE='true'
  AUTOCLOSE='true'
elif [ "x""$1" == "x--check_asllrp" ]; then
  CHECK_ASLLRP='true'
  AUTOCLOSE='true'
elif [ "x""$1" == "x--check_outdated" ]; then
  CHECK_OUTDATED='true'
  AUTOCLOSE='true'
elif [ "x""$1" == "x--uninstall" ]; then
  set_terminal_name "$TERMINAL_NAME"
  UNINSTALL='true'
else
  set_terminal_name "$TERMINAL_NAME"
  echo "Error in usage: $@"
  echo ""
  usage
  close
fi

# from https://stackoverflow.com/questions/4023830/how-to-compare-two-strings-in-dot-separated-version-format-in-bash
# $1 > $2 : return 1
# $1 = $2 : return 0
# $1 < $2 : return 2
vercomp() {
    if [[ "x""$1" == "x""$2" ]]
    then
        return 0
    fi
    local IFS=.
    local i ver1=($1) ver2=($2)
    # fill empty fields in ver1 with zeros
    for ((i=${#ver1[@]}; i<${#ver2[@]}; i++))
    do
        ver1[i]=0
    done
    for ((i=0; i<${#ver1[@]}; i++))
    do
        if [[ -z ${ver2[i]} ]]
        then
            # fill empty fields in ver2 with zeros
            ver2[i]=0
        fi
        if ((10#${ver1[i]} > 10#${ver2[i]}))
        then
            return 1
        fi
        if ((10#${ver1[i]} < 10#${ver2[i]}))
        then
            return 2
        fi
    done
    return 0
}

# verbetween 1 0 3: return 4
# verbetween 1 1 3: return 2
# verbetween 1 2 3: return 0
# verbetween 1 3 3: return 1 
# verbetween 1 4 3: return 3
verbetween() {
  vercomp "$1" "$3"
  if [[ "$?" -eq 1 ]]; then
    min="$3"
    max="$1"
  else
    min="$1"
    max="$3"
  fi
 vercomp "$min" "$2"
  if [[ "$?" -eq 1 ]]; then
    return 4
  elif [[ "$?" -eq 0 ]]; then
    return 2 
  elif [[ "$?" -eq 2 ]]; then
    vercomp "$2" "$max"
    if [[ "$?" -eq 2 ]]; then
      return 0
    elif [[ "$?" -eq 0 ]]; then
      return 1
    else
      return 3
    fi
  fi
}

cleanup() {
  echo ""
  echo "Cleaning up signbank files..."
  if [[ -f "$SIGNBANK_LICENSE_FN"'.latest' ]]; then
    rm -f "$SIGNBANK_LICENSE_FN"'.latest'
  fi
  if [[ -f "$SIGNBANK_FN"'.latest' ]]; then
    rm -f "$SIGNBANK_FN"'.latest'
  fi
  echo "Done."
  echo ""
}

error() {
  cleanup
  echo "$1"
  if [ "x""FROM_SS3_UPDATE" != 'xtrue' ]; then
    echo "Exiting..."
  fi
  echo ""
  close 1 # exit code 1 means an error occurred
}

get_current_version() {
  CURRENT_VERSION=$( sed -n 's/app_version \(.*\)$/\1/p' "$INFO_FILE" )
}

delete_signbank() {
  quit_signstream

  cd "${DIR}"
  echo "Deleting existing Boston University ASLLRP Sign Bank..."

  get_current_version

  verbetween "3.0.0" "$CURRENT_VERSION" "3.2.10"
  if [[ "$?" -eq 2 || "$?" -eq 0 ]]; then # 3.0.0<=$DEST_VERSION<3.2.10
    echo -e $POST_3_0_0_BLANK_GLOBAL_SIGNBANK_FILE_CONTENTS > signbank/$SIGNBANK_FN
  fi

  verbetween "3.2.10" "$CURRENT_VERSION" "3.3.0"
  if [[ "$?" -eq 2 || "$?" -eq 0 ]]; then # 3.2.10<=$DEST_VERSION<3.3.0
    echo -e $POST_3_2_10_BLANK_GLOBAL_SIGNBANK_FILE_CONTENTS > signbank/$SIGNBANK_FN
  fi

  echo "Done."
  echo ""

  reopen_signstream
}

# Only option provided here will be to uninstall (i.e. delete the global sign bank contents)
uninstall() {
  if [ "x""$UNINSTALL" == 'xtrue' ]; then
    echo ""
    echo "You have chosen to uninstall your current ASLLRP global Sign Bank. Is this correct?"
    echo ""
    echo "If you answer yes: if you already had the ASLLRP global Sign Bank installed it will be deleted."
    echo "If you answer no: nothing will occur."
    echo "This will not affect your local Sign Bank file, if you have been maintaining one."
    echo ""
    echo "(Please answer yes or no)"

    while true; do
      read -p "" yn
      if [[ "$yn" =~ ^(Y|y|YES|Yes|yes)$ ]]; then
        echo "You answered yes. Your current Boston University ASLLRP Sign Bank will now be deleted."
        delete_signbank
        break;
      elif [[ "$yn" =~ ^(N|n|NO|No|no)$ ]]; then
        echo "You answered no. Exiting..."
        break;
      else
        echo "Please answer yes or no.";
      fi
    done

    cleanup
    close
  
  fi
}

ask_update() {
  # First before doing anything, if coming from another script and FROM_SS3_UPDATE was passed, ask the user whether they want to even check for a sign bank update from Boston - if they say no then exit
  if [ "x""$FROM_SS3_UPDATE" == 'xtrue'  ]; then
    echo ""
    echo "Do you wish to (continue to) use the ASLLRP global Sign Bank?"
    echo ""
    echo "If you answer yes: the Boston University ASLLRP Sign Bank will now be installed/updated to the latest version (after you agree to the terms of use)."
    echo "If you answer no: if you already had the ASLLRP global Sign Bank installed it will be deleted."
    echo "This will not affect your local Sign Bank file, if you have been maintaining one."
    echo ""
    echo "(Please answer yes or no)"

    while true; do
      read -p "" yn
      if [[ "$yn" =~ ^(Y|y|YES|Yes|yes)$ ]]; then
        echo "Checking for new version now... Please wait.";
        break;
      elif [[ "$yn" =~ ^(N|n|NO|No|no)$ ]]; then 
        echo "You answered no. Your current Boston University ASLLRP Sign Bank will now be deleted."
        delete_signbank
        break;
      else
        echo "Please answer yes or no.";
      fi
    done

    if [[ "$yn" =~ ^(N|n|NO|No|no)$ ]]; then 
      cleanup
      close
    fi

  fi
}

# Check whether the current sign bank file is authored by Boston University (ASLLRP)
check_asllrp() {
  LOCAL_SIGNBANK_AUTHOR=`head -n 2 $SIGNBANK_FN | tail -n 1 | grep AUTHOR |  sed "s/.*AUTHOR='\([^']*\)'.*/\1/"`
  if [ "$LOCAL_SIGNBANK_AUTHOR" == "BOSTON UNIVERSITY" ]; then
    IS_CURRENTLY_BOSTON_FILE=true
    echo "Global Sign Bank file is currently ASLLRP"
  else
    echo "Global Sign Bank file is NOT currently ASLLRP"
  fi
  
  if [[ "x""$CHECK_ASLLRP" == 'xtrue' ]]; then
    if [ "x""$IS_CURRENTLY_BOSTON_FILE" == 'xtrue' ]; then
      exit 0
    else
      exit 1
    fi
  else
    if [ "x""$IS_CURRENTLY_BOSTON_FILE" == 'xtrue' ]; then
      return 0
    else
      return 1
    fi
  fi
}

# Check whether a new sign bank data version is available
check_outdated() {
  check_asllrp
  
  REMOTE_HEADER=$(curl -m 5 --range 0-2000 --silent --write-out "\nHTTPSTATUS:%{http_code}" "$SIGNBANK_URL")
  if ! ( [ "x""$(echo "$REMOTE_HEADER" | grep '^HTTPSTATUS:'  | sed -e 's/HTTPSTATUS://')" == "x200" ] ||
         [ "x""$(echo "$REMOTE_HEADER" | grep '^HTTPSTATUS:'  | sed -e 's/HTTPSTATUS://')" == "x206" ] ); then
    error "Unable to download the latest version of the Global Sign Bank. Please check your internet connection."
  fi
  
  REMOTE_DATA_VERSION=`echo "$REMOTE_HEADER" | head -n 2 | tail -n 1 | grep DATA_VERSION |  sed "s/.*DATA_VERSION='\([^']*\)'.*/\1/"`
  LOCAL_DATA_VERSION=`head -n 2 "$SIGNBANK_FN" | tail -n 1 | grep DATA_VERSION |  sed "s/.*DATA_VERSION='\([^']*\)'.*/\1/"`
  
  REMOTE_SCHEMA_VERSION=`echo "$REMOTE_HEADER" | head -n 2 | tail -n 1 | grep SCHEMA_VERSION | sed "s/.*SCHEMA_VERSION='\([^']*\)'.*/\1/"`
  LOCAL_SCHEMA_VERSION=`sed -n 's/signbank_schema_max_version \(.*\)$/\1/p' "$INFO_FILE"`
  
  if [ "x""$LOCAL_SCHEMA_VERSION" == "x" ]; then
    LOCAL_SCHEMA_VERSION="0.0"
  fi
  
  vercomp "$REMOTE_SCHEMA_VERSION" "$LOCAL_SCHEMA_VERSION"
  if [[ "$?" -eq 1 ]]; then # signstream update needed
    error "Your current schema version of SignStream3 ($LOCAL_SCHEMA_VERSION) is unable to parse the latest sign bank file ($REMOTE_SCHEMA_VERSION). Please update SignStream3 and then try again."
  fi
  
  if [ "x""$IS_CURRENTLY_BOSTON_FILE" == 'xfalse' ] || [ "x"$LOCAL_DATA_VERSION == "x" ] || [ ! $LOCAL_DATA_VERSION ]; then
    echo "No current Boston University ASLLRP Sign Bank detected on your system."
  else
    if [ "x""$REMOTE_DATA_VERSION" == "x" ]; then
      error "Can not determine the new Global Sign Bank data version."
    else
    
      echo "The signbank is currently on data version $LOCAL_DATA_VERSION and schema version $LOCAL_SCHEMA_VERSION"
      echo "The new signbank is on data version $REMOTE_DATA_VERSION and schema version $REMOTE_SCHEMA_VERSION"
  
      vercomp "$REMOTE_DATA_VERSION" "$LOCAL_DATA_VERSION"
      if [[ "$?" -eq 1 ]]; then # sign bank update needed
          echo "A newer data version ($REMOTE_DATA_VERSION) is available."
      else
        error "This is already the latest data version, so there is nothing to do."
      fi
    fi
  fi
  
  if [[ "x""$CHECK_OUTDATED" == "xtrue" ]]; then
    exit 0 # No need for the exit 1 condition - handled by error statements in previous block
  else
    return 0
  fi
  
  return 1
}

download_license(){
  if ! [ -f "$SIGNBANK_LICENSE_FN"'.latest' ]; then
    # download new files
    echo "Downloading Sign Bank License...Please wait."

    SIGNBANK_LICENSE_REQUEST=$(curl --silent --write-out "\nHTTPSTATUS:%{http_code}" --output "$SIGNBANK_LICENSE_FN"'.latest' "$SIGNBANK_LICENSE_URL")
    if [ "x""$(echo "$SIGNBANK_LICENSE_REQUEST" | grep '^HTTPSTATUS:'  | sed -e 's/HTTPSTATUS://')" != "x200" ]; then
      error "Unable to download the latest version of the Global Sign Bank License. Please check your internet connection."
    fi

    echo "Done."
    echo ""
  fi
}

accept_license() {

  download_license

  if [[ "$CONFIRMED" != "true" ]]; then
    # get acceptance on terms
    echo "Terms of Use for the ASLLRP Sign Bank."
    echo ""
    echo "------------------------------------------------------------"
    cat "$SIGNBANK_LICENSE_FN"'.latest' 
    echo "------------------------------------------------------------"
    echo ""
    echo "Do you accept these terms of use? (Please answer yes or no)"
    if [ "x""$IS_CURRENTLY_BOSTON_FILE" == 'xtrue' ]; then
      echo "PLEASE NOTE!!! If you answer no: your current Boston University ASLLRP Sign Bank will be deleted."
    fi

    while true; do
      read -p "" yn
      if [[ "$yn" =~ ^(Y|y|YES|Yes|yes)$ ]]; then
        echo "Installing files... Please wait.";
        break;
      elif [[ "$yn" =~ ^(N|n|NO|No|no)$ ]]; then 
        if [[ "x""$IS_CURRENTLY_BOSTON_FILE" == 'xtrue' ]]; then
          echo "You answered no. Your current Boston University ASLLRP Sign Bank will now be deleted."
          delete_signbank
        else
          echo "You answered no. The Sign Bank will NOT update."
        fi
        break;
      else
        echo "Please answer yes or no.";
      fi
    done

    if [[ "$yn" =~ ^(N|n|NO|No|no)$ ]]; then 
      cleanup
      close
    fi
  fi
}

download_signbank() {
  if ! [ -f "$SIGNBANK_FN"'.latest' ]; then
    # download new files
    echo "Downloading Sign Bank file...Please wait."

    SIGNBANK_REQUEST=$(curl --silent --write-out "\nHTTPSTATUS:%{http_code}" --output "$SIGNBANK_FN"'.latest' "$SIGNBANK_URL")
    if [ "x""$(echo "$SIGNBANK_REQUEST" | grep '^HTTPSTATUS:'  | sed -e 's/HTTPSTATUS://')" != "x200" ]; then
      error "Unable to download the latest version of the Global Sign Bank. Please check your internet connection."
    fi
    echo "Done."
    echo ""
  fi
}

quit_signstream() {
  if [ "x""$SS3_WAS_RUNNING" == 'xtrue' ]; then
    echo -e "Closing SignStream to Update... (You may be asked to save changes before closing)\n"
    #Close SignStream
    osascript -e 'quit app "SignStream3"'
  fi
}

reopen_signstream() {
  cd "${DIR}" 
  if [ "x""$SS3_WAS_RUNNING" == 'xtrue' ]; then
    echo ""
    echo "Relaunching SignStream3..."
    open -g "./SignStream3.app"
    echo "Done."
    echo ""
  fi
}

do_update() {
  echo "Starting update process..."
    
  accept_license

  quit_signstream
  
  download_signbank

  # TODO: verify with checksum; currently only checks if files were actually downloaded
  if [ ! -e "$SIGNBANK_FN"'.latest' -o ! -e "$SIGNBANK_LICENSE_FN"'.latest' ]; then
    error "Files were not downloaded"
  fi
        
  # remove the ".latest" at end of all files
  mv "$SIGNBANK_LICENSE_FN"'.latest' "$SIGNBANK_LICENSE_FN"
  mv "$SIGNBANK_FN"'.latest' "$SIGNBANK_FN"

  echo "Successfully updated the signbank."

  reopen_signstream
}

main() {

  cd "${DIR}"
  
  uninstall
  
  ask_update
  
  # change to the signbank directory
  cd signbank
  
  check_outdated # check_outdated calls check_asllrp
  
  # If we have gotten this far, we know we want to do the update
  do_update
  
  close

}

main
