#!/bin/bash

# Defaultní argumenty
START="false"
STOP="false"
LOCK="false"
UNLOCK="false"
SETKEY="false"
ENABLE="false"
DISABLE="false"
MODIFY="false"
DISABLE_AUTORUN="false"
UNINSTALL="false"
APP_NAME="kiwi-light"
INSTALL="false"
WGT=""
DEFAULT_MANIFEST_URL="https://update.ki-wi.cz/kiwi-light-desktop/updatev1/stable.json"
MANIFEST_URL=$DEFAULT_MANIFEST_URL
PROFILE_DIR=~/kiwi-light-data/default
EXECUTABLE=${PROFILE_DIR}/kiwi-light
USER_SYSTEMD_CONFIG_DIR=~/.config/systemd/user
WINDOW_POSITION=""
WINDOW_MODE=""
SERVICE_NAME="kiwi-light"
ARCH=$(arch)
OS="$(uname -s)"

# Pole s argumenty pro kiwi-light
ARGS=() # spouštěné v configure.sh
SYSTEMD_ARGS=() # pro systemd

# Pole pro environment variables
ENVIRONMENT=()


if [[ $OS != Linux* ]] ; then
  echo "Unsuported os $OS"
  exit 1
fi

# Zjištění architektury TODO: sehnat seznam architektur, které dokáže vypsat command "arch"
if [ "$ARCH" = "x86_64" ] ; then
  ARCH_SUFFIX="linux_amd64"
elif [ "$ARCH" = "arm" ] || [ "$ARCH" = "armhf" ] || [ "$ARCH" = "armv7l" ] ; then
  ARCH_SUFFIX="linux_arm"
elif [ "$ARCH" = "aarch64" ] ; then
  ARCH_SUFFIX="linux_arm64"
elif [ "$ARCH" = "i386" ] || [ "$ARCH" = "i686" ] ; then
  ARCH_SUFFIX="linux_386"
else
  echo "Unsupported architecture $ARCH"
  exit 1
fi

