#!/usr/bin/env bash

set -eu

red='\e[0;31m'
yellow='\e[1;33m'
cyan='\e[0;36m'
reset='\e[0m'

info() {
  printf "${cyan}info: $*${reset}\n"
}

warning() {
  printf >&2 "${yellow}warning: $*${reset}\n"
}

error() {
  printf >&2 "${red}error: $*${reset}\n"
  exit 1
}

section() {
  text="$*"
  printf -v bar '═%.0s' {1..78}
  printf -v fill ' %.0s' {1..76}
  printf "$cyan"
  printf '╔%s╗\n' "$bar"
  printf '║ %s ║\n' "${text}${fill:${#text}}"
  printf '╚%s╝\n' "$bar"
  printf "$reset"
}

banner() {
  printf "${cyan}"
  cat << EOF

  ██╗     ██╗██████╗ ██████╗ ███████╗████████╗██╗███╗   ███╗███████╗
  ██║     ██║██╔══██╗██╔══██╗██╔════╝╚══██╔══╝██║████╗ ████║██╔════╝
  ██║     ██║██████╔╝██████╔╝█████╗     ██║   ██║██╔████╔██║█████╗
  ██║     ██║██╔══██╗██╔══██╗██╔══╝     ██║   ██║██║╚██╔╝██║██╔══╝
  ███████╗██║██████╔╝██║  ██║███████╗   ██║   ██║██║ ╚═╝ ██║███████╗
  ╚══════╝╚═╝╚═════╝ ╚═╝  ╚═╝╚══════╝   ╚═╝   ╚═╝╚═╝     ╚═╝╚══════╝

EOF
  printf "${reset}"
}

SCRIPT_DIR="$( cd "$( dirname "$0")" && pwd)"

version() {
  if [ ! -f "$SCRIPT_DIR/VERSION" ]; then
    make VERSION > /dev/null
  fi
  echo "LibreTime Version $(cat "$SCRIPT_DIR/VERSION")"
  exit 0
}

usage() {
  cat >&2 << EOF
Usage: $0 [option]... [public_url]

  Install LibreTime on the system.

Options:

  --user USER, -u USER          User used to run LibreTime.
  --listen-port PORT, -p PORT   Listen port for LibreTime.
  --storage-path PATH, -s PATH  Storage path for LibreTime.

  --in-place, -i                Install LibreTime in place.

  --no-setup-icecast            Do not setup Icecast.
  --no-setup-postgresql         Do not setup Postgresql.
  --no-setup-rabbitmq           Do not setup RabbitMQ.

Environment variables:

  Advanced options can be changed using environment variables (flags will take
  precedence over environment variables).

EOF

  while read line; do
    if echo "$line" | grep -q '^#'; then
      line="${cyan}${line}${reset}"
    fi

    # Pretty print variable definition
    line=$(echo "$line" | sed -E 's/=\$\{[A-Z_]+\:-(.*)\}/=\1/g')

    printf "  ${line}\n"
  done <<< "$(grep -A1 '^# >' "$0")"
}

# Load .env file if exists
[[ -f "$SCRIPT_DIR/.env" ]] && source "$SCRIPT_DIR/.env"

# Configuration
# > User used to run LibreTime.
LIBRETIME_USER=${LIBRETIME_USER:-"libretime"}
# > Listen port for LibreTime.
LIBRETIME_LISTEN_PORT=${LIBRETIME_LISTEN_PORT:-"8080"}
# > Public URL for LibreTime.
LIBRETIME_PUBLIC_URL=${LIBRETIME_PUBLIC_URL:-}
# > Timezone for LibreTime.
LIBRETIME_TIMEZONE=${LIBRETIME_TIMEZONE:-}
# > Storage path for LibreTime.
LIBRETIME_STORAGE_PATH=${LIBRETIME_STORAGE_PATH:-"/srv/libretime"}

# > Install LibreTime in editable mode.
# > Will keep working files in the project directory.
LIBRETIME_INSTALL_IN_PLACE=${LIBRETIME_INSTALL_IN_PLACE:-false}
# > Install a default icecast configuration.
LIBRETIME_SETUP_ICECAST=${LIBRETIME_SETUP_ICECAST:-true}
# > Create a default postgresql user with a random password.
LIBRETIME_SETUP_POSTGRESQL=${LIBRETIME_SETUP_POSTGRESQL:-true}
# > Create a default rabbitmq user with a random password.
LIBRETIME_SETUP_RABBITMQ=${LIBRETIME_SETUP_RABBITMQ:-true}

