#!/bin/bash

#this generates a yad-friendly app list. This is run every time the gui script is executed.
#if this script detects nothing has changed since last run, then it will echo back the app list that was generated last time.

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

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

#determine if host system is 64 bit arm64 or 32 bit armhf
if [ ! -z "$(file "$(readlink -f "/sbin/init")" | grep 64)" ];then
  arch=64
elif [ ! -z "$(file "$(readlink -f "/sbin/init")" | grep 32)" ];then
  arch=32
else
  error "Failed to detect OS CPU architecture! Something is very wrong."
fi

#yad or xlunch format
format="$1"

if [ -z "$format" ];then
  format=yad
elif [[ "$format" = xlunch* ]];then
  format=xlunch
elif [ "$format" != 'yad' ] && [ "$format" != 'xlunch' ];then
  error "Unknown list format '$format'!"
fi

#specifies an app folder(s)
prefix="$2"

timestampfile="${DIRECTORY}/data/preload/timestamps-$(echo "$prefix" | tr -d '/')"
listfile="${DIRECTORY}/data/preload/LIST-$(echo "$prefix" | tr -d '/')"

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

mktimestamps() {
  #these directories are checked for changes
  checkdirs="${DIRECTORY}/apps
${DIRECTORY}/data/settings
${DIRECTORY}/data/status
${DIRECTORY}/etc"
  
  timestamps=''
  PREIFS="$IFS"
  IFS=$'\n'
  for dir in $checkdirs
  do
    timestamps="$timestamps
dir $dir $(stat -c %Y "${dir}/$(ls -t "$dir" | head -n1)")"
  done
  IFS="$PREIFS"
  #remove first empty newline and check a few other things for changes too
  timestamps="prefix: $prefix
format: $format
number of files: $(ls -1q "${DIRECTORY}/apps"/* | wc -l)
preload shasum: $(sha256sum "${DIRECTORY}/preload" | awk '{print $1}')
api shasum: $(sha256sum "${DIRECTORY}/api" | awk '{print $1}')
structure shasum: $(shasum "${DIRECTORY}/data/categories/structure" | awk '{print $1}')
${timestamps:1}"
}

reloadlist=0

if [ -f "$timestampfile" ];then
  #get modified timestamps for directories
  mktimestamps
  
  if [ "$timestamps" == "$(cat "$timestampfile")" ];then
    #if current timestamps and saved timestamps match, then don't reload the list
    reloadlist=0
    echo "Timestamps match." 1>&2
  else
    #timestamps don't match, so reload the list
    reloadlist=1
    echo "Timestamps don't match" 1>&2
    
    echo -e "original file: $(cat "$timestampfile")\nnew timestamp: $timestamps" 1>&2
  fi
else
  #timestamp file not found
  reloadlist=1
fi

if [ ! -f "$listfile" ] || [ -z "$(cat "$listfile")" ];then
  echo "list file for $prefix does not exist." 1>&2
  reloadlist=1
fi

if [ $reloadlist == 1 ];then
  echo "Generating list..." 1>&2
  
  source "${DIRECTORY}/api"
  vfiles="$(app_categories)" #generate paps within categories as folders
  
  #generate a virtual file system with apps in folders represented as subdirectories
  
  
  vfiles="$(echo "$vfiles" | grep . | sort | uniq)"
  #echo "$vfiles" 1>&2
  
  
  if [ ! -z "$prefix" ];then
    echo "Showing apps within $prefix/" 1>&2
    
    vfiles="$(echo "$vfiles" | grep "^$prefix/" | sed "s+$prefix/++g")"
  fi
  #echo "$vfiles" 1>&2
  
  #remove apps within categories - show this layer of stuff only.
  vfiles="$(echo "$vfiles" | sed 's+/.*+/+g' | sort | uniq)"
  
  #get list of apps - excluding folders
  APPS="$(echo "$vfiles" | grep -v '/')"
  
  #get list of folders - excluding apps - and hide the hidden folder.
  DIRS="$(echo "$vfiles" | grep '/' | tr -d '/' | grep -vx "hidden")"
  
  #remove apps that are not compatible with OS architecture
  PREIFS="$IFS"
  IFS=$'\n'
  for i in $APPS
  do
    #if install script doesn't exist -------------------- and if os-specific install script doesn't exist, then...
    if [ ! -f "${DIRECTORY}/apps/${i}/install" ] && [ ! -f "${DIRECTORY}/apps/${i}/install-${arch}" ];then
      #...remove the app from the list
      echo "Removing $i from the list because it is not compatible with your ${arch}-bit OS." 1>&2
      APPS="$(echo "$APPS" | grep -vx "$i")"
    fi
  done
  IFS="$PREIFS"
  
  #shuffle the list if enabled
  if [ "$(cat "${DIRECTORY}/data/settings/Shuffle App list")" == 'Yes' ];then
    APPS="$(echo "$APPS" | shuf)"
    DIRS="$(echo "$DIRS" | shuf)"
  fi
  
  if [ "$format" == yad ];then
    PREIFS="$IFS"
    IFS=$'\n'
    LIST=''
    for i in $DIRS
    do
      if [ -f "${DIRECTORY}/icons/categories/${i}.png" ];then
        diricon="${DIRECTORY}/icons/categories/${i}.png"
      else
        diricon="${DIRECTORY}/icons/categories/default.png"
      fi
      
      LIST="${LIST}$diricon
${DIRECTORY}/icons/none-24.png
$i
$i/
App folder
"
    done
    
    for i in $APPS
    do
      LIST="$LIST$(echo "${DIRECTORY}/icons/$(cat "${DIRECTORY}/data/status/${i}" 2>/dev/null || echo "none").png")
${DIRECTORY}/apps/${i}/icon-24.png
$i
$i
"\("$(cat "${DIRECTORY}/data/status/${i}" 2>/dev/null || echo "uninstalled")"\)" $(echo "$(cat "${DIRECTORY}/apps/${i}/description" || echo "Description unavailable")" | head -n1)
"
    done
    IFS="$PREIFS"
    
  elif [ "$format" == xlunch ];then
    #XUNCH list format
    
    PREIFS="$IFS"
    IFS=$'\n'
    LIST=''
    for i in $DIRS
    do
      if [ -f "${DIRECTORY}/icons/categories/${i}-64.png" ];then
        diricon="${DIRECTORY}/icons/categories/${i}-64.png"
      else
        diricon="${DIRECTORY}/icons/categories/default-64.png"
      fi
      
      LIST="$LIST
${i};$diricon;${i}/"
    done
    
    for i in $APPS
    do
      LIST="$LIST
${i} "\("$(cat "${DIRECTORY}/data/status/${i}" 2>/dev/null || echo "uninstalled")"\)";${DIRECTORY}/apps/${i}/icon-64.png;${i}"
    done
    IFS="$PREIFS"
  fi
  LIST="$(echo -e "$LIST")"
  
  #save entire list string to file for future use
  echo "$LIST" > "$listfile"
  
  #save timestamps to file too
  mktimestamps
  echo "$timestamps" > "$timestampfile"
else
  echo "Reading list file..." 1>&2
  LIST="$(cat "$listfile")"
fi

(#put icons in cache
PREIFS="$IFS"
IFS=$'\n'
for icon in $(echo "$LIST" | grep icon-24)
do
  cat "$icon" 1>/dev/null
  #echo "Putting $icon in cache..." 1>&2
done
IFS="$PREIFS" ) &

echo "$LIST"

#re-preload all categories in background
"${DIRECTORY}/etc/preload-daemon" "$format" &>/dev/null &
