#!/bin/bash

# install LeTTo and docker on Ubuntu LTS and
# configure proxy, mysql, setup

# ---------------------------------------------------------------------------------------------------------------------
# you can set the all credentials here or leave it blank to read from commandline

# password for the user 'admin' in the web-configuration-site
# if user letto is previously not installed the password is used for the new user letto
password=

# Base directory for Server-Installation
lettobase=/opt/letto

# local version from LeTTo-setup start and install on/off - default off
startlocal=off

# ---------------------------------------------------------------------------------------------------------------------

echo Install LeTTo-Setup
echo

export DEBIAN_FRONTEND=noninteractive

apt install lsb-release -y

ubuntu=$(lsb_release -d | grep "Ubuntu" | wc -l)
ubuntu1804=$(lsb_release -d | grep "Ubuntu 18.04" | wc -l)
ubuntu2004=$(lsb_release -d | grep "Ubuntu 20.04" | wc -l)
ubuntu2204=$(lsb_release -d | grep "Ubuntu 22.04" | wc -l)
ubuntu2404=$(lsb_release -d | grep "Ubuntu 24.04" | wc -l)
debian=$(lsb_release -d | grep "Debian GNU/Linux" | wc -l)
debian11=$(lsb_release -d | grep "Debian GNU/Linux 11" | wc -l)
debian12=$(lsb_release -d | grep "Debian GNU/Linux 12" | wc -l)
debian13=$(lsb_release -d | grep "Debian GNU/Linux 13" | wc -l)

# check if root-rights are available
if [ `id -u` = 0 ] ; then
    echo Install is running as root!
    echo Installs docker if not installed
    echo Creates user \"letto\" if not exists
    echo Configure user \"letto\" to be a docker admin
    echo install setup-service in Docker-Container on Port 8096-http - please do not open the port to the internet!!
    echo setup-service will be started from /etc/rc.local
    echo setup start and stop scripts are located in $lettobase/setup
else
    echo No root rights! Please start setup as root!
    exit 1
fi

if [ $ubuntu -eq 1 ] ; then
  arch=ubuntu
elif [ $debian -eq 1 ] ; then
  arch=debian
else
  echo please run script only on Ubuntu or Debian or adapt script to your linux-distribution
  exit 1
fi

# commandline-parameters
for i in $@ ; do
  # password
  if [[ $i == "-p"* ]] ; then
    password=${i:2}
  fi
done

# password for user admin in the setup
if [ -z $password ] ; then
  echo
  if getent passwd letto >/dev/null ; then
    echo "Set password for the user 'admin' in the web-configuration-site - No Passwort to cancel installation."
  else
    echo "Set password for the linux-user 'letto' and the user 'admin' in the web-configuration-site - No Passwort to cancel installation."
  fi
  echo -n password:
  read -s password
  echo
fi

if [ -z $password ] ; then
  echo Installation cancelled!
  exit 1
fi

# update all
apt-get -y update && \
apt-get -y upgrade && \
apt-get -y dist-upgrade && \
apt-get -y autoremove
if ! [ $? -eq 0 ] ; then echo "error - install cancelled!"; exit 1; fi
echo system is up to date

# install packages
apt-get install -y apt-utils apt-transport-https gnupg2 dirmngr && \
apt-get install -y zip less nano unzip wget net-tools gawk && \
apt-get install -y htop iputils-ping dos2unix curl && \
apt-get install -y ca-certificates curl lsb-release
if ! [ $? -eq 0 ] ; then echo "error - install cancelled!"; exit 1; fi
echo needed linux-packages installed

echo install java 21 jdk
if [ $ubuntu -eq 1 ] ; then
  apt-get -y install openjdk-21-jre openjdk-21-jdk openjdk-21-jre-headless openjdk-21-source
  if ! [ $? -eq 0 ] ; then echo "cannot install java 21 - install cancelled!"; exit 1; fi