# > Comma separated list of sections to exclude from packages list.
LIBRETIME_PACKAGES_EXCLUDES=${LIBRETIME_PACKAGES_EXCLUDES:-}

while [[ $# -gt 0 ]]; do
  case "$1" in
    --user | -u)
      LIBRETIME_USER=$2
      shift 2
      ;;
    --listen-port | -p)
      LIBRETIME_LISTEN_PORT=$2
      shift 2
      ;;
    --storage-path | -s)
      LIBRETIME_STORAGE_PATH=$2
      shift 2
      ;;
    --in-place | -i)
      LIBRETIME_INSTALL_IN_PLACE=true
      shift 1
      ;;
    --update-nginx)
      error "the '--update-nginx' option was removed in 4.0.0"
      ;;
    --no-setup-icecast)
      LIBRETIME_SETUP_ICECAST=false
      shift 1
      ;;
    --no-setup-postgresql)
      LIBRETIME_SETUP_POSTGRESQL=false
      shift 1
      ;;
    --no-setup-rabbitmq)
      LIBRETIME_SETUP_RABBITMQ=false
      shift 1
      ;;
    --packages-excludes)
      LIBRETIME_PACKAGES_EXCLUDES=$2
      shift 2
      ;;
    --help | -h)
      usage
      exit 0
      ;;
    --version)
      version
      exit 0
      ;;
    -*)
      usage
      exit 1
      ;;
    *)
      LIBRETIME_PUBLIC_URL=$1
      shift 1
      ;;
  esac
done

# Variables
DEFAULT_WEB_USER="www-data"

# Paths
VENV_DIR="/opt/libretime"
CONFIG_DIR="/etc/libretime"
CONFIG_FILEPATH="$CONFIG_DIR/config.yml"
CONFIG_TMP_FILEPATH="$CONFIG_DIR/config.yml.tmp"
CONFIG_EXAMPLE_FILEPATH="$SCRIPT_DIR/installer/config.yml"
WORKING_DIR="/var/lib/libretime"
LOG_DIR="/var/log/libretime"
LEGACY_WEB_ROOT="/usr/share/libretime/legacy"

SERVICE_DIR="/usr/lib/systemd/system"

# command_exist <command>
command_exist() {
  command -v "$1" > /dev/null || error "$1 command not found!"
}

# generate_random_password
generate_random_password() {
  tr -cd '[:alnum:]' < /dev/urandom | head -c32
}

# mkdir_and_chown <user> <path>
mkdir_and_chown() {
  mkdir -p "$2"
  chown -R "$1:$1" "$2"
}

# backup_if_exists <file>
backup_if_exists() {
  if [[ -f "$1" ]]; then
    backup="$1.$(date --iso-8601=seconds).bak"
    warning "found existing $1, creating a backup to $backup"
    mv "$1" "$backup"
  fi
}

# diff_if_exists <src> <dest>
diff_if_exists() {
  src="$1"
  dest="$2"
  shift 2

  if [[ -f "$dest" ]]; then
    src_explicit_filename="$(dirname "$src")/$(basename "$dest").new"
    cp "$src" "$src_explicit_filename"
    # print what the existing file $dest would become if $src is copied
    diff -u --color=always --ignore-trailing-space "$dest" "$src_explicit_filename" || :
    rm -f "$src_explicit_filename"
  fi
}

# cp_if_different <src> <dest>
cp_if_different() {
  if [[ -f "$2" ]] && diff -q "$1" "$2" > /dev/null; then
    return
  fi
  diff_if_exists "$1" "$2"
  backup_if_exists "$2"
  cp "$1" "$2"
}

# template_file <action> <src> <dest> <render...>
template_file() {
  action="$1"
  src="$2"
  dest="$3"
  shift 3

  tmp_file=$(mktemp)
  "$@" "$src" > "$tmp_file"
  $action "$tmp_file" "$dest"
  rm "$tmp_file"
}