# Parsování argumentů
COMMAND=$1
case $COMMAND in
  -h | --help | help)
    echo "$(basename "$0") Program to configure, install and uninstall $APP_NAME for linux."
    echo ""
    echo "usage:"
    echo "    install      default, optional - installs the app"
    echo "            --profile-dir=     sets profile dir for $APP_NAME app"
    echo "            --wgt=             sets wgt url for $APP_NAME app"
    echo "            --update=          where the app download from and from where the app will be updated"
    echo "            --disable-autorun  do not register $APP_NAME service for autorunning app"
    echo "            --service-name=    sets name of systemd service"
    echo "            --window-position= sets positon and size of app window in format: <X>,<Y>,<W>,<H>, if empty fullscreen is used"
    echo "                               the specified position is maintained only if the window-mode is set to \"windowed\""
    echo "            --window-mode=     sets application window mode, allowed values: {\"fullscreen\", \"windowed\", \"undefined\"}"
    echo "            --invasive=        invasive application launch mode. Options: {\"all\", \"[power,[screen],[volume]]\"}"
    echo "                               if an empty string, the application runs in non-invasive mode."
    echo "            --low-mem-insecure enable low-memory mode (fewer Chromium processes, but insecure)"
    echo "    uninstall    uninstall app"
    echo "            --service-name=    name of systemd service"
    echo "            --profile-dir=     sets profile dir for $APP_NAME app"
    echo "    start        temporary start $APP_NAME service for autorunning app, if it exists"
    echo "            --service-name=    name of systemd service"
    echo "    stop         temporary stop $APP_NAME service for autorunning app, if it exists"
    echo "            --service-name=    name of systemd service"
    echo "    disable      disable $APP_NAME service for autorunning app, if it exists"
    echo "            --service-name=    name of systemd service"
    echo "    enable       enable $APP_NAME service for autorunning app, if it exists"
    echo "            --service-name=    name of systemd service"
    echo "    modify       re-create new $APP_NAME service with new arguments"
    echo "            --profile-dir=     sets profile dir for $APP_NAME app"
    echo "            --wgt=             sets wgt url for $APP_NAME app"
    echo "            --update=          where the app download from and from where the app will be updated"
    echo "            --service-name=    name of systemd service"
    echo "            --window-position= sets positon and size of app window in format: <X>,<Y>,<W>,<H>, if empty fullscreen is used"
    echo "                               the specified position is maintained only if the window-mode is set to \"windowed\""
    echo "            --window-mode=     sets application window mode, allowed values: {\"fullscreen\", \"windowed\", \"undefined\"}"
    echo "            --invasive=        invasive application launch mode. Options: {\"all\", \"[power,[screen],[volume]]\"}"
    echo "                               if an empty string, the application runs in non-invasive mode."
    echo "            --low-mem-insecure enable low-memory mode (fewer Chromium processes, but insecure)"
    echo "    help | -h | --help"
    echo "              -- prints this help"
    exit 0
    ;;
  start)
    START="true"
    shift
    while [ $# -gt 0 ]; do
      case $1 in
        --service-name=*)
          SERVICE_NAME=${1:15}
          shift
          ;;
        *)
          echo "Unknown arg $1"
          exit 1
          ;;
      esac
    done
    ;;
  stop)
    STOP="true"
    shift
    while [ $# -gt 0 ]; do
      case $1 in
        --service-name=*)
          SERVICE_NAME=${1:15}
          shift
          ;;
        *)
          echo "Unknown arg $1"
          exit 1
          ;;
      esac
    done
    ;;
  lock)
    LOCK="true"
    shift
    while [ $# -gt 0 ]; do
      case $1 in
        *)
          echo "Unknown arg $1"
          exit 1
          ;;
      esac
    done
    ;;
  unlock)
    UNLOCK="true"
    shift
    while [ $# -gt 0 ]; do
      case $1 in
        *)
          echo "Unknown arg $1"
          exit 1
          ;;
      esac
    done
    ;;
  setkey)
    SETKEY="true"
    shift
    while [ $# -gt 0 ]; do
      case $1 in
        *)
          echo "Unknown arg $1"
          exit 1
          ;;
      esac
    done
    ;;
  disable)
    DISABLE="true"
    shift
    while [ $# -gt 0 ]; do
      case $1 in
        --service-name=*)
          SERVICE_NAME=${1:15}
          shift
          ;;
        *)
          echo "Unknown arg $1"
          exit 1
          ;;
      esac
    done
    ;;
  enable)
    ENABLE="true"
    shift
    while [ $# -gt 0 ]; do
      case $1 in
        --service-name=*)
          SERVICE_NAME=${1:15}
          shift
          ;;
        *)
          echo "Unknown arg $1"
          exit 1
          ;;
      esac
    done
    ;;
  uninstall)
    UNINSTALL="true"
    shift
    while [ $# -gt 0 ]; do
      case $1 in
        --profile-dir=*)
          ARGS+=("$1")
          SYSTEMD_ARGS+=("$1")
          PROFILE_DIR=${1:14}
          EXECUTABLE=${PROFILE_DIR%/}/kiwi-light
          shift
          ;;
        --service-name=*)
          SERVICE_NAME=${1:15}
          shift
          ;;
        *)
          echo "Unknown arg $1"
          exit 1
          ;;
      esac
    done
    ;;
  modify)
    MODIFY="true"
    shift
    while [ $# -gt 0 ]; do
      case $1 in
        --wgt=*)
          WGT=${1:6}
          shift
          ;;
        --profile-dir=*)
          ARGS+=("$1")
          SYSTEMD_ARGS+=("$1")
          PROFILE_DIR=${1:14}
          EXECUTABLE=${PROFILE_DIR%/}/kiwi-light
          shift
          ;;
        --update=*)
          MANIFEST_URL=${1:9}
          shift
          ;;
        --service-name=*)
          SERVICE_NAME=${1:15}
          shift
          ;;
        --window-position=*)
          WINDOW_POSITION=${1:18}
          shift
          ;;
        --window-mode=*)
          WINDOW_MODE=${1:14}
          shift
          ;;
        --invasive=*)
          SYSTEMD_ARGS+=("$1")
          shift
          ;;
        --low-mem-insecure*)
          SYSTEMD_ARGS+=("$1")
          shift
          ;;
        --env=*)
          ENVIRONMENT+=("${1:6}")
          shift
          ;;
        *)
          echo "Unknown arg $1"
          exit 1
          ;;
      esac
    done
    ;;
  install)
    shift
    ;&
  *)
    while [ $# -gt 0 ]; do
      case $1 in
        --wgt=*)
          WGT=${1:6}
          shift
          ;;
        --profile-dir=*)
          ARGS+=("$1")
          SYSTEMD_ARGS+=("$1")
          PROFILE_DIR=${1:14}
          EXECUTABLE=${PROFILE_DIR%/}/kiwi-light
          shift
          ;;
        --update=*)
          MANIFEST_URL=${1:9}
          shift
          ;;
        --window-position=*)
          WINDOW_POSITION=${1:18}
          shift
          ;;
        --window-mode=*)
          WINDOW_MODE=${1:14}
          shift
          ;;
        --service-name=*)
          SERVICE_NAME=${1:15}
          shift
          ;;
        --disable-autorun)
          DISABLE_AUTORUN="true"
          shift
          ;;
        --invasive=*)
          SYSTEMD_ARGS+=("$1")
          shift
          ;;
        --low-mem-insecure*)
          SYSTEMD_ARGS+=("$1")
          shift
          ;;
        --env=*)
          ENVIRONMENT+=("${1:6}")
          shift
          ;;
        *)
          echo "Unknown arg $1"
          exit 1
          ;;
      esac
    done
    INSTALL="true"
    ;;