elif [ $debian -eq 1 ] ; then
  wget -qO - https://packages.adoptium.net/artifactory/api/gpg/key/public | tee /etc/apt/trusted.gpg.d/adoptium.asc
  echo "deb https://packages.adoptium.net/artifactory/deb $(lsb_release -cs) main" | tee /etc/apt/sources.list.d/adoptium.list
  apt update
  apt install -y temurin-21-jdk
  # apt install -y openjdk-21-jre openjdk-21-jdk openjdk-21-jre-headless openjdk-21-source
  if ! [ $? -eq 0 ] ; then echo "cannot install java 21 - install cancelled!"; exit 1; fi
else
  if java -version 2>&1 | grep -q "version" ; then
    echo Java installed
  else
    echo please install java JDK greater oder equals Java-21 and rerun script
    exit 1
  fi
fi

# check if user letto is present and create if not
if getent passwd letto >/dev/null; then
  echo user letto exists
else
  apt-get -y update
  apt-get -y install openssl
  /sbin/useradd -rm -d /home/letto -s /bin/bash letto -p "$(openssl passwd -1 $password)"
  /sbin/adduser --gecos letto,0,0,0 letto
  if getent passwd letto >/dev/null; then
    echo user letto correctly installed
  else
    echo please create user letto with group letto
    exit 1
  fi
fi

if getent group letto >/dev/null; then
  echo group letto exists
else
  /sbin/addgroup letto
fi

if getent group letto | grep -q "\bletto\b"; then
    echo letto is in group letto
else
    /sbin/adduser letto letto
fi

# uid from user letto
lettouid=$(id letto | awk '{match($0,"uid=([0-9]+)\\(",a)}END{print a[1]}')

# check and install docker
curl -fsSL https://download.docker.com/linux/$arch/gpg | gpg --dearmor -o /usr/share/keyrings/docker-archive-keyring.gpg && \
echo "deb [arch=$(dpkg --print-architecture) signed-by=/usr/share/keyrings/docker-archive-keyring.gpg] https://download.docker.com/linux/$arch $(lsb_release -cs) stable" | tee /etc/apt/sources.list.d/docker.list >/dev/null && \
apt-get -y update && \
apt-get -y install docker-ce docker-ce-cli containerd.io docker-compose-plugin
if ! [ $? -eq 0 ] ; then echo "error - install cancelled!"; exit 1; fi

if docker version | grep -q Docker; then
  echo docker installed
else
  echo please install docker
  echo script cancelled!
  exit 1
fi

# check and install docker compose
dockercompose=
if docker compose version 2>>/dev/null | grep -q "Docker Compose"; then
  echo docker compose is installed
  dockercompose="docker compose"
else
  apt-get -y install docker-compose-plugin
  if docker compose version 2>>/dev/null | grep -q "Docker Compose"; then
    echo docker compose is installed
    dockercompose="docker compose"
  fi
fi
if [ -z $dockercompose ] ; then
    echo please install docker compose plugin
    echo script cancelled!
    exit 1
fi

# add user letto to docker group
if getent group docker | grep -q "\bletto\b"; then
    echo letto is in group docker
else
    /sbin/adduser letto docker
fi

# create paths
echo create paths
mkdir $lettobase -p
mkdir $lettobase/setup -p
mkdir $lettobase/docker -p
mkdir $lettobase/docker/compose -p
mkdir $lettobase/docker/compose/setup -p
mkdir $lettobase/docker/compose/letto -p
mkdir $lettobase/docker/compose/mysql -p
mkdir $lettobase/docker/proxy -p
mkdir $lettobase/docker/public -p
mkdir $lettobase/docker/storage -p
mkdir $lettobase/docker/storage/database -p
mkdir $lettobase/docker/storage/database-dump -p
mkdir $lettobase/docker/storage/database-backup -p
mkdir $lettobase/docker/storage/images -p
mkdir $lettobase/docker/storage/photos -p
mkdir $lettobase/docker/storage/plugins -p
mkdir $lettobase/docker/storage/projekte -p
mkdir $lettobase/docker/storage/print -p
mkdir $lettobase/docker/storage/export -p
mkdir $lettobase/docker/storage/backup -p
mkdir $lettobase/docker/storage/log    -p
mkdir $lettobase/docker/storage/log/letto    -p
mkdir $lettobase/docker/storage/log/data    -p

