#!/bin/bash
set -e

LOGFILE="/var/log/mds_install_$(date +'%Y%m%d_%H%M%S').log"

mkdir -p "$(dirname "$LOGFILE")"
exec > >(tee -a "$LOGFILE") 2>&1

mirror_xivo="http://mirror.xivo.solutions"
update='apt-get update'
install='apt-get install --assume-yes'
download='apt-get install --assume-yes --download-only'
dcomp='/usr/bin/xivo-dcomp'
custom_env='/etc/docker/mds/custom.env'

# Please update "default_lts_preinstallation" with archive installation steps when changing distribution
distribution='xivo-pollux'
dev_lts='quantum'
repo='debian'
debian_codename='bookworm'
debian_version='12'
debian_codename_dev='bookworm'
debian_version_dev='12'
not_installable_message='This version of XiVO MDS is not installable on 32-bit systems.'

declare -A lts_version_table=([2017.03]="Five" [2017.11]="Polaris" [2018.05]="Aldebaran" [2018.16]="Borealis" [2019.05]="Callisto" [2019.12]="Deneb" [2020.07]="Electra" [2020.18]="Freya" [2021.07]="Gaia" [2021.15]="Helios" [2022.05]="Izar" [2022.10]="Jabbah" [2023.05]="Kuma" [2023.10]="Luna" [2024.05]="Maia" [2024.10]="Naos" [2025.05]="Orion" [2025.10]="Pollux")

# 6099 Force the usage of ipV4 on the wget commands to avoid infinite loop
if ! grep --quiet "inet4_only = on" /etc/wgetrc ; then
    echo "inet4_only = on" >> /etc/wgetrc
fi

get_system_architecture() {
    architecture=$(uname -m)
}

check_system() {
    local version_file='/etc/debian_version'
    if [ ! -f $version_file ]; then
        echo "You must install XiVO MDS on a Debian $debian_version (\"$debian_codename\") system"
        echo "You do not seem to be on a Debian system"
        exit 1
    else
        your_version=$(cut -d '.' -f 1 "$version_file")
    fi

    if [ $your_version != $debian_version ]; then
        echo "You must install XiVO MDS on a Debian $debian_version (\"$debian_codename\") system"
        echo "You are currently on a Debian $your_version system"
        exit 1
    fi
}

add_dependencies() {
    $update
    # dirmngr and gnupg is needed by apt-key in Debian 9-10
    $install wget \
        dirmngr \
        gnupg \
        curl
}

add_xivo_key() {
    local xivo_keyring_file="/etc/apt/trusted.gpg.d/mirror.xivo.solutions.gpg"
    add_key_in_keyring "http://mirror.xivo.solutions/xivo_current.key" "${xivo_keyring_file}"
}

is_key_in_keyring() {
    local keyid="${1}"; shift
    local keyringfile="${1}"; shift

    if gpg --batch --no-tty --keyring "${keyringfile}" --list-keys --with-colons | grep -q "${keyid}"; then
        return 0
    else
        return 1
    fi
}

add_key_in_keyring() {
    local keyurl="${1}"; shift
    local keyringfile="${1}"; shift

    echo "Removing file ${keyringfile}"
    rm -rf "${keyringfile}"
    touch "${keyringfile}"
    echo "Adding GPG key from ${keyurl} to ${keyringfile}..."
    curl -fsSL "${keyurl}" | gpg --dearmor | tee "${keyringfile}" >/dev/null
}

# For archive versions. From version 2019.11 docker key is installed by xivo-docker
add_docker_key() {
    local docker_keyring_file="/etc/apt/trusted.gpg.d/download.docker.com.gpg"
    local docker_keyid="0EBFCD88"

    if ! is_key_in_keyring "${docker_keyid}" "${docker_keyring_file}"; then
        echo "Adding Docker GPG key..."
        add_key_in_keyring "https://download.docker.com/linux/debian/gpg" "${docker_keyring_file}"
    fi
}

add_xivo_apt_conf() {
    echo "Installing APT configuration file: /etc/apt/apt.conf.d/90xivo"

	cat > /etc/apt/apt.conf.d/90xivo <<-EOF
	Aptitude::Recommends-Important "false";
	APT::Install-Recommends "false";
	APT::Install-Suggests "false";
	EOF
}