esac

# Pokud neinstalujeme a chybí binárka, nemůžeme nic měnit
if [ $INSTALL = "false" ] && [ $UNINSTALL = "false" ] ; then
  if ! [ -f "$EXECUTABLE" ] ; then
    echo "$APP_NAME is not installed, you need to install it first."
    exit 0
  fi
  if ! [ -f "$USER_SYSTEMD_CONFIG_DIR/$SERVICE_NAME.service" ] ; then
    echo "$APP_NAME is not installed correctly, you need to re-install it first."
    exit 0
  fi
fi

# Uninstall
if [ $UNINSTALL = "true" ] ; then
  # Vypnutí služby
  systemctl --user stop "$SERVICE_NAME"
  systemctl --user disable "$SERVICE_NAME"
  # Odstranění souboru služby
  if [ -f "$USER_SYSTEMD_CONFIG_DIR/$SERVICE_NAME.service" ] ; then
      rm "$USER_SYSTEMD_CONFIG_DIR/$SERVICE_NAME.service" 
  fi
  # Reload daemonu po odstranění souboru služby
  systemctl --user daemon-reload
  # Odstranění binárky
  if [ -f "$EXECUTABLE" ] ; then
      rm "$EXECUTABLE"
  fi
  if [ $? -eq 0 ] ; then
    echo "App $APP_NAME has been uninstalled."
  fi
  exit 0
fi

# Start
if [ $START = "true" ] ; then
  # Zapnutí služby
  systemctl --user start "$SERVICE_NAME"
  if [ $? -eq 0 ] ; then
    echo "$SERVICE_NAME service has been started."
  fi
  exit 0
fi

# Stop
if [ $STOP = "true" ] ; then
  # Stopnutí služby
  systemctl --user stop "$SERVICE_NAME"
  if [ $? -eq 0 ] ; then
    echo "$SERVICE_NAME service has been stopped."
  fi
  exit 0
fi

