#!/bin/bash
DIRECTORY="$(readlink -f "$(dirname "$0")")"
function error {
  echo -e "\e[91m$1\e[39m"
  exit 1
}
[ -z "$(yad --help)" ] && error "YAD needs to be installed to run pi-apps."
echo '|‾‾‾‾\(‾)          /‾\
| |‾) |‾|         / ⧋ \ |‾'\''‾‾\|‾'\''‾‾\/‾‾‾|
|  ‾_/| | |‾‾‾|  / ‾‾‾ \| |‾) | |‾) \ ‾‾\
|_|‾  |_|  ‾‾‾  /_/‾‾‾\_\ .‾_/| .‾_/|‾‾ /
                        |_|‾  |_|‾   ‾‾‾
'
#check for updates in background
"${DIRECTORY}/updater" &>/dev/null &
#Variable 1 is used to view the details of the specified app
if [ ! -z "$1" ];then
  output="$1"
fi
runonce() {
  #run a command, only if it's never been run before. Useful for one-time migration or setting changes.
  
  #all arguments is command(s) to run
  #hash the command and check if it's already been run before
  
  runonce_hash="$(echo "$@" | sha256sum | awk '{print $1}')"
  if grep -q "$runonce_hash" "${DIRECTORY}/data/runonce_hashes" ;then
    #hash found
    #echo "runonce: '$@' already run before. Skipping."
    true
  else
    #run the command.
    bash <(echo "$@")
    #if it succeeds, add the hash to the list to never run it again
    if [ $? == 0 ];then
      echo "$runonce_hash" >> "${DIRECTORY}/data/runonce_hashes"
      #echo "'$@' succeeded. Added to list."
    else
      echo "'$@' failed. Not adding hash to list."
    fi
    
  fi
  
}
#mark wine as installed, if twisteros
runonce "
  if [ -f /usr/local/bin/twistver ] && command -v wine >/dev/null ;then
    echo 'installed' > '${DIRECTORY}/data/status/Wine (x86)'
  fi"
#mark box86 as installed, if twisteros
runonce "
  if [ -f /usr/local/bin/twistver ] && command -v box86 >/dev/null ;then
    echo 'installed' > '${DIRECTORY}/data/status/Box86'
  fi"
#move a bunch of apps to the new multimedia category
runonce "
  '${DIRECTORY}/etc/categoryedit' 'Chromium Widevine' Multimedia >/dev/null
  '${DIRECTORY}/etc/categoryedit' 'FreeTube' Multimedia >/dev/null
  '${DIRECTORY}/etc/categoryedit' 'Sonic Pi 3.2' Multimedia >/dev/null
  '${DIRECTORY}/etc/categoryedit' 'TBOPlayer' Multimedia >/dev/null
  '${DIRECTORY}/etc/categoryedit' 'WACUP (new WinAmp)' Multimedia >/dev/null
  '${DIRECTORY}/etc/categoryedit' 'YouTubuddy' Multimedia >/dev/null"
#move a couple apps to tools category
runonce "
  '${DIRECTORY}/etc/categoryedit' 'Snapdrop' Tools >/dev/null
  '${DIRECTORY}/etc/categoryedit' 'Node.js' Tools >/dev/null"
#re-run install script on twistos lite to show select pre-hidden apps
runonce "
  if [ -f /usr/local/bin/twistver ] && [[ "\$"(twistver) != 'Twister OS version'* ]];then
    '${DIRECTORY}/install'
  fi"
runonce "
  rm -rf '${DIRECTORY}/apps/Back to Chromium v86'
  rm -rf '${DIRECTORY}/apps/Back to Chromium v78'
  rm -rf '${DIRECTORY}/apps/FreeCAD (precompiled)'
  rm -rf '${DIRECTORY}/apps/Chromium Media Edition'
  rm -rf '${DIRECTORY}/apps/Retropie'
  if [ "\$"(cat '${DIRECTORY}/data/status/Back to Chromium v78' 2>/dev/null) == installed ] || [ "\$"(cat '${DIRECTORY}/data/status/Back to Chromium v86' 2>/dev/null) == installed ];then
    echo 'installed' > '${DIRECTORY}/data/status/Downgrade Chromium'
  fi
  "
#for old installs prior to having categories, re-run install script
runonce "
  if [ ! -e '${DIRECTORY}/data/categories' ];then
    '${DIRECTORY}/install'
  fi
  "