# create standard startpage in public
echo "<!DOCTYPE html>" >$lettobase/docker/public/index.html
echo "<html lang=\"de\">" >>$lettobase/docker/public/index.html
echo "<head>" >>$lettobase/docker/public/index.html
echo "   <meta charset=\"UTF-8\">" >>$lettobase/docker/public/index.html
echo "   <title>LeTTo-Server</title>" >>$lettobase/docker/public/index.html
echo "</head>" >>$lettobase/docker/public/index.html
echo "<body>" >>$lettobase/docker/public/index.html
echo "   <a href=\"https://letto.at\"><img src=\"/img/LeTTo_Logo_animated_10.gif\"/></a><br>" >>$lettobase/docker/public/index.html
echo "   <h1>LeTTo Server - running !</h1>" >>$lettobase/docker/public/index.html
echo "   <a href=\"/config\">Setup</a><br>" >>$lettobase/docker/public/index.html
echo "</body>" >>$lettobase/docker/public/index.html

# create setup on localhost
cd $lettobase/setup
rm $lettobase/setup/lettosetup.jar -f
wget --no-check-certificate --auth-no-challenge -c https://build.letto.at/download/setup/stable/lettosetup.jar         -O $lettobase/setup/lettosetup.jar
wget --no-check-certificate --auth-no-challenge -c https://build.letto.at/download/setup/statuslettosetup.sh    -O $lettobase/setup/statuslettosetup.sh
wget --no-check-certificate --auth-no-challenge -c https://build.letto.at/download/setup/startlettosetup.sh     -O $lettobase/setup/startlettosetup.sh
wget --no-check-certificate --auth-no-challenge -c https://build.letto.at/download/setup/stoplettosetup.sh      -O $lettobase/setup/stoplettosetup.sh
wget --no-check-certificate --auth-no-challenge -c https://build.letto.at/download/setup/updatelettosetup.sh    -O $lettobase/setup/updatelettosetup.sh
wget --no-check-certificate --auth-no-challenge -c https://build.letto.at/download/setup/application.properties -O $lettobase/setup/application.properties

echo "letto.path.setup=$lettobase/setup" >$lettobase/setup/application.properties
echo "letto.path.docker=$lettobase/docker" >>$lettobase/setup/application.properties
echo "LETTO_UID=$lettouid" >>$lettobase/setup/application.properties
echo "ADMIN_PASSWORD=$password" >>$lettobase/setup/application.properties
echo "RUN_AS_ROOT=true"        >>$lettobase/setup/application.properties
echo "LETTO_RESTKEY="          >>$lettobase/setup/application.properties
echo "LETTO_PATH=$lettobase"                              >>$lettobase/setup/application.properties
echo "SETUP_COMPOSE=$lettobase/docker/compose/setup"      >>$lettobase/setup/application.properties
echo "LETTO_COMPOSE=$lettobase/docker/compose/letto"      >>$lettobase/setup/application.properties
echo "HOST_BS=LINUX"                                      >>$lettobase/setup/application.properties
echo "PATH_SEPERATOR=/"                                   >>$lettobase/setup/application.properties
echo "DEBUG=false"             >>$lettobase/setup/application.properties
echo "STABLE=false"            >>$lettobase/setup/application.properties

chmod 755 -R $lettobase/setup
chown letto -R $lettobase/setup
chgrp letto -R $lettobase/setup

