#! /bin/bash
#--------------------------------------------------------------------------------------------------------
# Name: Linux Lite - Lite Software
# Architecture: all
# Authors: Misko_2083, Jerry Bezencon, gerito1, Johnathan "ShaggyTwoDope" Jenkins, Ralphy
# Website: https://www.linuxliteos.com
#--------------------------------------------------------------------------------------------------------

# Ensure multi-language support
export LANG=C

# Variables
_ICON="/usr/share/icons/Papirus/24x24/apps/litesoftware.png"		# Lite Software icon variable
_APPNAME="Lite Software"                                 # Application name
_APPINST="/usr/share/liteappsicons/litesoftware/ll-install-software_32x32.png"
_APPREM="/usr/share/liteappsicons/litesoftware/ll-remove-software_32x32.png"
# ask for administrative credentials
if [ "$EUID" -ne "0" ]; then pkexec "$0"; exit 0 ; if [ "${PIPESTATUS[@]}" -eq "126" ]; then exit 0 ; fi; else :; fi

# Kill off any package managers that may be running
if [ "$(pidof synaptic)" ]; then killall -9 synaptic; fi
if [ ! -z "$(pgrep gdebi-gtk)" ]; then killall -9 gdebi-gtk; fi
# Set up log facilities
# Example output: [02/06/15 20:03:12] message input
LOGFILE="/var/log/lite-software.log"
lslog() {
    message="$@"
    echo '['$(date +%D\ %H:%M:%S)']'"$message" >> "$LOGFILE"
}
# Log last activities to retrieve errors
TMP_LOG="/tmp/lite-software.log"

prepare() {
  # Check internet access
  if eval "curl -sk google.com" >> /dev/null 2>&1; then :; else # Prompt ERROR internet connection
    zenity --info --width="390" --ok-label="Got it!" --title=" $_APPNAME - No Internet access" \
            --text="\n<b>Your computer does not seem to be connected to the Internet</b> \n \nYou need to be connected to the Internet to download and install applications." 2>/dev/null
    return
  fi
  # Check if apt-cache was built and ask to update
  if zenity --question --width="380" --height="120" --window-icon="$_ICON" --title=" Update Software Sources" \
            --text="\n<b>Would you like to update software sources now?</b>\n\nIt is recommended to always update software sources before installing applications. \
\n\nClick <b>No</b> to continue without updating or <b>Yes</b> to update software sources next." 2>/dev/null; then
      TOTALREPOS=$(cat /etc/apt/sources.list | grep '^deb' -c) # Total of repositories registered, this is approximated
      apt-get update 2>&1 | awk -v total=$TOTALREPOS '/^Ign|^ Get/{count++;$1=""} FNR { if (total != 0){percentage=int (1000*count/total);print (percentage < 90?percentage:99),"\n#",$0 }; fflush(stdout)}' \
      | zenity --progress --window-icon="$_ICON" --width="600" --pulsate --no-cancel --text="Updating package lists..." --title="Updating Software Sources. Please wait..." --percentage="0" --auto-close 2>/dev/null
      if [ "${PIPESTATUS[0]}" -ne "0" ]; then
        zenity --error --width="300" --height="90" --title="  $_APPNAME - Error" \
               --text="\n<b>Updating sources has failed</b>\n\nRefer to /var/log/lite-software.log for more information." 2>/dev/null
        lslog "ERROR: Updating sources has failed."
      fi
        lslog "INFO: Software sources were updated."
      else
        lslog "INFO: The updating of packages was canceled by the user"
  fi
}
# Set app icon variable
APPICON="/usr/share/liteappsicons/litesoftware/appicons/"

#--------------------------------------------------------------------------------------------------------
# soft_list is the list of package aliases to check/install/remove
# Consist in a list describing aspect for every package
# package_alias=( "element 0" "element 1" "element 2" "element 3" "element 4" "element 5" "element 6")
# element 0: TRUE\FALSE for being selected
# element 1: The Application name ie: Google Chrome, iDevices Manager
# element 2: The category which belongs to (one only) ie:  Internet, Multimedia
# element 3: Status of the package ie: Installed, Not Installed
# element 4: Description of the package ie: "Easily locate files and folders in your computer", "Clementine is a modern music player and library organizer"
# element 5: List of packages needed to provide the application ie: "aisleriot gnome-mahjongg gnome-mines gnome-hearts"
# element 6: List of additional packages (this is optional) ie: libavformat-extra-54
#--------------------------------------------------------------------------------------------------------
soft_list=(audacity
  calibre
  googlechrome
  dropbox
  etcher
  filezilla
  gamespack
  geany
  handbrake
  idevices
  imessenger
  kodi
  msedge
  clementine
  nitroshare
  zim
  obs
  passmgr
  playonlinux
  remote
  redshift
  extras
  ssr
  skype
  soundjuicer
  spotify
  steam
  teams
  teamviewer
  telegram
  torrent
  tor
  videoedit
  vbox
  weather
  guvcview
  wine
  zoom )