#completely remove cordless app
runonce "rm -rf '${DIRECTORY}/apps/Cordless' &>/dev/null"
install() {
  app="$1"
  #terminal title text
  linecount="$(echo "$app" | wc -l)"
  if [ $linecount -eq 1 ];then
    title="Installing $app"
  elif [ $linecount -le 4 ];then
    title="Installing $(echo "$app" | tr '\n' '|' | sed -i 's/|/, /g')"
  else
    title="Installing several apps"
  fi
  "${DIRECTORY}/etc/terminal-run" '
    if "'"${DIRECTORY}/manage"'" multi-install "'"$app"'" ; then
      echo -e "\nClosing in 30 seconds."
      sleep 30
    else
      echo -e "\nClose this window to exit."
      read enter #technically you could press Enter to exit.
    fi
    ' "$title"
  sleep 1
  while ps -C manage &>/dev/null;do sleep 0.1; done
  
  #re-preload all categories in background
  "${DIRECTORY}/etc/preload-daemon" "$format" &>/dev/null &
}
uninstall() {
  app="$1"
  #terminal title text
  linecount="$(echo "$app" | wc -l)"
  if [ $linecount -eq 1 ];then
    title="Uninstalling $app"
  elif [ $linecount -le 4 ];then
    title="Uninstalling $(echo "$app" | tr '\n' '|' | sed -i 's/|/, /g')"
  else
    title="Uninstalling several apps"
  fi
  "${DIRECTORY}/etc/terminal-run" '
    if "'"${DIRECTORY}/manage"'" multi-uninstall "'"$app"'" ; then
      echo -e "\nClosing in 30 seconds."
      sleep 30
    else
      echo -e "\nClose this window to exit."
      read enter #technically you could press Enter to exit.
    fi
    ' "$title"
  sleep 1
  while ps -C manage &>/dev/null;do sleep 0.1; done
  
  #re-preload all categories in background
  "${DIRECTORY}/etc/preload-daemon" "$format" &>/dev/null &
}
motd="$(echo -e "$(wget -qO- https://raw.githubusercontent.com/Botspot/pi-apps-announcements/main/message | shuf -n 1)")"
#app list mode. Allowed values: 'yad', 'xlunch'
guimode="$(cat "${DIRECTORY}/data/settings/App List Style")"
[ -z "$guimode" ] && guimode=yad
#mode=yad
prefix=''
while true;do
  LIST="$("${DIRECTORY}/preload" $guimode "$prefix")"
  #LIST="$(cat "${DIRECTORY}/data/preload/LIST")"
  #echo "$LIST"
  
  #if output is not empty then assume button pressed was Details
  button=0
  
  while [ -z "$output" ];do
    
    if [ "$guimode" == yad ];then
      if [ -z "$prefix" ];then
        buttons=("--button=!${DIRECTORY}/icons/install.png!Install:4" \
        "--button=!${DIRECTORY}/icons/uninstall.png!Uninstall:2" \
        "--button=!${DIRECTORY}/icons/info.png!View more about the selected software:0" )
      else
        buttons=("--button=!${DIRECTORY}/icons/back.png!Back:3" \
        "--button=!${DIRECTORY}/icons/install.png!Install:4" \
        "--button=!${DIRECTORY}/icons/uninstall.png!Uninstall:2" \
        "--button=!${DIRECTORY}/icons/info.png!Details:0" )
      fi
      
      output="$(echo -e "$LIST" | yad --center --title='Pi-Apps'"$([ ! -z "$prefix" ] && echo ": $(echo "$prefix" | tr '/' '>')")" --width=310 --height=400 --no-headers \
        --text="$([ -z "$prefix" ] && echo "$motd" || echo "Viewing $(echo "$prefix" | tr '/' '>') category")" --image="${DIRECTORY}/icons/logo-64.png" --image-on-top \
        --list --multiple --separator='\n' --window-icon="${DIRECTORY}/icons/logo.png" \
        --column=:IMG --column=:IMG --column=Name --column=Sysname:HD --column=tip:HD \
        --print-column=4 --tooltip-column=5 \
        "${buttons[@]}" \
      )"
      
      button=$? #get exit code to determine which button was pressed
      echo "Button: ${button}"
      if [ $button -eq 252 ];then #if window manager x was pressed
        exit 0
      fi
      if [ "$button" == 3 ];then
        #back button
        break
      fi
      if [ -z "$output" ];then
        echo "output variable empty!"
        yad --center --title='Pi-Apps' --width=310 \
          --window-icon="${DIRECTORY}/icons/logo.png" \
          --text="Mind reading is not supported.
    (You didn"\'"t select an App)" \
          --button=OK:0
      fi
      
    elif [ "$guimode" == xlunch ];then
      if [ ! -d "${DIRECTORY}/xlunch" ] || [ ! -f /usr/bin/xlunch ];then
        #get current number of terminal-run processes
        rm -f /tmp/xlunchfailed /tmp/xlunchfinished /tmp/terminalexit
        echo '' > /tmp/terminalexit
        "${DIRECTORY}/etc/terminal-run" "
          function error {
            echo -e "\""\e[91m$1\e[39m"\""
            echo 'Close this terminal to exit.'
            echo '' > /tmp/xlunchfailed
            sleep infinity
          }
          trap 'echo "\"""\"" > /tmp/terminalexit' EXIT
          rm -f /tmp/terminalexit
          sudo rm -rf /usr/bin/xlunch "\""$DIRECTORY/xlunch"\"" 2>/dev/null
          sudo apt install -y libimlib2-dev libx11-dev || error 'APT failed to install libimlib2-dev and libx11-dev packages!'
          cd "\""$DIRECTORY"\""
          git clone https://github.com/Tomas-M/xlunch || error 'Failed to clone xlunch repository!'
          cd "\""$DIRECTORY/xlunch"\""
          echo 'Running make...'
          make -j8 || error 'make command failed!'
          echo 'Running sudo make install...'
          sudo make install || error 'sudo make install failed!'
          sudo rm -f /usr/share/applications/genentries.desktop
          cd $HOME
          if [ ! -f /usr/bin/xlunch ];then
            error 'xlunch should be installed now, but /usr/bin/xlunch does not exist!'
          fi
          echo '' > /tmp/xlunchfinished
        " 'Compiling xlunch...'
        #if terminal doesn't start in 3 seconds, then /tmp/terminalexit will exist.
        sleep 3
        #check for an exit status code from the running terminal
        while true; do
          if [ -f /tmp/xlunchfinished ];then
            break
            echo "xlunch finished installing."
          elif [ -f /tmp/xlunchfailed ] || [ -f /tmp/terminalexit ];then
            #revert back to yad
            echo 'yad' > "{DIRECTORY}/data/settings/App List Style"
            error "xlunch failed to compile!\nOr the terminal exited."
          else
            sleep 1
          fi
        done
      fi
      #xlunch compiled
      
      screen_width="$(xdpyinfo | grep 'dimensions:' | tr 'x' '\n' | tr ' ' '\n' | sed -n 7p)"
      screen_height="$(xdpyinfo | grep 'dimensions:' | tr 'x' '\n' | tr ' ' '\n' | sed -n 8p)"
      height=700
      width=800
      xposition=$(((screen_width/2)-(width/2)))
      yposition=$(((screen_height/2)-(height/2)))
      
      if false;then
        scrotosition=$(((screen_width/2)-(width/2))) -a "$((xposition+1)),$((yposition+33)),${width},${height}" blur.png #blur_init.png
        convert -blur 10x5 ~/blur.png ~/blur.png
      fi
      
      if [ ! -z "$prefix" ];then
        echo "Adding back button to xlunch..."
        LIST="Back;${DIRECTORY}/icons/back-64.png;./
$LIST"
        LIST="$(echo "$LIST" | grep .)"
      fi
      
      if [ -z "$prefix" ];then
        searchbox="Search: "
      else
        searchbox="Viewing $(echo "$prefix" | tr '/' '>'). Search: "
      fi
      
      
      #xlunchtheme=light
      if [ "$xlunchtheme" == light ];then
        #light mode
        output="$(echo -e "$LIST" | xlunch -WoCS -s 64 --bc e0e0e0 --tc 000000 --pc 6060ffff --hc ffffff50 \
          -p "$searchbox" -a -c $([ $width -lt 550 ] && echo 1 || echo 2) --title "Pi-Apps: Raspberry Pi app store" \
          --icon "${DIRECTORY}/icons/logo.png" --scrollbarcolor ffffff40 --scrollindicatorcolor 0000ff80 \
          --width $width --height $height --xposition $xposition --yposition $yposition \
          --button "${DIRECTORY}/icons/logo-128-3d.png;;$((($width/2)-(128/2))),0;pi-apps-homepage1" \
          --button "${DIRECTORY}/icons/logo-3d.png;;$([ -z "$prefix" ] && echo '45' || echo '65'),$([ -z "$prefix" ] && echo '10' || echo '0');pi-apps-homepage1"
          #-g ~/blur.png
          )"
      else
        #dark mode
        output="$(echo -e "$LIST" | xlunch -WoCS -s 64 --bc 000000A0 --tc ffffffff --pc 6060ffff --hc 60606010 \
          -p "$searchbox" -a -c $([ $width -lt 550 ] && echo 1 || echo 2) --title "Pi-Apps: Raspberry Pi app store" \
          --icon "${DIRECTORY}/icons/logo.png" --scrollbarcolor ffffff40 --scrollindicatorcolor 0000ff80 \
          --width $width --height $height --xposition $xposition --yposition $yposition \
          --button "${DIRECTORY}/icons/logo-128-trans.png;;$((($width/2)-(128/2))),0;pi-apps-homepage1" \
          --button "${DIRECTORY}/icons/logo-trans.png;;$([ -z "$prefix" ] && echo '45' || echo '65'),$([ -z "$prefix" ] && echo '10' || echo '0');pi-apps-homepage1"
          #-g ~/blur.png
          )"
      fi
      button=0
      
      if [ -z "$output" ];then
        error "xlunch did not report any selected apps!"
      fi
      
      #homepage button
      if [ "$output" == 'pi-apps-homepage1' ];then
        chromium-browser https://github.com/Botspot/pi-apps &
        output=''
      fi
    else
      error "Unrecognized app list style '$guimode'!"
    fi
    output="$(echo "$output" | sed '/^$/d')"
    echo "Output: ${output}EOO"
    
  done
  #output variable populated
  
  case $button in
    1)
      echo "User exited."
      exit 0
      ;;
    3)
      echo "Back"
      prefix="$(dirname "$prefix" | tr -d '.')"
      ;;
    0)
      echo "Details"
      if echo "$output" | grep -q '/' ;then
        #folder
        if [ "$output" == './' ];then
          echo "Back"
          prefix="$(dirname "$prefix" | tr -d '.')"
        else
          prefix="$prefix/$output"
          prefix="${prefix::-1}"
          prefix="$(echo "$prefix" | sed 's+^/++')"
        fi
        echo "Prefix is $prefix"
        output=''
      else
        #app
        output="$(echo "$output" | head -n1)"
        
        if [ -f "${DIRECTORY}/data/installed-packages/${output}" ] && [ ! -z "$(cat "${DIRECTORY}/data/installed-packages/${output}")" ];then
          installedpackages="