check_source_exists() {
    local type="$1"; shift
    local distribution="$1"; shift
    local component="$1"; shift
    local list="$1"; shift

    grep -Prq "^\s*${type}\s.+\s${distribution}\s+${component}\b" ${list}
}

add_backports_in_sources_list() {
    local distribution=${1}; shift

    echo "Adding ${distribution}-backports source"
    if ! check_source_exists deb ${distribution}-backports main "/etc/apt/sources.list*"; then
		cat >> /etc/apt/sources.list <<-EOF

			# ${distribution}-backports, previously on backports.debian.org
			deb http://ftp.fr.debian.org/debian ${distribution}-backports main
		EOF
    fi
    if ! check_source_exists deb-src ${distribution}-backports main "/etc/apt/sources.list*"; then
		cat >> /etc/apt/sources.list <<-EOF
			deb-src http://ftp.fr.debian.org/debian ${distribution}-backports main
		EOF
    fi
}

add_mirror() {
    echo "Add mirrors informations"
    local mirror="deb $mirror_xivo/$repo $distribution main"
    apt_dir="/etc/apt"
    sources_list_dir="$apt_dir/sources.list.d"
    if ! grep -qr "$mirror" "$apt_dir"; then
        echo "$mirror" > $sources_list_dir/tmp-pf.sources.list
    fi
    add_xivo_key

    $update
    $install xivo-dist
    xivo-dist "$distribution"


    rm -f "$sources_list_dir/tmp-pf.sources.list"
    $update
}

add_pgdg_mirror() {
    $install ca-certificates lsb-release
    add_key_in_keyring "https://apt.postgresql.org/pub/repos/apt/ACCC4CF8.asc" "/etc/apt/trusted.gpg.d/apt.postgresql.org.gpg"
    sh -c 'echo "deb http://apt.postgresql.org/pub/repos/apt/ $(lsb_release -cs)-pgdg main" > /etc/apt/sources.list.d/pgdg.list'
    $update
}

get_xivo_host () {
    if [ -f ${custom_env} ]; then
        XIVO_HOST=$(grep XIVO_HOST ${custom_env} | awk -F "=" '/1/ {print $2}')
    fi
    if [ -z ${XIVO_HOST} ]; then
        XIVO_HOST=$(whiptail --inputbox "Enter the XiVO MAIN Server(mds0) IP Address: " 8 50 3>&1 1>&2 2>&3)
    fi
}

install_dahdi_modules() {
    flavour=$(echo $(uname -r) | cut -d\- -f3)
    kernel_release=$(ls /lib/modules/ | grep ${flavour})
    for kr in ${kernel_release}; do
        ${download} dahdi-linux-modules-${kr}
        ${install} dahdi-linux-modules-${kr}
    done
}

install_mds () {
    # Only install dahdi-linux-modules if the package dahdi-linux-dkms was not found
    dahdi_dkms_exists=$(apt-cache pkgnames | grep -q "dahdi-linux-dkms"; echo $?)
    if [ $dahdi_dkms_exists -eq 0 ]; then
      echo "DAHDI: dahdi-linux-dkms package found in repository"
    else
      echo "DAHDI: dahdi-linux-dkms package not found in repository"
      install_dahdi_modules
    fi

    # Install docker stuff
    ${install} docker-ce

    # Install asterisk
    ${download} asterisk xivo-res-freeze-check asterisk-dbg asterisk-sounds-main asterisk-sounds-wav-en-us asterisk-sounds-wav-fr-fr xivo-sounds-en-us xivo-sounds-fr-fr
    ${install} asterisk xivo-res-freeze-check asterisk-dbg asterisk-sounds-main asterisk-sounds-wav-en-us asterisk-sounds-wav-fr-fr xivo-sounds-en-us xivo-sounds-fr-fr
    # Install asterisk default moh
    ${install} asterisk-moh-opsound-g722 asterisk-moh-opsound-gsm asterisk-moh-opsound-wav

    if [ $dev_install = true ]; then
        mkdir -p /etc/docker/mds
        echo "XIVOCC_DIST=latestdev" >> /etc/docker/mds/custom.env
    fi

    if [ $rc_install = true ]; then
        mkdir -p /etc/docker/mds
        echo "XIVOCC_DIST=latestrc" >> /etc/docker/mds/custom.env
    fi

    # Installs mds
    ${install} xivo-manage-db-mds

    # required but probably already installed
    ${install} xivo-config xivo-bus
    # Annex xivo components
    ${install} xivo-confgend-client xivo-sysconfd xivo-monitoring-mds xivo-service

    export DEBIAN_FRONTEND=noninteractive
    ${install} postfix

    configure_mds
    export DEBIAN_FRONTEND=dialog

    /usr/bin/xivo-update-keys
    /usr/bin/xivo-configure-uuid


    if [ -f "${dcomp}" ]; then
         ${dcomp} pull
    fi

    xivo-service restart all
}