# Check system arch, don't list 64bit only apps in i686 system eg. skypeforlinux is only available in 64bit
# The unset soft_list number corresponds to the item above the application you DON'Twant to list in 32bit systems
# eg. skypeforlinux is actually number 18 in the list, so its unset soft_list number becomes 17
#UNAME=$(uname -m)
#if [ "i686" == ${UNAME} ]; then
#    unset soft_list[17]
#    unset soft_list[5] # list another application here, and so on
#else
#    :
#fi

audacity=("$APPICON/audacity.png" "Audacity" "Multimedia" "" "Software for recording and editing sounds" "audacity" "" )
calibre=("$APPICON/calibre.png" "Calibre" "Office" "" "An open source e-book library management application" "calibre" "" )
googlechrome=("$APPICON/chrome.png" "Chrome Web Browser" "Internet" "" "The Google Chrome web browser" "google-chrome-stable" "" )
dropbox=("$APPICON/dropbox.png" "Dropbox" "Internet" "" "A popular cloud storage application" "dropbox thunar-dropbox-plugin python3-gpg" "" )
etcher=("$APPICON/etcher.png" "Etcher USB Burner" "Accessories" "" "Easily flash OS images to SD cards and USB drives" "balena-etcher-electron" "" )
filezilla=("$APPICON/filezilla.png" "Filezilla" "Internet" "" "A full-featured FTP/FTPS/SFTP client application" "filezilla" "" )
gamespack=("$APPICON/gamespack.png" "Games Pack" "Games" "" "Solitaire, Mahjongg, Chess, Mines, Sudoku and Tetris" "aisleriot gnome-chess gnome-mahjongg gnome-mines gnome-sudoku quadrapassel" "" )
geany=("$APPICON/geany.png" "Geany" "Accessories" "" "A full featured IDE and text editor for developers" "geany" "geany-plugins" )
handbrake=("$APPICON/handbrake.png" "Handbrake" "Multimedia" "" "Convert video to nearly any format" "handbrake" "" )
idevices=("$APPICON/gtkpod.png" "iDevices Manager" "Multimedia" "" "Manage your iDevices with Gtkpod" "gtkpod" "" )
imessenger=("$APPICON/pidgin.png" "Instant Messenger" "Internet" "" "Pidgin, a multi-protocol Instant Messenging client" "pidgin" "" )
kodi=("$APPICON/kodi.png" "Kodi" "Multimedia" "" "The Kodi Media Center" "kodi" "" )
msedge=("$APPICON/microsoft-edge.png" "Microsoft Edge Browser" "Internet" "" "Microsoft Edge is a cross-platform web browser." "microsoft-edge-stable" "" )
clementine=("$APPICON/clementine.png" "Music Player" "Multimedia" "" "Clementine is a modern music player and library organizer" "clementine" "")
nitroshare=("$APPICON/nitroshare.png" "Nitroshare" "Network" "" "Transfer files easily between Linux, Mac and Windows" "nitroshare libqmdnsengine0" "")
zim=("$APPICON/zim.png" "Note Taking Journal" "Accessories" "" "Zim is a Note taking/Wiki editing application" "zim" "" )
obs=("$APPICON/obs.png" "OBS Studio" "Multimedia" "" "A popular tool to record and stream desktop content" "obs-studio" "")
passmgr=("$APPICON/keepassxc.png" "Password Manager" "Accessories" "" "KeePassXC, a full featured password manager" "keepassxc" "" )
playonlinux=("$APPICON/playonlinux.png" "PlayOnLinux" "Cross Platform" "" "Use many games and apps designed to run on Windows" "playonlinux" "" )
remote=("$APPICON/remmina.png" "Remote Desktop Software" "Internet" "" "Remmina - Remotely connect to a Windows PC" "remmina" "" )
redshift=("$APPICON/redshift.png" "Redshift" "Accessories" "" "Adjusts the color temperature of your screen automatically" "redshift redshift-gtk" "" )
extras=("$APPICON/extras.png" "Restricted Extras" "Multimedia" "" "Additional codecs and file formats (highly recommended)" "ubuntu-restricted-extras" "libavcodec-extra58" )
ssr=("$APPICON/ssr.png" "Simple Screen Recorder" "Multimedia" "" "A simple to use screen and audio recorder" "simplescreenrecorder" "" )
skype=("$APPICON/skype.png" "Skype" "Internet" "" "A popular audio and video chat application" "skypeforlinux" "" )
soundjuicer=("$APPICON/sound-juicer.png" "Sound Juicer" "Multimedia" "" "A tool to extract music tracks from CD's" "sound-juicer" "ubuntu-restricted-extras" )
spotify=("$APPICON/spotify.png" "Spotify" "Multimedia" "" "A digital music service" "spotify-client" "" )
steam=("$APPICON/steam.png" "Steam" "Games" "" "A cross platform gaming client" "steam-installer steam-devices steam:i386" "" )
teams=("$APPICON/teams.png" "Teams" "Internet" "" "Connect with anyone from anywhere on Microsoft Teams" "teams" "" )
teamviewer=("$APPICON/teamviewer.png" "Teamviewer" "Internet" "" "Remote Desktop Support software" "teamviewer" "" )
telegram=("$APPICON/telegram.png" "Telegram" "Internet" "" "Fast and secure messaging application" "telegram-desktop" "" )
torrent=("$APPICON/deluge.png" "Torrent Software" "Internet" "" "Deluge Torrent client software" "deluge deluge-common" "" )
tor=("$APPICON/tor.png" "Tor Web Browser" "Internet" "" "A privacy respecting web browser" "tor-web-browser" "" )
videoedit=("$APPICON/openshot.png" "Video Editing Software" "Multimedia" "" "Openshot - a simple yet powerful video editor" "openshot openshot-qt blender inkscape" "")
vbox=("$APPICON/virtualbox.png" "VirtualBox" "System" "" "Install operating systems like Windows within Linux Lite" "virtualbox-qt virtualbox virtualbox-guest-dkms virtualbox-guest-utils virtualbox-guest-x11 virtualbox-dkms" "" )
weather=("$APPICON/weather.png" "Weather Monitor" "System Tray" "" "A Weather Monitor Plugin for your tray" "xfce4-weather-plugin" "" )
guvcview=("$APPICON/guvcview.png" "Webcam Software" "Internet" "" "Guvcview, webcam software for your computer" "guvcview" "" )
wine=("$APPICON/wine.png" "Wine" "Cross Platform" "" "Install and run Windows programs and games on Linux Lite" "wine-stable wine32-preloader wine64-preloader wine64-tools winetricks wine-menu-linuxlite" "")
zoom=("$APPICON/zoom.png" "Zoom" "Internet" "" "A cross platform video and audio conferencing application" "zoom" "" )