This app installed these packages: $(cat "${DIRECTORY}/data/installed-packages/${output}" | sort | uniq | tr '\n' ' ')"
        else
          installedpackages=''
        fi
        
        #text below the app icon
        description="$(cat "${DIRECTORY}/apps/${output}/description" || echo 'Description unavailable')$installedpackages"
        
        #text to the right of the app icon
        abovetext="$output
  Current status: $(echo "$(cat "${DIRECTORY}/data/status/${output}" || echo 'Uninstalled')" | sed 's/corrupted/corrupted (installation failed)/g')"
        if [ -f "${DIRECTORY}/apps/${output}/website" ];then
          #show website if it exists
          abovetext="$abovetext
  Website: $(cat "${DIRECTORY}/apps/${output}/website" | head -n1)"
          
        fi
        
        if [ -z "$clicklist" ];then
          source "${DIRECTORY}/api"
          clicklist="$(usercount)"
        fi
        
        usercount="$(echo "$clicklist" | grep " $output"'$' | awk '{print $1}' | head -n1)"
        if [ ! -z "$usercount" ] && [ "$usercount" -gt 20 ];then
          abovetext="$abovetext
  $(printf "%'d" "$usercount") users"
          
          if [ "$usercount" -ge 1500 ] && [ "$usercount" -lt 10000 ];then
            #if a lot of users, add an exclamation point!
            abovetext="${abovetext}!"
          elif [ "$usercount" -ge 10000 ];then
            #if a crazy number of users, add two exclamation points!
            abovetext="${abovetext}!!"
          fi
        fi
        
        #if already installed then no need to provide install button. And vice versa.
        whichbutton="$(
        if [ "$(cat "${DIRECTORY}/data/settings/Show Edit button")" == 'Yes' ];then
          echo "--button=Edit!${DIRECTORY}/icons/edit.png:10"
        fi
        if [ -f "${DIRECTORY}/apps/${output}/credits" ];then
          echo "--button=Credits!${DIRECTORY}/icons/credits.png:12"
        fi
        if [ ! -f "${DIRECTORY}/data/status/${output}" ];then
          #Taking a chance here. If status file is nonexistent, assume uninstalled.
          echo "--button=!${DIRECTORY}/icons/install.png:4"
        elif [ "$(cat "${DIRECTORY}/data/status/${output}")" == 'installed' ];then
          echo "--button=!${DIRECTORY}/icons/uninstall.png:2"
        elif [ "$(cat "${DIRECTORY}/data/status/${output}")" == 'uninstalled' ];then
          echo "--button=!${DIRECTORY}/icons/install.png:4"
        else
          #if status is corrupted or unknown, then show both buttons
          echo "--button=!${DIRECTORY}/icons/uninstall.png:2 --button=!${DIRECTORY}/icons/install.png:4"
        fi
        )"
        
        echo "$description" | yad --text-info --fontname=12 --wrap --show-uri --text="$(echo "$abovetext" | sed 's/&/&/g')" \
          --image="${DIRECTORY}/apps/${output}/icon-64.png" --image-on-top \
          --title="Details of ${output}" --window-icon="${DIRECTORY}/icons/logo.png" --center --width=700 --height=300 \
          --button=Back!"${DIRECTORY}/icons/back.png":0 \
          --button=''!"${DIRECTORY}/icons/up.png"!'View previous App':6 \
          --button=''!"${DIRECTORY}/icons/down.png"!'View next App':8 \
          $whichbutton
        button=$? #get exit code to determine which button was pressed
        echo "Button: ${button}"
        
        if [ $button == 0 ];then
          echo 'Back' #do nothing, as user requested to go back
          #clear app var
          output=''
        elif [ $button == 4 ];then
          app="$output"
          install "$app"
        elif [ $button == 2 ];then
          app="$output"
          uninstall "$app"
        elif [ $button == 6 ] || [ $button == 8 ];then
          #previous or next app clicked
          lsoutput="$(echo "$LIST" | grep -v '/' | grep -v '(' | grep -v *'\n App folder' | awk -F ';' '{print $NF}' | uniq)"
          echo "$lsoutput"
          
          if [ $button == 6 ];then
            echo 'previous app'
            
            #convert $output into number, then subtract 1 from it
            number="$(echo "$lsoutput" | grep -nx "$output" | cut -f1 -d: )"
            
            lastline="$(echo "$lsoutput" | wc -l)"
            
            if [ $(($number - 1)) -lt '1' ];then
              newnumber=$lastline
            else
              newnumber=$(($number - 1))
            fi
            
            output="$(echo "$lsoutput" | sed -n "${newnumber}p")"
            
            echo "Line number was ${number}, but now is ${newnumber}. Name is ${output}."
          elif [ $button == 8 ];then
            echo 'next app'
            
            #convert $output into number, then add 1 to it
            number="$(echo "$lsoutput" | grep -nx "$output" | cut -f1 -d: )"
            
            echo "Line number was ${number}, but now is ${newnumber}. Name is ${output}."
            
            lastline="$(echo "$lsoutput" | wc -l)"
            
            if [ $(($number + 1)) -gt $lastline ];then
              newnumber=1
            else
              newnumber=$(($number + 1))
            fi
            
            output="$(echo "$lsoutput" | sed -n "${newnumber}p")"
            
            echo "Line number was ${number}, but now is ${newnumber}. Name is ${output}."
          fi
        elif [ $button == 10 ];then
          echo "edit $output"
          "${DIRECTORY}/createapp" "$output"
        elif [ $button == 12 ];then
          echo "credits of $output"
          cat "${DIRECTORY}/apps/${output}/credits" | yad --text-info --fontname=12 --wrap \
            --image="${DIRECTORY}/apps/${output}/icon-64.png" --image-on-top \
            --title="Credits of ${output}" --window-icon="${DIRECTORY}/icons/logo.png" --center --width=700 --height=300 \
            --button=Close!"${DIRECTORY}/icons/exit.png":0
            
        else
          echo 'unknown button. Exiting now.'
          exit 0
        fi
      fi
      ;;
    2)
      #uninstall
      if ! echo "$output" | grep -q '/' ;then
        uninstall "$output"
        #clear output var to prompt main window to open next
      else
        motd="Sorry, you can"\'"t uninstall folders."
        prefix=''
      fi
      output=''
      ;;
    4)
      #install
      if ! echo "$output" | grep -q '/' ;then
        install "$output"
        #clear output var to prompt main window to open next
      else
        motd="Sorry, you can"\'"t install folders."
        prefix=''
      fi
      output=''
      ;;
    *)
    error "Unknown button: $button"
    ;;
  esac
done