configure_mds () {
    echo "Configuring XiVO"

    get_xivo_host
    echo "XIVO HOST IS $XIVO_HOST"

    if [ $do_configure_xds_sync -eq 1 ]; then
        get_ssh_key
    fi
    echo "db_uri: postgresql://asterisk:proformatique@$XIVO_HOST/asterisk" > /etc/xivo-dao/conf.d/010-mds_db_uri.yml
    configure_postfix

    #used by xivo-service and start only service used by mds
    touch /var/lib/xivo/mds_enabled
}

get_ssh_key () {
    if ! mkdir -p /root/.ssh/; then
        echo -e "\e[1;31mFailed to create /root/.ssh/ directory. Exiting..."
        echo "Can't continue to install the XiVO Main ssh key."
        echo "Please fix the problem and re-run the installation."
        exit 1
    fi
    if wget https://$XIVO_HOST/ssh-key --no-check-certificate -O /root/.ssh/rsync_xds.pub >/dev/null 2>&1; then
        echo -e "\\e[1;33mInstalling XiVO Main ssh key to /root/.ssh/authorized_keys\\e[0m"
        cat /root/.ssh/rsync_xds.pub >> /root/.ssh/authorized_keys
    else
        echo -e "\e[1;31mFailed to get public ssh key from XiVO Main for XDS File Synchronization. Exiting...\e[0m"
        echo "Please verify that XiVO Main is running and \"xivo-xds-sync -i\" was run"
        echo "as described in the documentation for XDS installation."
        echo "Then re-run the installation."
        exit 1
    fi
    apt-get install rsync -y
}

configure_postfix () {
    # Configure the relayhost to XiVO Main IP
    postconf -e "relayhost = $XIVO_HOST"

    # Get the myorigin first from domain, and if not set, from hostname
    myorigin=$(dnsdomainname)
    if [ -z "${myorigin}" ]; then
        myorigin=$(hostname --short)
    fi
    # Configure myorigin with /etc/mailname file (as on XiVO Main)
    touch /etc/mailname
    echo "$myorigin" > /etc/mailname
    postconf -e "myorigin = /etc/mailname"

    postfix reload
}

check_system_is_64bit() {
    if [ "$architecture" != "x86_64" ]; then
        echo $not_installable_message
        exit 1
    fi
}

check_archive_prefix() {
    if [ "${1::5}" = "xivo-" ]; then
        echo 'Archive version must be typed without the prefix "xivo-"'
        exit 1
    fi
}

usage() {
    cat << EOF
    This script is used to install XiVO MDS

    usage : $(basename $0) [-d|-a version|-r version]
        whitout arg : install production version
        -d          : install development version
        -r version  : install rc version
        -a version  : install archived version (2018.11 or later)

EOF
    exit 1
}

get_version_name() {
    if [[ -v lts_version_table[$1] ]]; then
        echo ${lts_version_table[$1]}
    else
        echo 'intermediate version'
    fi
}