# Lock
if [ $LOCK = "true" ] ; then
  # Zamknutí plochy
  killall lxpanel > /dev/null 2>&1 &
  killall pcmanfm > /dev/null 2>&1 &
  xset s noblank
  xset s off
  xset -dpms
  echo "System has been locked."
  # Check for lock in user autostart
  if grep -Fxq "@bash ~/Downloads/configure.sh lock" "$HOME/.config/lxsession/LXDE-pi/autostart" 2>/dev/null; then
    echo "Autolock already set"
    exit 0
  else
    # Ensure user lxsession directory exists
    mkdir -p $HOME/.config/lxsession/LXDE-pi
    # If user autostart already has text a new line is added
    if [ -s "$HOME/.config/lxsession/LXDE-pi/autostart" ]; then
        echo "" >> "$HOME/.config/lxsession/LXDE-pi/autostart"
    fi
    # Add lock to user autostart
    echo "@bash ~/Downloads/configure.sh lock" >> "$HOME/.config/lxsession/LXDE-pi/autostart"
    echo "Autolock on start set."
  fi
  exit 0
fi

# Unlock
if [ $UNLOCK = "true" ] ; then
  # Odemknutí plochy
  nohup lxpanel --profile LXDE-pi > /dev/null 2>&1 &
  nohup pcmanfm --desktop --profile LXDE-pi > /dev/null 2>&1 &
  echo "System has been unlocked."
  # Check for lock in user autostart
  if grep -Fxq "@bash ~/Downloads/configure.sh lock" "$HOME/.config/lxsession/LXDE-pi/autostart" 2>/dev/null; then
    # Remove the lock line
    sed -i "\|@bash ~/Downloads/configure.sh lock|d" "$HOME/.config/lxsession/LXDE-pi/autostart"
    echo "Removed autolock from user autostart"

    # Check if user autostart is now empty
    if [ ! -s "$HOME/.config/lxsession/LXDE-pi/autostart" ] || ! grep -q '[^[:space:]]' "$HOME/.config/lxsession/LXDE-pi/autostart"; then
      rm -f "$HOME/.config/lxsession/LXDE-pi/autostart"
      echo "User autostart file removed as it is now empty"
    fi
  else
    echo "No autolock in user autostart."
  fi
  exit 0
fi

# Setkey
if [ $SETKEY = "true" ] ; then
  # Nastavení klávesových zkratek
  echo "Setting keyboard shortcuts..."
  # Ensure the rc.xml file exists
  if [ ! -f "$HOME/.config/openbox/lxde-pi-rc.xml" ]; then
    echo "User keybind settings file not found. Creating..."
    mkdir -p $HOME/.config/openbox/ && cp /etc/xdg/openbox/lxde-pi-rc.xml $HOME/.config/openbox/
    echo "User keybind file created."
  fi

  # Define keybindings and their commands
  declare -A KEYBINDS=(
    ["C-A-i"]="~/Downloads/configure.sh lock"
    ["C-A-u"]="~/Downloads/configure.sh unlock"
  )

  # Add keybinds if they are not already present
  for KEY in "${!KEYBINDS[@]}"; do
    if ! grep -q "key=\"$KEY\"" "$HOME/.config/openbox/lxde-pi-rc.xml"; then
      awk "/<\/keyboard>/ {
        print \"  <keybind key=\\\"$KEY\\\">\";
        print \"    <action name=\\\"Execute\\\">\";
        print \"      <command>bash -c \\\"${KEYBINDS[$KEY]}\\\"</command>\";
        print \"    </action>\";
        print \"  </keybind>\";
        print \"\";
      }1" "$HOME/.config/openbox/lxde-pi-rc.xml" > "$HOME/.config/openbox/lxde-pi-rc.xml.tmp" && mv "$HOME/.config/openbox/lxde-pi-rc.xml.tmp" "$HOME/.config/openbox/lxde-pi-rc.xml"
      echo "Added keybind: $KEY -> ${KEYBINDS[$KEY]}"
    else
      echo "Keybind already exists: $KEY (skipped)."
    fi
  done
  # Restart Openbox to apply changes
  openbox --reconfigure
  exit 0
fi

# Disable
if [ $DISABLE = "true" ] ; then
  # Odregistrování služby
  systemctl --user disable "$SERVICE_NAME"
  if [ $? -eq 0 ] ; then
    echo "$SERVICE_NAME service has been disabled."
  fi
  exit 0
fi