get_pkg_status() {
  result="Installed"
  for PKG in  $@
  do
    TEST_PKG=(`apt-cache policy "$PKG" | grep "Installed:"`)
    if [ "${TEST_PKG[1]}" == "(none)" ];then
      result="Not Installed"
      break
    fi
  done
  read ${2} <<< ${result}
  unset result
  unset TEST_PKG
}

# Check for installed packages
check_installed() {
  for element in ${soft_list[*]}
  do
    current_pkg="$element[5]"
    status="$element[3]"
    get_pkg_status "${!current_pkg}" status # Get the status of the main package
    read ${element}"[3]" <<< ${status}      # Write the status in the package status
  done
}

install_pkgs() {
  declare -a pkg_arr=("${!1}")

  lslog "INFO: Installation of packages initiated: ${pkg_arr[@]}"
  apt-get install -f --show-progress ${pkg_arr[@]} -y 2>&1 | tee "$TMP_LOG" | awk ' BEGIN { FS=" "; total=1;end_download=0} /upgraded/ {total= $1 + $3;FS="[ :]" } /^Get:[[:digit:]]+/ {printf "#Downloading %s %s %s\n",$7,$(NF-1),$NF;print int(($2 - 1) * 100 / total); fflush(stdout)} /^\(Reading / {if (end_download==0){print 100;fflush(stdout);end_download=1}} /^(Preparing|Unpacking|Selecting|Processing|Setting|Download)/ {print "#", $0; fflush(stdout)}  /^Progress/ {print  match($0, /([0-9]+)/, arr); if(arr[1] != "") print arr[1] ; fflush(stdout)}' \
   | ( zenity --window-icon="$_ICON" --progress --no-cancel --width="600" --text="Downloading package(s)...\nThis may take a while." --title="$_APPNAME - Downloading. Please wait..." --percentage="0" --auto-close 2>/dev/null ; zenity --progress --no-cancel --window-icon="$_ICON" --width="600" --text="Installing and configuring packages...\nThis may take a while." --title="$_APPNAME - Installing. Please wait..." --auto-close 2>/dev/null)
  if [ "${PIPESTATUS[0]}" -ne "0" ]; then
    err_msg=$(awk '/^E:/{$1=""; print $0}' "$TMP_LOG" | tail -n 1)
    lslog "ERROR:$err_msg"
    zenity --error --width="340" --height="80" --title="  $_APPNAME - Error" --text="\n$_APPNAME Error:\n\n-$err_msg \n\n- Make sure your computer is connected to the Internet and try again." 2>/dev/null
    return
  else
    zenity --info --window-icon="$_ICON" --width="280" --height="80" --title="   $_APPNAME - Installation" --text="\nInstallation successfully completed." 2>/dev/null
    lslog "INFO: Installation was a success."
  fi
}

