#!/bin/bash
# Script:      astra-live
# Title:       Astra Linux Live Build Orchestrator
# Description: This script orchestrates the build process for a bootable Astra Linux image.
#              It reads the configuration, sets up the environment, installs packages, and
#              creates the final image in the specified format.

# ----[ HEADER AND DEFINITIONS ]----
set -e          # exit on error
set -o pipefail # exit on pipeline error
set -u          # treat unset variable as error

# The purpose of these variables is described in the help for the toggle_shell_options function in libastralive.
SET_E=""
SET_U=""

SCRIPT_DIR="$(dirname "$(readlink -f "$0")")"
export TEXTDOMAIN="live-build-astra"

# ----[ LIBRARY SOURCING ]----
for DIR in "${SCRIPT_DIR}" "/usr/lib/astra-live"; do
    if [ -f "${DIR}/libastralive" ]; then
        LIBASTRALIVE="${DIR}/libastralive"
        break
    fi
done
. "${LIBASTRALIVE}" || exit 1

# ----[ INTERNAL FUNCTIONS ]----
help() {
    local HEADLINE="${1:-$(gettext 'This script builds a bootable Astra Linux image.')}"
    local COMMANDS="${CMD[*]}"
    local SYNTAX="$0 [start_cmd] [-] [end_cmd]"
    local EXAMPLES=(
        "${LIGHTYELLOW}  $0 -                                ${ENDCOLOR}$(gettext "Run the build from start to finish.")"
        "${LIGHTYELLOW}  $0 build_environment - build_chroot ${ENDCOLOR}$(gettext "Start the build by building the base environment and finish by installing the entire system in chroot.")"
        "${LIGHTYELLOW}  $0 - build_chroot                   ${ENDCOLOR}$(gettext "Start the build from the beginning and finish by installing the entire system in chroot.")"
        "${LIGHTYELLOW}  $0 build_environment -              ${ENDCOLOR}$(gettext "Start the build by building the base environment and run to completion.")"
        "${LIGHTYELLOW}  $0 build_image                      ${ENDCOLOR}$(gettext "Build only images from previously prepared data.")"
    )

    echo -e "${LIGHTYELLOW}${HEADLINE}${ENDCOLOR}\n"
    echo -e "$(gettext "Supported commands:") ${CYAN}${CMD[*]}${ENDCOLOR}\n"
    echo -e "$(gettext "Usage:") ${MAGENTA}${SYNTAX}${ENDCOLOR}"
    echo -e "$(gettext "  Run from start_cmd to end_cmd")"
    echo -e "$(gettext "  If start_cmd is omitted, start from the first command")"
    echo -e "$(gettext "  If end_cmd is omitted, end with the last command")"
    echo -e "$(gettext "  Enter a single cmd to run the specific command")"
    echo -e "$(gettext "  Enter '-' as the only argument to run all commands\n")"
    echo -e "$(gettext "Examples:")"
    for EXAMPLE in "${EXAMPLES[@]}"; do
        echo -e "${EXAMPLE}"
    done

    exit 0
}

# ----[ COMMON SETUP ]----
toggle_shell_options u
set_variables BUILD_DIR="${PWD}/build"     # If the variable has not been set before, assign a value to it
set_variables MAIN_EXECUTABLE="astra-live" # If the variable has not been set before, assign a value to it
console_colors                             # Set console colors
allow_root_only                            # Allow only root user to run the script
create_log_file "$@"                       # Сreate a log file to record script output
toggle_shell_options u
INSTALL_DIR="${BUILD_DIR}/chroot"

trap 'unmount_dirs ${BUILD_DIR}; stop_http_server' EXIT

CMD=(build_environment build_bootstrap build_chroot build_live build_boot build_image) # CMD holds a list of available commands that can be executed by the build script.
process_command_range "$@"                                                             # Process script arguments to define the range of commands to execute.

if [ ! -f "${BUILD_DIR}/config" ]; then
    if [ -f "${SCRIPT_DIR}/config" ]; then
        cp "${SCRIPT_DIR}/config" "${BUILD_DIR}/config"
    else
        cp "/etc/astra-live/config" "${BUILD_DIR}/config"
    fi
fi

update_config "${BUILD_DIR}/config" BUILD_DIR

if check_config_file "${BUILD_DIR}/config" REMOVE_SOURCES KEEP_CACHE KEEP_IMAGE KEEP_LOG; then
    read_config "${BUILD_DIR}/config" REMOVE_SOURCES KEEP_CACHE KEEP_IMAGE KEEP_LOG
else
    exit 1
fi

toggle_shell_options u
# If the first command in the queue is 'build_environment', then if REMOVE_SOURCES="true", remove_sources clears the build directory.
if [ "${CMD[INDEX]}" = "build_environment" ]; then
    remove_sources
fi
toggle_shell_options u

# Default GENERATE_IMAGES to "iso" if it was empty in the config
# and store the potentially updated array back into memory
read_config "${BUILD_DIR}/config" GENERATE_IMAGES
if ! ((${#GENERATE_IMAGES[@]})); then
    GENERATE_IMAGES+=("iso")
fi
update_config "${BUILD_DIR}/config" GENERATE_IMAGES

if check_config_file "${BUILD_DIR}/config" DISTRIBUTION ARCHITECTURE HOST_NAME USER_NAME USER_PASSWORD_HASH AUTOLOGIN BUILD_DIR COMP_TYPE REMOVE_SOURCES KEEP_CACHE KEEP_IMAGE KEEP_LOG REPO_LIST ADD_PACKAGES ADD_PACKAGES_LIST DELETE_PACKAGES DELETE_PACKAGES_LIST REPLACE_PACKAGES REPLACE_PACKAGES_LIST TASKS GENERATE_IMAGES ISO_NAME DOCKER_NAME DOCKER_TAG QCOW2_NAME RAW_NAME TAR_NAME VMDK_NAME WSL_NAME; then
    . "${BUILD_DIR}/config"
    grant_write_permissions "${BUILD_DIR}/config"
else
    exit 1
fi

check_required_packages # Check if the required packages are present

toggle_shell_options u
# Set default DOCKER_TAG in memory *only* if it was empty in the config
set_variables DOCKER_TAG="astralinux:${DISTRIBUTION}"

# Determine which variables need updating in the config file
VARS_TO_UPDATE=("BUILD_DIR" "GENERATE_IMAGES")
if [[ " ${GENERATE_IMAGES[@]} " =~ " docker " ]]; then
    VARS_TO_UPDATE+=("DOCKER_TAG")
fi
update_config "${BUILD_DIR}/config" "${VARS_TO_UPDATE[@]}"
toggle_shell_options u

# ----[ MAIN ]----

export LC_ALL=C

# Run commands within the defined range.
for ((iterator = "${START_INDEX}"; iterator < "${END_INDEX}"; iterator++)); do
    "${CMD[iterator]}"
done