ask_before_proceeding_installation_mds(){
    user_has_been_asked_before=1
    local option=$1
    local version=$2
    local version_prefix=${2:0:7}
    if [[ $# -eq 0 ]]; then
        echo "You are going to install production version : $distribution."
    elif [[ $version_prefix =~ ^[0-9]{4}\.[0-9]{2}+$ ]] && [[ $option == "-a" ]]; then
        echo "You are going to install xivo mds $(get_version_name $version_prefix) ($version)."
    elif [[ $option == "-d" ]]; then
        echo "You are going to install MDS ${dev_lts} dev version."
        echo "To install production version, re-run the script without parameters."
    else
        echo "Be careful ! The version $option $version you choose was not recognized."
    fi

    echo "The installation will start in 5 seconds. Type Ctrl+C if you want to abort."
    for _ in $(seq 1 1 5); do
        sleep 1
        echo -n "."
    done
    echo "Go!"
    sleep 1
}

recover_from_wrong_distrib_input(){
    if [ -f /etc/apt/sources.list.d/tmp-pf.sources.list ]; then
        rm /etc/apt/sources.list.d/tmp-pf.sources.list
    fi
}

after_install_notice(){
    #Mail configuration notice
    local from_suffix=""
    from_suffix=$(head /etc/mailname)

    echo ""
    echo "Mail configuration notice"
    echo "========================="
    echo "  Postfix was configured to use the MDS Main ($XIVO_HOST) as SMTP relay."
    echo "  On the XiVO Main, don't forget to follow SMTP relay configuration in documentation:"
    echo "     Installation & Upgrade > XiVO Distributed System > Installation > XiVO Configuration > SMTP relay configuration"
    echo ""
    echo "  Also note that postfix was configured to take the domain part of the from address (user@domain) in /etc/mailname."
    echo "  With current configuration asterisk voicemail notification will be sent with the from address"
    echo "    asterisk@$from_suffix"
    echo "  You should check that it will work. See XDS installation documentation for further information:"
    echo "     Installation & Upgrade > XiVO Distributed System > Installation > Media Server Configuration > Mail configuration"

}

default_lts_preinstallation() {
    do_configure_xds_sync=0
}

do_archive_install() {
    local version="$1"
    check_archive_prefix $version
    ask_before_proceeding_installation_mds -a $version
    distribution="xivo-$version"
    repo='archive'

    if dpkg --compare-versions "$version" "ge" "2021.03.00"; then
        do_configure_xds_sync=1
    fi
    if dpkg --compare-versions "$version" "ge" "2024.05"; then
        debian_version=$debian_version
        debian_codename=$debian_codename
    elif dpkg --compare-versions "$version" "ge" "2022.04.00"; then
        debian_version='11'
        debian_codename='bullseye'
    elif dpkg --compare-versions "$version" "gt" "2020.09.00"; then
        debian_version='10'
        debian_codename='buster'
    elif dpkg --compare-versions "$version" "gt" "2018.13.00"; then
        debian_version='9'
        debian_codename='stretch'
        add_docker_key
    elif dpkg --compare-versions "$version" "gt" "2018.11.00"; then
        debian_version='8'
        debian_codename='jessie'
        add_docker_key
    fi

    if dpkg --compare-versions "$version" "le" "2018.11.00"; then
        # 2018.11 and earlier don't have mds available
        echo "This script only supports installing XiVO 2018.12 or later."
        exit 1
    fi
}

get_system_architecture
check_system_is_64bit

do_configure_xds_sync=0

user_has_been_asked_before=0
while getopts ':dr:a:' opt; do
    case ${opt} in
        d)
            ask_before_proceeding_installation_mds -d
            distribution="xivo-$dev_lts-dev"
            debian_codename=$debian_codename_dev
            debian_version=$debian_version_dev
            do_configure_xds_sync=1
            dev_install=true
            ;;
        r)
            rc_install=true
            do_archive_install "$OPTARG"
            ;;
        a)
            do_archive_install "$OPTARG"
            ;;
        *)
            usage
            ;;
    esac
done

if [[ ${user_has_been_asked_before} -eq 0 ]]; then
    ask_before_proceeding_installation_mds $1 $2
    default_lts_preinstallation
fi
recover_from_wrong_distrib_input

check_system
add_xivo_apt_conf
add_dependencies
if [ "$debian_codename" = "buster" ] || [ "${debian_codename}" = "bullseye" ]; then
    add_backports_in_sources_list ${debian_codename}
fi
add_mirror
add_pgdg_mirror
install_mds
after_install_notice
