#!/bin/bash

tkis_upgrade(){
  local program_name=$1
  local version=$2
  local rule_name=$3
  local subversion=$(echo $version | grep -o "^[[:alnum:]_-]*\.[[:alnum:]_-]*\.[[:alnum:]_-]*")
  local micversion=$(echo $version | grep -o "^[[:alnum:]_-]*\.[[:alnum:]_-]*")
  local majversion=$(echo $version | grep -o "^[[:alnum:]_-]*")
  local start_time_day=
  local start_time_hour=
  local start_time_minute=
  local start_time_second=

  let start_time_second=$(date --utc +%-S)
  let start_time_minute=$(date --utc +%-M)
  let start_time_hour=$(date --utc +%-H)
  let start_time_day=$(date --utc +%-d)

  push_to_null .

  if [ -f ${SE}settings-$list_filename ] ; then
    debug "Loading local settings file: ${SE}settings-$list_filename"
    tkis_source_file ${SE}settings-$list_filename
  else
    debug "${SE}settings-$list_filename doest not exist or cannot be accessed"
  fi

  debug "Looking for ignore system_versions: \"$(fss_basic_list_read -c 0 -n $tkis_process $SY$list_filename  | grep -s '^ignore system_versions[[:space:]]*$')\""
  if [[ $(fss_basic_list_read -c 0 -n $tkis_process $SY$list_filename  | grep -s "^ignore system_versions[[:space:]]*$") == "ignore system_versions" ]] ; then
    debug "Instructing program to disregard the systems version file"
    tkis_ignore_system_version="yes"
  fi

  debug "Looking for running_on_host: \"$(fss_basic_list_read -c 0 -n $tkis_process $SY$list_filename  | grep -s '^running_on_host[[:space:]]*$')\""
  if [[ $(fss_basic_list_read -c 0 -n $tkis_process $SY$list_filename  | grep -s "^running_on_host[[:space:]]*$") == "running_on_host" ]] ; then
    debug "Setting security precautions in place to protect the host system from damage"
    tkis_running_on_host="yes"
    tkis_ignore_system_version="yes"
  fi

  if [[ $program_name == "" ]] ; then
    error "tkis_upgrade(): Missing rule file parameter"
  fi

  if [ -f $tkis_local_error.$program_name ] ; then
    error "tkis_upgrade(): The local error file: $color_reset$color_notice$tkis_local_error.$program_name$color_error exists. Fix the problem then delete the local error file to continue"
  fi

  if ! [ -f $RU$list_filename/$program_name ] ; then
    error "tkis_upgrade(): The rule $color_reset$color_notice$RU$list_filename/$program_name$color_error is missing or cannot be accessed" 
  fi

  if [[ $(grep -s "^[[:space:]]*$version:[[:space:]]*$" $RU$list_filename/$program_name) != "" ]] ; then
    debug "It looks like $version is not the version, but instead a rule_name and will therefore be treated as one"

    if [[ $rule_name != "" ]] ; then
      error "tkis_upgrade(): $color_reset$color_notice$rule_name$color_reset$color_error is already defined as $color_reset$color_notice$version"
    fi

    rule_name=$version
    version=
  fi

  debug "version=$version"

  if [[ $version == "" ]] ; then
    debug "version was not passed, obtaining default version for $program_name for $tkis_process"
    tkis_get_version $program_name

    if ! [ $? -eq 0 ] ; then
      error "tkis_upgrade(): $color_reset$color_noticetkis_get_version $program_name$color_error failed for some reason"
    fi
  else
    VERSION=$version
    tkis_process_version
  fi

  version=$VERSION
  subversion=$SUBVERSION
  micversion=$MICVERSION
  majversion=$MAJVERSION
  unset VERSION
  unset SUBVERSION
  unset MICVERSION
  unset MAJVERSION

  if [[ $rule_name == "" ]] ; then
    debug "rule_name was not passed, defaulting to: main"
    rule_name="main"
  fi

  if [ -f $system_version_file ] ; then
    local system_version=$(fss_basic_read -c 0 -n $program_name $system_version_file)
  else
    local system_version=
  fi

  if [[ $system_version != "" ]] ; then
    notice "System version $color_reset$color_notice$system_version$color_reset$color_highlight, Upgrade Version: $color_reset$color_notice$version"
  fi

  # now extract the archive
  tkis_extract $program_name $version

  if ! [ $? -eq 0 ] ; then
    error "tkis_upgrade(): $color_reset${color_notice}tkis_extract $program_name $version$color_error failed for some reason"
  fi

  # change into our archive now
  debug "Going into the directory: ${WO}$program_name-$version"

  # change into our archive now
  if [ -f ${tkis_data}$tkis_process.last_directory.$program_name ] ; then
    if [ ! -d $(cat ${tkis_data}$tkis_process.last_directory.$program_name) ] ; then
      error "tkis_upgrade(): The directory '$color_reset${color_notice}$(cat ${tkis_data}$tkis_process.last_directory.$program_name)$color_reset${color_error}' does not exist or cannot be accessed, unable to change directory as requested by $color_reset$color_notice$rule_name"
    fi

    debug "Going into the directory: $(cat ${tkis_data}$tkis_process.last_directory.$program_name)"
    push_to_null $(cat ${tkis_data}$tkis_process.last_directory.$program_name)
  else
    debug "Going into the directory: ${WO}$program_name-$version"
    push_to_null ${WO}$program_name-$version

      if [[ $? -ne 0 ]] ; then
        debug "Previous directory change failed, now trying: ${WO}$program_name$version"
        push_to_null ${WO}$program_name$version

        if [[ $? -ne 0 ]] ; then
          debug "Previous directory change failed, now trying: ${WO}$program_name.$version"
          push_to_null ${WO}$program_name.$version

          if [[ $? -ne 0 ]] ; then
            debug "Previous directory change failed, now trying: ${WO}$program_name"
            push_to_null ${WO}$program_name
          fi
        fi
      fi
  fi

  debug "executing: tkis_handle_patches $program_name $version $subversion"
  tkis_handle_patches $program_name $version $subversion

  # prepare to parse list
  local current=0
  local current_line=
  local current_word=
  local list_size=

  # prepare to execute the rules
  debug "Loading List Size: fss_basic_list_read -c 0 -s -n $rule_name ${RU}$list_filename/$program_name"
  list_size=$(fss_basic_list_read -c 0 -s -n $rule_name ${RU}$list_filename/$program_name)

  debug "Loading list to check for non-whitespace: fss_basic_list_read -c 0 -n $rule_name ${RU}$list_filename/$program_name"
  LIST_DATA=$(fss_basic_list_read -c 0 -n $rule_name ${RU}$list_filename/$program_name)

  # now check for non-whitespaces
  if [[ $list_size -le 0 || $LIST_DATA == "" ]] ; then
    error "tkis_upgrade(): There is no data in the list $color_reset$color_notice$rule_name$color_reset$color_error from the file $color_reset$color_notice${RU}$list_filename/$program_name"
  fi

  unset LIST_DATA LIST_NAME LIST_SIZE LIST_TOTAL

  if [[ -f $tkis_resume_rule.$program_name ]] ; then
    current=$(cat $tkis_resume_rule.$program_name)

    # attempt to identify a corrupt/invalid resume file
    local weird=$(echo $(cat $tkis_resume_rule.$program_name) | sed -e 's|0||g' -e 's|1||g' -e 's|2||g' -e 's|3||g' -e 's|4||g' -e 's|5||g' -e 's|6||g' -e 's|7||g' -e 's|8||g' -e 's|9||g')

    # on invalid/corrupt data start from the top
    if [[ $current == "" || $weird != "" ]] ; then
      warning "$color_reset$color_notice$tkis_resume_rule.$program_name$color_reset$color_warning was found but is corrupt or contains invalid data: $color_reset$color_notice$current$color_reset$color_warning; execution will start from the top instead of resuming"
      rm -f $tkis_resume_rule.$program_name
      current=0
    elif [[ $current -lt 0 || $current -ge $list_size ]] ; then
      warning "$color_reset$color_notice$tkis_resume_rule.$program_name$color_reset$color_warning was found but contains invalid resume position: $color_reset$color_notice$current$color_reset$color_warning; execution will start from the top instead of resuming"
      rm -f $tkis_resume_rule.$program_name
      current=0
    fi
  fi

  # make sure LIST_LINE is reset
  LIST_LINE=

  debug "Rule is resuming/starting on line #$current"
  while [ $current -lt $list_size ] ; do
    debug "obtaining list line #$current, \"$rule_name\", \"${RU}$list_filename/$program_name\""
    LIST_DATA=$(fss_basic_list_read -c 0 -l $current -n $rule_name ${RU}$list_filename/$program_name)
    current_line=$LIST_DATA

    # for security purposes, remove these variables before executing bash code
    unset LIST_DATA LIST_NAME LIST_SIZE LIST_TOTAL

    if [[ $(echo $current_line | sed -e 's|[[:space:]]||g') != "" ]] ; then
      tkis_execute "$current_line"

      if ! [ $? -eq 0 ] ; then
        error "tkis_upgrade(): $color_reset$color_noticetkis_execute $current_line$color_error failed for some reason"
      fi
    else
      debug "\"tkis_execute $current_line\" was skipped because current_line \"$current_line\" is only whitespace"
    fi

    let current=$current+1

    if [[ $current -lt $list_size ]] ; then
      # save the next spot so resume can work properly
      echo $current > $tkis_resume_rule.$program_name
    fi
  done

  # now save the version
  if [[ $tkis_ignore_system_version != "yes" ]] ; then
    if [[ $system_version == "" ]] ; then
      echo "$program_name $version" >> $system_version_file
    elif [[ $system_version != $version ]] ; then
      sed -i -e "s|^$program_name $system_version|$program_name $version|" $system_version_file
    fi
  fi

  # return to our previous location
  debug "popping last directory"
  pop_to_null

  tkis_handle_cleanup $program_name $version
  tkis_local_pop

  notice "Successfully upgraded $color_reset$color_notice$program_name-$version$color_highlight for $color_reset$color_notice$tkis_process"

  debug "popping to original directory prior to script execution"
  pop_to_null

  # remove resume file
  rm -f $tkis_resume_rule.$program_name

  tkis_calculate_time
}