remove_pkgs() {
  declare -a pkg_arr=("${!1}")

  lslog "INFO: Removal of packages initiated: ${pkg_arr[@]}"
  apt-get remove -f ${pkg_arr[@]} -y 2>&1 | tee "$TMP_LOG" | awk ' BEGIN { FS=" "; total=0; pkg=0}  /upgraded/ {total=$6 } /^Removing/ {print "#", $0;pkg+=1;print int((pkg - 1) * 100 / total); fflush(stdout)}' \
    | zenity --progress --window-icon="$_ICON" --no-cancel --width="600" --text="Removing package(s)...\nThis may take a while." --title="$_APPNAME - Removing. Please wait..." --percentage="0" --auto-close 2>/dev/null
  if [ "${PIPESTATUS[0]}" -ne "0" ]; then
    err_msg=$(awk '/^E:/{$1=""; print $0}' "$TMP_LOG" | tail -n 1)
    lslog "ERROR:$err_msg"
    zenity --error --title="  $_APPNAME - Error" --text="\n$_APPNAME Error:\n\n-$err_msg" 2>/dev/null
    return
  else
    zenity --info --window-icon="$_ICON" --width="280" --height="80" --title="   $_APPNAME - Removal" --text="\nRemoval successfully completed." 2>/dev/null
    lslog "INFO: Removal was a success."
  fi
}

