#!/bin/bash

# shellcheck source=../xivo-upgrade-functions
source /usr/bin/xivo-upgrade-functions

get_mds_version_installed_from_apt() {
    echo "$(LANG='C' apt-cache policy xivo-mds-installer | grep Installed | grep -oE '[0-9]{2,4}\.[0-9]+(\.[0-9]+)?|1\.2\.[0-9]{1,2}' | head -n1)"
}

get_mds_version_candidate_from_apt() {
    echo "$(LANG='C' apt-cache policy xivo-mds-installer | grep Candidate | grep -oE '[0-9]{2,4}\.[0-9]+(\.[0-9]+)?|1\.2\.[0-9]{1,2}' | head -n1)"
}

display_mds_version() {
    local version_installed="${1}"; shift
    local version_candidate="${1}"; shift

    echo "installed version : $version_installed"
    echo "proposed update	: $version_candidate"
}

stop_mds() {
    xivo-service stop all
}

start_mds() {
    xivo-dcomp up -d --remove-orphans
    xivo-service start
}

install_xivo_docker() {
    apt install --yes xivo-docker
}

exec_buster_to_bullseye_migration() {
    local force_yes="--allow-downgrades --allow-remove-essential --allow-change-held-packages"

    add_xivo_apt_conf

    echo "Executing pre-bullseye upgrade actions..."
    # Force install of new dahdi-linux-dkms module before switching to bullseye
    apt install --yes ${force_yes} -o Dpkg::Options::="--force-confnew" dahdi-linux-dkms

    # On MDS, force install of xivo-config before upgrade
    apt install --yes ${force_yes} -o Dpkg::Options::="--force-confnew" xivo-config

    # Switch to Bullseye
    switch_to_bullseye

    apt update

    echo "Executing manual upgrade actions..."
    # Upgrade docker-ce before xivo upgrade (force bullseye repo)
    # shellcheck disable=SC2086
    apt install --yes ${force_yes} -o Dpkg::Options::="--force-confnew" docker-ce/bullseye docker-ce-cli/bullseye containerd.io/bullseye
    # Docker upgrade starts the containers that were stopped at beginning of upgrade.
    # So stopping them again
    xivo-service stop

    apt update

    echo "Executing MDS full upgrade actions..."
    # shellcheck disable=SC2086
    apt dist-upgrade --yes ${force_yes} -o Dpkg::Options::="--force-confnew"

    apt update
    echo "Executing cleaning actions..."
    apt autoremove --yes
}

mds_upgrade() {
    # Prepare Docker installation first
    install_xivo_docker

    if is_buster; then
        export UPGRADING_TO_BULLSEYE=1
        exec_buster_to_bullseye_migration
    else
        echo "Upgrading media server..."
        echo "Executing manual upgrade actions..."
        apt install --yes -o Dpkg::Options::="--force-confnew" xivo-config xivo-dist
        echo "Executing full upgrade actions..."
        apt dist-upgrade --yes -o Dpkg::Options::="--force-confnew"
        echo "Executing cleaning actions..."
        apt autoremove --yes
    fi

    echo "Running post-upgrade actions..."
    if [[ "$UPGRADING_TO_BULLSEYE" == "1" ]]; then
        check_if_grub_is_broken
        display_buster_to_bullseye_upgrade_reboot_notice
    fi
}

upgrade_db() {
    xivo-dcomp upgrade-db
    wait_for_postgres
}

recreate_upgrade_status_file_and_export() {
    local status_file="${1}"; shift

    rm -f "${status_file}"
    touch "${status_file}"
    export MDS_UPGRADE_STATUS_FILE=${status_file}
}

upgrading_system() {
    local force="${1}"; shift

    local mds_version_installed
    local mds_version_candidate
    mds_version_installed=$(get_mds_version_installed_from_apt)
    mds_version_candidate=$(get_mds_version_candidate_from_apt)
    
    export MDS_VERSION_INSTALLED="${mds_version_installed}"
    export MDS_VERSION_CANDIDATE="${mds_version_candidate}"
    display_mds_version "${mds_version_installed}" "${mds_version_candidate}"
    if is_buster; then
        display_system_upgrade_notice
    fi
    ask_to_continue_upgrade "${force}"
    local mds_upgrade_status_file="/tmp/mds-upgrade.status"
    recreate_upgrade_status_file_and_export "${mds_upgrade_status_file}"

    pre_stop "mds"
    stop_mds
    post_stop "mds"
    echo "Upgrading mds..."
    mds_upgrade
    upgrade_db
    pre_start "mds"
    start_mds
    post_start "mds"
}

usage() {
    local progname="${1}"; shift

    echo "usage: ${progname} [-d] [-f] [-h]"
    echo -e "\t-d: only download packages"
    echo -e "\t-f: force install the proposed version"
    echo -e "\t-h: print usage"
}

main() {
    local progname="mds-upgrade"
    # Parse flags
    local download_only
    local force
    while getopts :dfh opt
    do
        case ${opt} in
            d) download_only=1;;
            f) force=1;;
            h)
                usage "${progname}"
                exit 0
            ;;
            '?')
                echo "${progname} : option ${OPTARG} is not valid" >&2
                usage "${progname}"
                exit 1
            ;;
        esac
    done
    download_only="${download_only:-"0"}"
    force="${force:-"0"}"

    # Beginning
    export DEBIAN_FRONTEND=noninteractive
    export APT_LISTCHANGES_FRONTEND=none

    if (! is_buster && ! is_bullseye); then
        echo "Upgrade aborted."
        echo "Your MDS is lower than Freya (2020.18) and uses Debian 9 (or lower)"
        echo "Upgrade to MDS >= 2022.04 (which uses Debian 11) is not supported"
        echo "You MUST first upgrade to a MDS >= Freya (2020.18)"
        exit 1
    fi

    if [ $download_only -eq 0 ]; then
        upgrading_system "${force}"
    else
        if is_buster; then
            # Switch repo to bullseye
            switch_to_bullseye
            apt update

            # Download packages
            apt -y -d -o Dpkg::Options::="--force-confnew" dist-upgrade

            # Switch back to buster
            change_sources_list 'bullseye' 'buster' '/etc/apt/sources.list'
            change_sources_list 'bullseye' 'buster' '/etc/apt/sources.list.d/docker.list'
            add_postgresql_sources_list 'buster'
            # Fix the security repo name change
            change_sources_list 'buster-security' 'buster\/updates' '/etc/apt/sources.list'
            # Ensure buster backports are present
            add_distribution_sources_list 'buster-backports'
            apt update
        else
            apt -y -d -o Dpkg::Options::="--force-confnew" dist-upgrade
        fi
    fi
}

main "${@}"