if [ $startlocal == "on" ] ; then
  echo start local version of LeTTo-Setup
  $lettobase/setup/stoplettosetup.sh
  $lettobase/setup/startlettosetup.sh
  # add setup to autostart rc.local if ubuntu
  if [ -e /etc/rc.local ]; then
    if [ $(cat /etc/rc.local|grep startlettosetup.sh| wc -l) -gt 0 ] ; then
      # 1 or more lines with the startscript exist, replace them with startscript
      cp /etc/rc.local /etc/rc.local.si && \
      sed "s/[^\n]*startlettosetup.sh[^\n]*/\/opt\/letto\/setup\/startlettosetup.sh/g" /etc/rc.local.si >/etc/rc.local && \
      rm /etc/rc.local.si
    else
      # startsccript not exists in rc.local insert at second row
      cp /etc/rc.local /etc/rc.local.si && \
      ix=0 && \
      rm /etc/rc.local && \
      while IFS= read p; do
        ix="$(expr $ix + 1)"
        echo "$p" >>/etc/rc.local
        if [ $ix -eq 1 ] ; then echo /opt/letto/setup/startlettosetup.sh >>/etc/rc.local; fi
      done </etc/rc.local.si && \
      rm /etc/rc.local.si
    fi
  else
    echo start /opt/letto/setup/startlettosetup.sh automatically at system startup
    echo '#!/bin/bash' >/etc/rc.local
    echo "$lettobase/setup/startlettosetup.sh" >>/etc/rc.local
    echo "exit 0" >>/etc/rc.local
  fi
  chmod 755 /etc/rc.local
fi

# create Base-Konfiguration
rm $lettobase/docker/compose/setup/docker-compose.yml -f
wget --no-check-certificate --auth-no-challenge -c https://build.letto.at/download/install/yml/docker-compose-setup.yml -O $lettobase/docker/compose/setup/docker-compose.yml

echo "ADMIN_PASSWORD=$password" >$lettobase/docker/compose/setup/.env
echo "LETTO_UID=$lettouid"     >>$lettobase/docker/compose/setup/.env
echo "HTTPS_PORT=3096"         >>$lettobase/docker/compose/setup/.env
echo "RUN_AS_ROOT=true"        >>$lettobase/docker/compose/setup/.env
echo "LETTO_RESTKEY="          >>$lettobase/docker/compose/setup/.env
echo "LETTO_PATH=$lettobase"                              >>$lettobase/docker/compose/setup/.env
echo "SETUP_COMPOSE=$lettobase/docker/compose/setup"      >>$lettobase/docker/compose/setup/.env
echo "LETTO_COMPOSE=$lettobase/docker/compose/letto"      >>$lettobase/docker/compose/setup/.env
echo "HOST_BS=LINUX"                                      >>$lettobase/docker/compose/setup/.env
echo "PATH_SEPERATOR=/"                                   >>$lettobase/docker/compose/setup/.env
echo "DEBUG=false"             >>$lettobase/docker/compose/setup/.env
echo "STABLE=false"            >>$lettobase/docker/compose/setup/.env

if [ $debian -eq 1 ] ; then
  service docker restart
  systemctl is-enabled docker
  systemctl is-enabled containerd
  systemctl status docker containerd
  echo "give docker some time to start correctly and wait a minute"
  sleep 60
  service docker restart
  sleep 2
fi

# create docker networks
echo create Network nw-letto
docker network create nw-letto
echo create Network nw-proxy
docker network create nw-proxy

# create docker Volumes
echo create Volume certs-data, certs, lettomysql
docker volume create certs
docker volume create certs-data
docker volume create lettomysql

docker ps
if ! [ $? -eq 0 ] ; then
  echo "cannot start docker service correctly please check and start 'docker compose up -d' from directory $lettobase/docker/compose/setup/ later.";
else
  cd $lettobase/docker/compose/setup
  $dockercompose pull
  $dockercompose up -d
fi

echo set rights for user letto
chmod 755    -R /opt/letto/docker
chown letto  -R /opt/letto/docker
chgrp letto  -R /opt/letto/docker

# detect ip address
MYIP=$(ip route get 1.1.1.1 | grep -oP 'src \K[0-9.]+')

echo
echo visit https://$MYIP:3096/config to configure LeTTo-Host Setup
if [ $startlocal == "on" ] ; then
  echo or if you have problems you can also visit the local installation
  echo on https://$MYIP:9096/setup
  echo
fi

echo finished!