# get_config <key...>
get_config() {
  query="/^${1}:/\n"
  while [[ $# -gt 1 ]]; do
    shift
    query+="/ \+${1}:/\n"
  done
  query+="q"

  echo -e "$query" | ed --quiet "$CONFIG_FILEPATH" |
    tail -n 2 |
    grep "$1" |
    awk -F ': ' '{ print $2 }'
}

# set_config <value> <key...>
set_config() {
  value="${1}" && shift

  query="/^${1}:/\n"
  while [[ $# -gt 1 ]]; do
    shift
    query+="/ \+${1}:/\n"
  done
  query+="s|\(${1}:\).*|\1 ${value}|\n"
  query+="wq"

  echo -e "$query" | ed --quiet "$CONFIG_TMP_FILEPATH" > /dev/null
}

# install_python_app <path>
install_python_app()  {
  info "installing python app from $1"
  $VENV_DIR/bin/pip install --upgrade "$1"
}

# link_python_app <name>
link_python_app() {
  ln -s -f "$VENV_DIR/bin/$1" "/usr/local/bin/$1"
}

# install_service <name> <filepath>
#
# <filepath> has to be relative to the project root
install_service() {
  command_exist systemctl

  local service_name="$1"
  local service_src="$2"
  local service_dest="$SERVICE_DIR/$service_name"

  info "deploying $service_name service"

  [[ -f "$service_src" ]] || error "service '$service_name' src path '$service_src' does not exists!"

  if [[ ! -d "$SERVICE_DIR" ]]; then
    mkdir -p "$SERVICE_DIR"
  fi

  template_file cp_if_different "$service_src" "$service_dest" \
    sed \
      -e "s|^User=.*|User=${LIBRETIME_USER}|" \
      -e "s|^Group=.*|Group=${LIBRETIME_USER}|" \
      -e "s|@@DEFAULT_WEB_USER@@|${DEFAULT_WEB_USER}|g" \
      -e "s|@@VENV_DIR@@|${VENV_DIR}|g" \
      -e "s|@@CONFIG_DIR@@|${CONFIG_DIR}|g" \
      -e "s|@@CONFIG_FILEPATH@@|${CONFIG_FILEPATH}|g" \
      -e "s|@@LOG_DIR@@|${LOG_DIR}|g" \
      -e "s|@@WORKING_DIR@@|${WORKING_DIR}|g"

  chmod 0644 "$service_dest"
  chown root:root "$service_dest"
  systemctl enable "$service_name"
}

# service_restart_if_active <name>
service_restart_if_active() {
  if systemctl is-active "$1" > /dev/null; then
    info "restarting $1 service"
    systemctl restart "$1"
  fi
}

is_ubuntu=false
is_debian=false
distro="unknown"

check_distribution()  {
  local ID="unknown"
  local VERSION_ID="unknown"

  if [[ -f "/etc/os-release" ]]; then
    source "/etc/os-release"
  fi

  # shellcheck disable=SC2034
  case "$ID-$VERSION_ID" in
    ubuntu-20.04) is_ubuntu=true && distro="focal" ;;
    debian-11)    is_debian=true && distro="bullseye" ;;
    *)
      error "could not determine supported distribution '$ID-$VERSION_ID'

Please check the documentation to find the supported distributions.

Support for installing LibreTime on Buster has dropped since 3.1.0.
Support for installing LibreTime on Bionic has dropped since 3.1.0.
Support for installing LibreTime on Xenial has dropped since 3.0.0-alpha.10.
Support for installing LibreTime on Stretch has dropped since 3.0.0-alpha.10.
Support for installing LibreTime on Jessie has dropped since 3.0.0-alpha.8."
      ;;
  esac
}

# list_packages <packages_file>
list_packages() {
  extra_args=()
  for section in $LIBRETIME_PACKAGES_EXCLUDES; do
    extra_args+=("--exclude=$section")
  done

  "$SCRIPT_DIR/tools/packages.py" \
    "$distro" \
    "$1" \
    --format=line \
    "${extra_args[@]}"
}

prepare_packages_install() {
  if $is_ubuntu || $is_debian; then
    DEBIAN_FRONTEND=noninteractive apt-get -q update
  fi

  if $is_ubuntu; then
    install_packages software-properties-common
    add-apt-repository -y ppa:libretime/libretime

    DEBIAN_FRONTEND=noninteractive apt-get -q update
  fi
}

# install_packages <packages...>
install_packages() {
  if $is_ubuntu || $is_debian; then
    # shellcheck disable=SC2086
    DEBIAN_FRONTEND=noninteractive apt-get -qq -y install "$@"
  else
    warning "installing dependencies is not supported for this distribution"
  fi
}

# get_system_timezone
get_system_timezone() {
  if ! command -v timedatectl > /dev/null; then
    return
  fi

  timezone="$(timedatectl show --property=Timezone --value)"
  if [[ -n "$timezone" && ! "$timezone" =~ UTC$ ]]; then
    echo "$timezone"
  fi
}

load_config_defaults() {
  if [[ -z "$LIBRETIME_TIMEZONE" ]]; then
    LIBRETIME_TIMEZONE="$(get_system_timezone)"
  fi
}

# Prepare
########################################################################################

# Make sure only root can run our script
(($( id -u) == 0))  || error "this script must be run as root!"

banner
check_distribution

load_config_defaults

is_first_install=true
if [[ -f "$CONFIG_FILEPATH" ]]; then
  is_first_install=false
  warning "a configuration file already exists at $CONFIG_FILEPATH, only running upgrade steps!"
fi

section "Prepare"

prepare_packages_install

install_packages sudo git make ed
make VERSION

info "creating project user"
if ! id "$LIBRETIME_USER" &> /dev/null; then
  useradd --no-create-home --home-dir "$WORKING_DIR" "$LIBRETIME_USER"
fi

info "creating project directories"
mkdir -p "$CONFIG_DIR"
mkdir_and_chown "$LIBRETIME_USER" "$WORKING_DIR"
mkdir_and_chown "$LIBRETIME_USER" "$LOG_DIR"

if $is_first_install; then
  [[ -f "$CONFIG_TMP_FILEPATH" ]] || cp "$CONFIG_EXAMPLE_FILEPATH" "$CONFIG_TMP_FILEPATH"
  chown "$LIBRETIME_USER:$LIBRETIME_USER" "$CONFIG_TMP_FILEPATH"
  chmod 640 "$CONFIG_TMP_FILEPATH"

  if [[ -n "$LIBRETIME_PUBLIC_URL" ]]; then
    set_config "$LIBRETIME_PUBLIC_URL" general public_url
  fi
  set_config "$(generate_random_password)" general api_key

  set_config "$(generate_random_password)" general secret_key

  if [[ -n "$LIBRETIME_TIMEZONE" ]]; then
    set_config "$LIBRETIME_TIMEZONE"  general timezone
  fi

  mkdir_and_chown "$LIBRETIME_USER" "$LIBRETIME_STORAGE_PATH"
  set_config "$LIBRETIME_STORAGE_PATH" storage path
else
  if [[ "$LIBRETIME_STORAGE_PATH" != "$(get_config storage path)" ]]; then
    error \
      "configuration mismatch between" \
      "the installer storage path option ('$LIBRETIME_STORAGE_PATH') and" \
      "the configuration file 'storage.path' field ('$(get_config storage path)')"
  fi
fi

# PostgreSQL
########################################################################################

# > LibreTime PostgreSQL user
LIBRETIME_POSTGRESQL_USER=${LIBRETIME_POSTGRESQL_USER:-"libretime"}
# > LibreTime PostgreSQL user password
LIBRETIME_POSTGRESQL_PASSWORD=${LIBRETIME_POSTGRESQL_PASSWORD:-$(generate_random_password)}
# > LibreTime PostgreSQL database
LIBRETIME_POSTGRESQL_DATABASE=${LIBRETIME_POSTGRESQL_DATABASE:-"libretime"}

if $LIBRETIME_SETUP_POSTGRESQL; then
  section "PostgreSQL"
  install_packages postgresql postgresql-client

  if $is_first_install; then
    if ! sudo -iH -u postgres psql --csv --tuples-only --command='\du' | grep -qw "^$LIBRETIME_POSTGRESQL_USER"; then
      info "creating PostgreSQL user '$LIBRETIME_POSTGRESQL_USER'"
      sudo -iH -u postgres createuser "$LIBRETIME_POSTGRESQL_USER"
      sudo -iH -u postgres psql -c "ALTER ROLE $LIBRETIME_POSTGRESQL_USER WITH PASSWORD '$LIBRETIME_POSTGRESQL_PASSWORD';"

      set_config "$LIBRETIME_POSTGRESQL_USER" database user
      set_config "$LIBRETIME_POSTGRESQL_PASSWORD" database password
    else
      warning "PostgreSQL user '$LIBRETIME_POSTGRESQL_USER' already exists!"
    fi

    if ! sudo -iH -u postgres psql --csv --tuples-only --list | grep -qw "^$LIBRETIME_POSTGRESQL_DATABASE"; then
      info "creating PostgreSQL database '$LIBRETIME_POSTGRESQL_DATABASE' with owner '$LIBRETIME_POSTGRESQL_USER'"
      sudo -iH -u postgres createdb --template=template0 --encoding=UTF-8 --owner="$LIBRETIME_POSTGRESQL_USER" "$LIBRETIME_POSTGRESQL_DATABASE"

      set_config "$LIBRETIME_POSTGRESQL_DATABASE" database name
    else
      warning "PostgreSQL database '$LIBRETIME_POSTGRESQL_DATABASE' already exists!"
    fi
  fi
fi

# RabbitMQ
########################################################################################

# > LibreTime RabbitMQ user
LIBRETIME_RABBITMQ_USER=${LIBRETIME_RABBITMQ_USER:-"libretime"}
# > LibreTime RabbitMQ user password
LIBRETIME_RABBITMQ_PASSWORD=${LIBRETIME_RABBITMQ_PASSWORD:-$(generate_random_password)}
# > LibreTime RabbitMQ vhost
LIBRETIME_RABBITMQ_VHOST=${LIBRETIME_RABBITMQ_VHOST:-"/libretime"}

if $LIBRETIME_SETUP_RABBITMQ; then
  section "RabbitMQ"
  install_packages rabbitmq-server

  if $is_first_install; then
    if ! rabbitmqctl --quiet list_users | grep -qw "^$LIBRETIME_RABBITMQ_USER"; then
      info "creating RabbitMQ user '$LIBRETIME_RABBITMQ_USER'"
      rabbitmqctl add_user "$LIBRETIME_RABBITMQ_USER" "$LIBRETIME_RABBITMQ_PASSWORD"

      set_config "$LIBRETIME_RABBITMQ_USER" rabbitmq user
      set_config "$LIBRETIME_RABBITMQ_PASSWORD" rabbitmq password
    else
      warning "RabbitMQ user '$LIBRETIME_RABBITMQ_USER' already exists!"
    fi

    if ! rabbitmqctl --quiet list_vhosts | grep -qw "^$LIBRETIME_RABBITMQ_VHOST"; then
      info "creating RabbitMQ vhost '$LIBRETIME_RABBITMQ_VHOST' with owner '$LIBRETIME_RABBITMQ_USER'"
      rabbitmqctl add_vhost "$LIBRETIME_RABBITMQ_VHOST"
      rabbitmqctl set_permissions -p "$LIBRETIME_RABBITMQ_VHOST" "$LIBRETIME_RABBITMQ_USER" '.*' '.*' '.*'

      set_config "$LIBRETIME_RABBITMQ_VHOST" rabbitmq vhost
    else
      warning "RabbitMQ vhost '$LIBRETIME_RABBITMQ_VHOST' already exists!"
    fi
  fi
fi

# Icecast
########################################################################################

# > LibreTime Icecast admin password
LIBRETIME_ICECAST_ADMIN_PASSWORD=${LIBRETIME_ICECAST_ADMIN_PASSWORD:-$(generate_random_password)}
# > LibreTime Icecast source password
LIBRETIME_ICECAST_SOURCE_PASSWORD=${LIBRETIME_ICECAST_SOURCE_PASSWORD:-$(generate_random_password)}
# > LibreTime Icecast relay password
LIBRETIME_ICECAST_RELAY_PASSWORD=${LIBRETIME_ICECAST_RELAY_PASSWORD:-$(generate_random_password)}

if $LIBRETIME_SETUP_ICECAST; then
  section "Icecast"
  install_packages icecast2
  systemctl enable icecast2

  systemctl start icecast2

  if $is_first_install; then
    icecast_config_filepath="/etc/icecast2/icecast.xml"

    cp_if_different \
      "${SCRIPT_DIR}/installer/icecast/icecast.xml" \
      "$icecast_config_filepath"

    sed --in-place \
      -e "s|<admin-password>[^<]*</admin-password>|<admin-password>${LIBRETIME_ICECAST_ADMIN_PASSWORD}</admin-password>|" \
      -e "s|<source-password>[^<]*</source-password>|<source-password>${LIBRETIME_ICECAST_SOURCE_PASSWORD}</source-password>|" \
      -e "s|<relay-password>[^<]*</relay-password>|<relay-password>${LIBRETIME_ICECAST_RELAY_PASSWORD}</relay-password>|" \
      "$icecast_config_filepath"

    service_restart_if_active icecast2

    set_config "$LIBRETIME_ICECAST_ADMIN_PASSWORD" stream outputs .default_icecast_output admin_password
    set_config "$LIBRETIME_ICECAST_SOURCE_PASSWORD" stream outputs .default_icecast_output source_password
  fi
fi

# Prepare python
########################################################################################

section "Python3"
install_packages python3 python3-pip python3-wheel python3-venv

info "creating python3 venv"
python3 -m venv "$VENV_DIR"

info "upgrading python3 tools"
$VENV_DIR/bin/pip install --upgrade "pip<24.1" setuptools wheel

# Install Shared and API client
########################################################################################

section "Shared"

# shellcheck disable=SC2046
install_packages $(list_packages "$SCRIPT_DIR/shared")

install_python_app "$SCRIPT_DIR/shared"

section "API client"
install_python_app "$SCRIPT_DIR/api-client"

# Install API
########################################################################################

section "API"

# shellcheck disable=SC2046
install_packages $(list_packages "$SCRIPT_DIR/api")

install_python_app "$SCRIPT_DIR/api[prod]"
link_python_app libretime-api

install_service "libretime-api.service" "$SCRIPT_DIR/api/install/systemd/libretime-api.service"
install_service "libretime-api.socket" "$SCRIPT_DIR/api/install/systemd/libretime-api.socket"

# Install Playout
########################################################################################

section "Playout"

# shellcheck disable=SC2046
install_packages $(list_packages "$SCRIPT_DIR/playout")

install_python_app "$SCRIPT_DIR/playout"
link_python_app libretime-liquidsoap
link_python_app libretime-playout
link_python_app libretime-playout-notify

info "creating libretime-playout working directory"
mkdir_and_chown "$LIBRETIME_USER" "$WORKING_DIR/playout"

install_service "libretime-liquidsoap.service" "$SCRIPT_DIR/playout/install/systemd/libretime-liquidsoap.service"
install_service "libretime-playout.service" "$SCRIPT_DIR/playout/install/systemd/libretime-playout.service"

info "deploying libretime-liquidsoap logrotate config"
template_file cp_if_different \
  "$SCRIPT_DIR/playout/install/logrotate/libretime-liquidsoap.conf" \
  "/etc/logrotate.d/libretime-liquidsoap" \
  sed \
    -e "s|@@LOG_DIR@@|${LOG_DIR}|g" \
    -e "s|@@USER@@|${LIBRETIME_USER}|g"

# Install Analyzer
########################################################################################

section "Analyzer"

# shellcheck disable=SC2046
install_packages $(list_packages "$SCRIPT_DIR/analyzer")

install_python_app "$SCRIPT_DIR/analyzer"
link_python_app libretime-analyzer

info "creating libretime-analyzer working directory"
mkdir_and_chown "$LIBRETIME_USER" "$WORKING_DIR/analyzer"

install_service "libretime-analyzer.service" "$SCRIPT_DIR/analyzer/install/systemd/libretime-analyzer.service"

# Install Worker
########################################################################################

section "Worker"

install_python_app "$SCRIPT_DIR/worker"
link_python_app libretime-worker

info "creating libretime-worker working directory"
mkdir_and_chown "$LIBRETIME_USER" "$WORKING_DIR/worker"

install_service "libretime-worker.service" "$SCRIPT_DIR/worker/install/systemd/libretime-worker.service"

# Install Legacy
########################################################################################

section "Legacy"

install_composer() {
  install_packages unzip

  curl -sS https://composer.github.io/installer.sig > installer.sig
  echo " composer-setup.php" >> installer.sig

  curl -sS https://getcomposer.org/installer > composer-setup.php

  if ! sha384sum installer.sig; then
    rm -f composer-setup.php
    error "invalid composer-setup.php checksum"
  fi

  php -f composer-setup.php -- \
    --install-dir=/usr/local/bin \
    --filename=composer \
    --quiet

  rm -f composer-setup.php installer.sig
}

# shellcheck disable=SC2046
install_packages $(list_packages "$SCRIPT_DIR/legacy")

if ! command -v "composer" > /dev/null; then
  info "installing Composer"
  install_composer
fi

info "building libretime-legacy files"
make -C legacy build
cp "$SCRIPT_DIR/VERSION" "$SCRIPT_DIR/legacy/"

info "deploying libretime-legacy files"
if $LIBRETIME_INSTALL_IN_PLACE; then
  LEGACY_WEB_ROOT="$SCRIPT_DIR/legacy"
else
  if [[ -d "$LEGACY_WEB_ROOT" ]]; then
    info "cleaning old libretime-legacy files"
    rm -Rf "$LEGACY_WEB_ROOT"
  fi

  mkdir_and_chown "$LIBRETIME_USER" "$LEGACY_WEB_ROOT"
  cp -R "$SCRIPT_DIR/legacy/." "$LEGACY_WEB_ROOT"
  chown -R "$LIBRETIME_USER:$LIBRETIME_USER" "$LEGACY_WEB_ROOT"
fi

PHP_VERSION="$(php-config --version | awk -F . '{ print $1 "." $2 }')"

info "deploying libretime-legacy php-fpm config"
template_file cp_if_different \
  "$SCRIPT_DIR/legacy/install/php-fpm/libretime-legacy.conf" \
  "/etc/php/$PHP_VERSION/fpm/pool.d/libretime-legacy.conf" \
  sed \
    -e "s|@@DEFAULT_WEB_USER@@|${DEFAULT_WEB_USER}|g" \
    -e "s|@@USER@@|${LIBRETIME_USER}|g"

info "deploying libretime-legacy logrotate config"
template_file cp_if_different \
  "$SCRIPT_DIR/legacy/install/logrotate/libretime-legacy.conf" \
  "/etc/logrotate.d/libretime-legacy" \
  sed \
    -e "s|@@LOG_DIR@@|${LOG_DIR}|g" \
    -e "s|@@USER@@|${LIBRETIME_USER}|g"

# Install Nginx
########################################################################################

section "Nginx"

if $is_first_install; then
  install_packages nginx

  info "disabling nginx default site"
  rm -f "/etc/nginx/sites-enabled/default"
fi

info "deploying libretime nginx config"
template_file cp_if_different \
  "${SCRIPT_DIR}/installer/nginx/libretime.conf" \
  "/etc/nginx/sites-available/libretime.conf" \
  sed \
  -e "s|@@LISTEN_PORT@@|${LIBRETIME_LISTEN_PORT}|g" \
  -e "s|@@LEGACY_WEB_ROOT@@|${LEGACY_WEB_ROOT}|g" \
  -e "s|@@STORAGE_PATH@@|${LIBRETIME_STORAGE_PATH}|g"

info "enabling libretime nginx config"
ln -s --force \
  "/etc/nginx/sites-available/libretime.conf" \
  "/etc/nginx/sites-enabled/libretime.conf"

# Finalize
########################################################################################

if $is_first_install; then
  section "Finalize"
  info "moving config file in place"
  mv "$CONFIG_TMP_FILEPATH" "$CONFIG_FILEPATH"
fi

# Services
########################################################################################

section "Services"

install_service "libretime.target" "$SCRIPT_DIR/installer/systemd/libretime.target"

systemctl daemon-reload

service_restart_if_active "php$PHP_VERSION-fpm"
service_restart_if_active "nginx"

# Instructions
########################################################################################

if $is_first_install; then
  section "Instructions"
  printf "
${yellow}\
To finalize the installation process, start by editing your configuration file $CONFIG_FILEPATH.

Once configured, run the following command to setup the database:

${cyan}\
$ sudo -u $LIBRETIME_USER libretime-api migrate

${yellow}\
Finally, start LibreTime using the following command:

${cyan}\
$ sudo systemctl start libretime.target

${reset}"

else
  printf "
${yellow}\
Once upgraded, run the following command to migrate the database:

${cyan}\
$ sudo -u $LIBRETIME_USER libretime-api migrate

${yellow}\
You can restart LibreTime using the following command:

${cyan}\
$ sudo systemctl restart libretime.target

${reset}"
fi