#!/bin/bash

tkis_package(){
  local version_override=$1
  local program_name=$2
  local rule_name=$3
  local rule_type=$4
  local repeat_name=$5
  local save_name=$6

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

  if [[ $rule_name == "" ]] ; then
    error "tkis_package(): Missing rule's list name parameter for the program $color_reset$color_notice$program_name$color_error inside of $color_reset$color_notice${RU}$list_filename/$program_name"
  fi

  if [[ $rule_type == "" ]] ; then
    error "tkis_package(): Missing instruction type parameter for the rule $color_reset$color_notice$program_name$color_error inside of $color_reset$color_notice${RU}$list_filename/$program_name$color_error, should be one of the following: package, repeat, instruct, reinstruct, or always"
  elif [[ $rule_type != "package" && $rule_type != "repeat" && $rule_type != "instruct" && $rule_type != "reinstruct" && $rule_type != "always" ]] ; then
    error "tkis_package(): Instruction type is $color_reset$color_notice$rule_type$color_error for the rule $color_reset$color_notice$program_name$color_error inside of $color_reset$color_notice${RU}$list_filename/$program_name$color_error but must be one of the following: package, repeat, instruct, reinstruct, or always"
  fi

  if [ -f $tkis_local_error.$program_name ] ; then
    error "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 "The rule $color_reset$color_notice$RU$list_filename/$program_name$color_error is missing or cannot be accessed"
  fi

  if [[ $repeat_name == "as" ]] ; then
    if [[ $save_name == "" ]] ; then
      error "You specified $color_reset${color_notice}as$color_reset$color_error as the fourth parameter, this is a special reserved word and its use requires a fifth parameter"
    fi

    notice "You specified $color_reset${color_notice}as$color_reset$color_highlight as a fourth parameter, $color_reset${color_notice}$program_name$color_reset$color_highlight will be seen as $color_reset${color_notice}$save_name"
  else
    save_name=$program_name
  fi

  if [[ $rule_type == "package" || $rule_type == "repeat" ]] ; then
    if [[ $version_override == "no" ]] ; then
      # first get the version number
      local version=
      local subversion=
      local micversion=
      local majversion=
      local system_version=
      tkis_get_version $program_name

      if ! [ $? -eq 0 ] ; then
        error "tkis_package(): $color_reset$color_noticetkis_get_version $program_name$color_error failed for some reason"
      fi

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

    # If version_override was given, then use that instead of the global or system version
    else
      version=$version_override
    fi

    if [[ -f ${tkis_data}installed.$tkis_process ]] ; then
      if [[ $repeat_name == "" || $repeat_name == "as" ]] ; then
        debug "Searching already installed for ^$save_name $rule_name$"
        if [[ $(grep -s "^$save_name $version $rule_name$" ${tkis_data}installed.$tkis_process) != "" ]] ; then
          notice "$tkis_process $color_reset$color_notice$program_name$color_highlight $rule_name is already installed"

          if [ -f $tkis_resume_rule.$program_name ] ; then rm -f $tkis_resume_rule.$program_name ; fi
          return 0
        fi
      else
        debug "Searching already installed for \"^$save_name $rule_name $repeat_name$\""
        if [[ $(grep -s "^$save_name $version $rule_name $repeat_name$" ${tkis_data}installed.$tkis_process) != "" ]] ; then
          notice "$tkis_process $color_reset$color_notice$save_name $color_highlight $rule_name $repeat_name is already installed"

          if [ -f $tkis_resume_rule.$program_name ] ; then rm -f $tkis_resume_rule.$program_name ; fi
          return 0
        fi
      fi
    fi

    if [[ $tkis_ignore_system_version != "yes" && -f $system_version_file ]] ; then
      if [[ $repeat_name == "" || $repeat_name == "as" ]] ; then
        system_version=$(fss_basic_read -n $save_name $system_version_file)

        if [[ $tkis_force_install != "yes" ]] ; then
          if [[ $system_version == $version ]] ; then
            notice "System version $color_reset$color_notice$system_version$color_reset$color_highlight is up to date, not bothering to install $color_reset$color_notice$save_name-$version"

            if [ -f $tkis_resume_rule.$program_name ] ; then rm -f $tkis_resume_rule.$program_name ; fi
            return 0
          elif [[ $system_version > $version ]] ; then
            warning "System version $color_reset$color_notice$system_version$color_reset$color_warning is a newer version than the given version $color_reset$color_notice$version$color_reset$color_warning for the package $color_reset$color_notice$program_name"
          elif [[ $system_version < $version && $system_version != "" ]] ; then
            notice "System version is $color_reset$color_notice$system_version$color_highlight is older, updating to $color_reset$color_notice$version"
          fi
        fi
      fi
    fi

    # now extract the archive
    tkis_extract $program_name $version

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

    # 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_package(): 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
  else
    if [[ -f ${tkis_data}installed.$tkis_process ]] ; then
       if [[ $repeat_name == "" || $repeat_name == "as" ]] ; then
         debug "Searching already installed for \"^$save_name $rule_name$\""
         if [[ $(grep -s "^$save_name $rule_name$" ${tkis_data}installed.$tkis_process) != "" ]] ; then
           notice "$tkis_process $color_reset$color_notice$save_name $rule_name$color_highlight is already executed"

           if [ -f $tkis_resume_rule.$program_name ] ; then rm -f $tkis_resume_rule.$program_name ; fi
           return 0
         fi
       else
         debug "Searching already installed for ^$save_name $rule_name $repeat_name$"
         if [[ $(grep -s "^$save_name $rule_name $repeat_name$" ${tkis_data}installed.$tkis_process) != "" ]] ; then
           notice "$tkis_process $color_reset$color_notice$save_name $rule_name $repeat_name$color_reset$color_warning is already executed"

           if [ -f $tkis_resume_rule.$program_name ] ; then rm -f $tkis_resume_rule.$program_name ; fi
           return 0
         fi
      fi
    fi

    push_to_null $WO
  fi

  # 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 -p -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_package(): 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_package(): $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

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

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

    if [[ $repeat_name == "" || $repeat_name == "as" ]] ; then
      echo "$save_name $version $rule_name" >> ${tkis_data}installed.$tkis_process
    else
      echo "$save_name $version $rule_name $repeat_name" >> ${tkis_data}installed.$tkis_process
    fi

    tkis_handle_cleanup $program_name $version
    tkis_local_pop

    notice "Successfully installed $color_reset$color_notice$save_name-$version$color_highlight for $color_reset$color_notice$tkis_process"
  else
    if [[ $rule_type != "always" ]] ; then
      if [[ $repeat_name == "" ]] ; then
        echo "$save_name $rule_name" >> ${tkis_data}installed.$tkis_process
      else
        echo "$save_name $rule_name $repeat_name $save_name" >> ${tkis_data}installed.$tkis_process
      fi
    fi

    rm -f $tkis_resume_rule.$program_name
    tkis_local_pop

    notice "Successfully executed $color_reset$color_notice$save_name$color_highlight for $color_reset$color_notice$tkis_process"
  fi
}