# Enable
if [ $ENABLE = "true" ] ; then
  # Není nutné vytvářet znova službu s novými argumenty pro aplikaci
  systemctl --user enable "$SERVICE_NAME"
  if [ $? -eq 0 ] ; then
    echo "$SERVICE_NAME service has been enabled."
  fi
  exit 0
fi

# Install
if [ $MODIFY = "false" ] && [ -n "$MANIFEST_URL" ]; then
  if [ -f "$EXECUTABLE" ] ; then
    echo "$APP_NAME already installed. Please uninstall app first."
    exit 0
  fi

  # Získání url k té správné binárce
  MANIFEST=$(wget "$MANIFEST_URL" -q -O -)
  # Předpokládá, že v manifestu je pouze jedna položka "version"
  VERSION=$(grep -Po '("version"\s*:\s*"\K).*(?=")' <<< "$MANIFEST")

  if [ -z "$VERSION" ] ; then
    echo "Installation was not succesfull. Error getting version from manifest."
    exit 1
  fi

  DOWNLOAD_URL=${MANIFEST_URL%/*}/${VERSION/+/"%2B"}/$ARCH_SUFFIX

  # Stažení binárky
  mkdir -p "$(dirname "${EXECUTABLE}")"

  wget "$DOWNLOAD_URL" -O "$EXECUTABLE"

  if [ $? -ne 0 ] ; then
    rm "$EXECUTABLE"
    echo "Installation was not succesfull. Download failed."
    exit 1
  fi

  chmod +x "$EXECUTABLE"
  chmod +x configure.sh
  
fi

# Nastavení update kanálu, pokud se nejedná o default
if [[ $DEFAULT_MANIFEST_URL != "$MANIFEST_URL" ]] ; then
  "$EXECUTABLE" "${ARGS[@]}" set update "$MANIFEST_URL"
fi

# Nastavení wgt, pokud je zadané
if [[ $WGT != "" ]] ; then
  "$EXECUTABLE" "${ARGS[@]}" set wgt "$WGT"
fi

# Nastavení pozice, pokud je zadaná
if [[ $WINDOW_POSITION != "" ]] ; then
  "$EXECUTABLE" "${ARGS[@]}" set window-position "$WINDOW_POSITION"
fi

# Nastavení režimu oknu, pokud je zadán
if [[ $WINDOW_MODE != "" ]] ; then
  "$EXECUTABLE" "${ARGS[@]}" set window-mode "$WINDOW_MODE"
fi

mkdir -p "$USER_SYSTEMD_CONFIG_DIR"

# https://www.freedesktop.org/software/systemd/man/systemd.service.html#Command%20lines
systemd_execstart_maybe_quote () {
  sed -e 's/\\/\\\\/g' -e 's/"/\\"/g' -e 's/\$/\$\$/g' -e '/[ ";|<>]/s/^\(.*\)$/"\0"/'
}

print_systemd_execstart_maybe_quote () {
  echo -n "$1" | systemd_execstart_maybe_quote
}

# TODO: Quotování Environment=: https://stackoverflow.com/questions/43278883/how-to-write-systemd-environment-variables-value-which-contains
cat > "$USER_SYSTEMD_CONFIG_DIR/$SERVICE_NAME.service" << EOF
[Unit]
After=graphical-session.target
Description=$SERVICE_NAME
StartLimitIntervalSec=0
Wants=graphical-session.target

[Service]$(for e in "${ENVIRONMENT[@]}" ; do printf '\nEnvironment=%s' "$e" ; done)
ExecStart=$(print_systemd_execstart_maybe_quote "${EXECUTABLE}" ; for a in "${SYSTEMD_ARGS[@]}" ; do echo -n ' ' ; print_systemd_execstart_maybe_quote "$a" ; done)
Restart=always
RestartSec=5
SyslogIdentifier=$SERVICE_NAME

[Install]
WantedBy=default.target
EOF

if [ $DISABLE_AUTORUN = "true" ] ; then
  exit 0
fi

systemctl --user daemon-reload
systemctl --user start "$SERVICE_NAME"
systemctl --user enable "$SERVICE_NAME"

echo "$SERVICE_NAME service has been created and enabled."