# The installation menu
install_menu() {
  while (true); do
  check_installed

  selection=$(for element in ${soft_list[*]}
    do
      pkg_status="$element[3]"
      #Only list Not Installed applications
      if [ "${!pkg_status}" == "Installed" ]; then
        continue;
      fi
      row="$element[@]"                          #grab the whole row
      printf  '%s\n' "${!row}"                 #print every element in the row separated with a newline
    done | zenity --window-icon="$_ICON" --list --imagelist --multiple --width="920" --height="760" --print-column="2,6,7" --separator="| " --column="Select" --column="Name" --column="Category" --column="Status" \
      --column="Description" --column="Packages" --column="Optional Packages" \
      --text='    <span font="Roboto 13">Select the program or programs you want then click the <b>Install</b> button. \n\n<b> - Sort</b> columns by clicking on the column headers. \n<b> - Ctrl key:</b> Hold down <b>Ctrl</b> and click on applications <b>anywhere</b> on the list. \n<b> - Shift key:</b> Hold down <b>Shift</b> and click the <b>first</b> and then the <b>last</b> application you want from the list.\n </span>' \
      --title=" Install Software" --cancel-label="Back to Task Selector" --ok-label="Install" --hide-column="6,7" 2>/dev/null)

  # If Cancel is clicked then return to main loop
  if [ "${PIPESTATUS[0]}" -ne "0" ]; then return; fi

  # Check if anything is selected
  echo "$selection" | grep '[a-zA-Z0-9]'
  if [ "${PIPESTATUS[1]}" -ne "0" ]; then
    zenity --info  --width="280" --title="  Install Software" --text="\nNo application was selected for installation." 2>/dev/null
    continue
  fi

  # Split selection
  OIFS=$IFS
  IFS='|'
  selection_array=($selection)
  PKGS_NAMES=""
  PKGS=""
  for ((i=0; i<${#selection_array[@]}; ++i));
  do
    if (( i % 3 == 0 )); then
      PKGS_NAMES=$PKGS_NAMES${selection_array[$i]}"\n"
      continue
    fi
    PKGS=$PKGS${selection_array[$i]}" "
  done
  IFS=$OIFS

  zenity --question --width="320" --window-icon="$_ICON" --title="  $_APPNAME - Install" \
         --text="\nThe following software has been selected:<b>\n\n ${PKGS_NAMES} </b>\nDo you want to proceed with the installation?" 2>/dev/null
  if [ "$?" -eq "0" ]; then
    install_pkgs PKGS[@]; return; else continue
  fi
  done
}

# The installation menu
remove_menu() {
  while (true); do
  check_installed

  selection=$(for element in ${soft_list[*]}
    do
      pkg_status="$element[3]"
      #Only list Installed applications
      if [ "${!pkg_status}" == "Not Installed" ]; then
        continue;
      fi
      row="$element[@]"                          #grab the whole row
      printf  '%s\n' "${!row}"                 #print every element in the row separated with a newline
    done | zenity --window-icon="$_ICON" --list --imagelist --multiple --width="920" --height="760" --print-column="2,6" --separator="| " --column="Select" --column="Name" --column="Category" --column="Status" \
      --column="Description" --column="Packages" --column="Optional Packages" \
      --text='    <span font="Roboto 13">Select the program or programs you want to remove, then click the <b>Remove</b> button. \n\n<b> - Sort</b> columns by clicking on the column headers. \n<b> - Ctrl key:</b> Hold down <b>Ctrl</b> and click on applications <b>anywhere</b> on the list. \n<b> - Shift key:</b> Hold down <b>Shift</b> and click the <b>first</b> and then the <b>last</b> application you want from the list.\n </span>' \
      --title="Remove Software" --cancel-label="Back to Task Selector" --ok-label="Remove" --hide-column=6,7 2>/dev/null)

  # if cancel is clicked then return to main loop
  if [ "${PIPESTATUS[0]}" -ne "0" ]; then return; fi

  # Check if anything is selected
  echo "$selection" | grep '[a-zA-Z0-9]'
  if [ "${PIPESTATUS[1]}" -ne "0" ]; then
    zenity --info --width="260" --title="  Remove Software" --text="\nNo application was selected for removal." 2>/dev/null
    continue
  fi

  # Split selection
  OIFS=$IFS
  IFS='|'
  selection_array=($selection)
  PKGS_NAMES=""
  PKGS=""
  for ((i=0; i<${#selection_array[@]}; ++i));
  do
    if (( i % 2 == 0 )); then
      PKGS_NAMES=$PKGS_NAMES${selection_array[$i]}"\n"
      continue
    fi
    PKGS=$PKGS${selection_array[$i]}" "
  done
  IFS=$OIFS
  zenity --question --width="320" --window-icon="$_ICON" --title="  $_APPNAME - Remove" \
         --text="\nThe following software has been selected:<b>\n\n ${PKGS_NAMES} </b>\nDo you want to proceed with the removal?" 2>/dev/null
  if [ "$?" -eq "0" ]; then
    remove_pkgs PKGS[@]; return; else continue
  fi
  done
}
# We begin here
prepare
# The main loop
while (true); do
  TASK=$(zenity --list --imagelist --width="240" --height="210" --cancel-label="Quit" --window-icon="$_ICON" \
  --text='    <span font="Sans Bold 9">Please select a Task below</span>:\n' \
  --title="  $_APPNAME" --hide-header --column="Icons" --column="Task" --column="Code Task" --hide-column="3" --print-column="3" \
  "$_APPINST" "  Install Software" "1" "$_APPREM" "  Remove Software" "2" 2>/dev/null)
  if [ "${PIPESTATUS[0]}" -ne "0" ]; then
    exit 0
  elif [ -n "${TASK}" ];then
    case "$TASK" in
      "1") install_menu ;;
      "2") remove_menu ;;
    esac
  fi
done
exit 0
