#!/bin/bash

dp_port=$1
dp_secret=$2
dp_id=$3
dp_url_signalr=$4

### Init Logging ###

log_colibri_root="/var/log/colibri"
log_folder="$log_colibri_root/dp"
mkdir -p $log_folder
timestamp=$(date --iso-8601=ns | sed -E 's/(.*),([0-9]{7}).*(\+|-.*)/\1.\2\3/')
log_file="install_${timestamp}.log"
log_file_path="$log_folder/$log_file"

function Write_Log {
	message=$1
	severity=$2

	if [ "$severity" == "" ]; then severity="INFO"; fi
	timestamp=$(date --iso-8601=ns | sed -E 's/(.*),([0-9]{7}).*(\+|-.*)/\1.\2\3/')
	log_line="[$timestamp][${severity^^}]: $message"
	if [ "${severity^^}" == "ERROR" ] || [ "${severity^^}" == "WARNING" ]; then
		>&2 echo "$log_line"
		echo "$log_line" >> "$log_file_path"
	else
		echo "$log_line" | tee -a "$log_file_path"
	fi
}

### End Init Logging ###

### Custom functions

Compare_Versions () {
    if [[ $1 == $2 ]]
    then
        return 0
    fi
    local IFS=.
    local i ver1=($1) ver2=($2)
    # fill empty fields in ver1 with zeros
    for ((i=${#ver1[@]}; i<${#ver2[@]}; i++))
    do
        ver1[i]=0
    done
    for ((i=0; i<${#ver1[@]}; i++))
    do
        if ((10#${ver1[i]:=0} > 10#${ver2[i]:=0}))
        then
            return 1
        fi
        if ((10#${ver1[i]} < 10#${ver2[i]}))
        then
            return 2
        fi
    done
    return 0
}

Update_Env() {
	env_file=$1
	key=$2
	value=$3

	env_content=$(cat "$env_file")
	if ! echo "$env_content" | grep -q "${key}="; then
		echo "${key}=${value}" >> "$env_file"
	else
		sed -E "s|^(${key}=).*$|\1${value}|" -i "$env_file"
	fi
}

### End Custom functions


### Init variables ###

url_base=$(echo "$dp_url_signalr" | sed -E 's;^https://signalr.(.*)(/$|$);http://\1;' | sed 's:/$::')
port_base='5001'
docker_min_ver="24.0.7"
docker_compose_min_ver="2.21.0"
colibri_user="colibri_service_user"
url_dp="${url_base}:${port_base}/dp"
remote_hash_file="${url_dp}/dp.tar.gz.md5"
remote_cert_file="${url_base}:${port_base}/service_repo/agent/ca/colibriCA.crt"
local_colibri_root="/opt/colibri"
local_dp_folder="$local_colibri_root/dp"
local_ssh_folder="$local_colibri_root/ssh"
local_certs_folder="$local_colibri_root/openssl/certs"
local_dp_db_folder="/var/lib/colibri_dp"
local_docker_folder="${local_dp_folder}/docker"
local_pack_file="${local_dp_folder}/dp.tar.gz"
local_automount_folder="$local_colibri_root/automount"
local_repo_folder="$local_colibri_root/repositories"
local_cron_folder="/etc/cron.d"
local_automount_cron_task="$local_cron_folder/colibri_osimage_mount"

### End Init variables

### Verify prerequisites ###

Write_Log "### Test Docker Version"

Write_Log "- Verify current Docker(&Compose) version"
if [ -z "$(which docker)" ]; then
	Write_Log "Docker is not installed. Stop installation" "ERROR"
	bash "$local_dp_folder"/uninstall.sh true
	exit 1
fi

local_docker_ver=$(docker --version | awk '{gsub(",","",$3);print $3}')
if [ -z "$local_docker_ver" ]; then
	Write_Log "Docker version is empty" "ERROR"
	bash "$local_dp_folder"/uninstall.sh true
	exit 2
fi
Write_Log "  - Installed Docker [$local_docker_ver]"

local_docker_compose_ver=$(docker compose version | awk '{gsub("v","",$4);print $4}')
if [ -z "$local_docker_compose_ver" ]; then
	Write_Log "Docker compose version is empty" "ERROR"
	bash "$local_dp_folder"/uninstall.sh true
	exit 3
fi
Write_Log "  - Installed Docker Compose [$local_docker_compose_ver]"

Compare_Versions "$docker_min_ver" "$local_docker_ver"
ret_docker_ver=$?
if [ $ret_docker_ver -eq 1 ]; then
	Write_Log "Currently installed Docker version [$local_docker_ver] is lower then minimal required [$docker_min_ver]" "ERROR"
	bash "$local_dp_folder"/uninstall.sh true
	exit 4
fi

Compare_Versions "$docker_compose_min_ver" "$local_docker_compose_ver"
ret_docker_compose_ver=$?
if [ $ret_docker_compose_ver -eq 1 ]; then
	Write_Log "Currently installed Docker Compose version [$local_docker_compose_ver] is lower then minimal required [$docker_compose_min_ver]" "ERROR"
	bash "$local_dp_folder"/uninstall.sh true
	exit 5
fi

Write_Log "### Process leftovers"
Write_Log "- Cleanup leftovers"
bash "$local_dp_folder"/uninstall.sh true

Write_Log "- Detect old style images"
if [ -d "$local_repo_folder/software/img_repo" ] && [ $(find "$local_repo_folder/software/img_repo" -type f -iname '*.iso' | wc -l) -gt 0 ]; then
	if [ -f $local_automount_folder/automount.csv ]; then
		Write_Log "- Old automount task list detected. Start conversion"
		mkdir -p "$local_repo_folder/os/img_repo" >/dev/null 2>&1
		mkdir -p "$local_automount_folder/img" >/dev/null 2>&1
		for image in $(sed 1d $local_automount_folder/automount.csv); do
			image_file=$(echo "$image" | awk -F',' '{print $2}')
			image_id=$(echo "$image" | awk -F',' '{print $1}')
			Write_Log "Processing [$image_file]..."
			mv "$local_repo_folder/software/img_repo/${image_file}" "$local_repo_folder/os/img_repo/${image_id}.iso"
			echo "id=${image_id}" > "$local_automount_folder/img/${image_id}.immnt"
			echo "filename=${image_id}.iso" >> "$local_automount_folder/img/${image_id}.immnt"
			echo "action=mount" >> "$local_automount_folder/img/${image_id}.immnt"
		done
		rm -f "$local_automount_folder/automount.csv" >/dev/null 2>&1
		rm -f "$local_automount_folder/automount.sh" >/dev/null 2>&1
		Write_Log "- Remove old images dir recursively [$local_repo_folder/software/img_repo]"
		rm -rf "$local_repo_folder/software/img_repo" >/dev/null 2>&1
	else
		Write_Log "- Old automount task list not found"
	fi
else
	Write_Log "- Old image location empty or not exists. Proceed with installation"
fi

Write_Log "### Test prerequisites"

if [ -z "$dp_id" ] || [ -z "$dp_port" ] || [ -z "$dp_secret" ] || [ -z "$dp_url_signalr" ]; then
	Write_Log "Some of required input parameters are empty:" "ERROR"
	[ -z "$dp_id" ] && Write_Log "DP ID is empty" "ERROR"
	[ -z "$dp_port" ] && Write_Log "DP Port is empty" "ERROR"
	[ -z "$dp_secret" ] && Write_Log "DP Secret is empty" "ERROR"
	[ -z "$dp_url_signalr" ] && Write_Log "SignalR URL is empty" "ERROR"
	bash "$local_dp_folder"/uninstall.sh true
	exit 10
fi

Write_Log "- Validate downloaded files"
if [ ! -d "$local_dp_folder" ]; then
	Write_Log "DP folder [$local_dp_folder] is not detected on a client. Stop installation" "ERROR"
	bash "$local_dp_folder"/uninstall.sh true
	exit 11
fi

if [ ! -f "$local_pack_file" ]; then
	Write_Log "Archive with DP files is not available on a client. Stop installation" "ERROR"
	bash "$local_dp_folder"/uninstall.sh true
	exit 12
fi

if [ ! -f "${local_dp_folder}/automount.sh" ]; then
	Write_Log "Automount script is not detected at [${local_dp_folder}/automount.sh]" "ERROR"
	bash "$local_dp_folder"/uninstall.sh true
	exit 13
fi

Write_Log "- Validate downloader tools"
if [ -z "$(which curl)" ] && [ -z "$(which wget)" ]; then
	Write_Log "Neither curl nor wget tool were detected. There are no tools for downloading purposes. Stop installation" "ERROR"
	bash "$local_dp_folder"/uninstall.sh true
	exit 14
fi

Write_Log "- Validate SSH installation"
if [ -z "$(which sshd)" ]; then
	Write_Log "SSHD is not detected. Unable to proceed. Stop installation" "ERROR"
	bash "$local_dp_folder"/uninstall.sh true
	exit 15
fi

Write_Log "- Validate SSH configuration"
ssh_auth_config="$(sed -En 's/^PubkeyAuthentication\s(.*)/\1/p' /etc/ssh/sshd_config)"
if [ -n "$ssh_auth_config" ] && [ "${ssh_auth_config,,}" != "yes" ]; then
	Write_Log "SSHD option PubkeyAuthentication is set to [$ssh_auth_config] but has to be configured [yes]. Unable to proceed. Stop installation" "ERROR"
	bash "$local_dp_folder"/uninstall.sh true
	exit 16
fi

Write_Log "Test OK"

### End Download prerequisites ###

Write_Log "### Process DP archive"

Write_Log "- Prepare certificate for container"
Write_Log "  - Make dir for CA"
[ ! -d "$local_certs_folder" ] && mkdir -p "$local_certs_folder" >/dev/null 2>&1
Write_Log "  - Download certificate"
{ out_dwn_crt=$( (wget "$remote_cert_file" -O "$local_certs_folder"/colibriCA.crt) 2>&1 1>&3-) ;} 3>&1
ret_dwn_crt=$?
if [ $ret_dwn_crt -ne 0 ]; then
	Write_Log "Error during Colibri CA downloading. Exit code: [$ret_dwn_crt]. Details: [$out_dwn_crt]" "WARNING"
	bash "$local_dp_folder"/uninstall.sh true
	exit 20
fi

Write_Log "- Read remote hash file"
remote_file_hash=$(wget -q -O - "$remote_hash_file" || curl -L "$remote_hash_file")
if [ -z "$remote_file_hash" ]; then
	Write_Log "Hash file is empty. Stop installation" "ERROR"
	bash "$local_dp_folder"/uninstall.sh true
	exit 21
fi

Write_Log "- Check archive hash"
local_file_hash=$(md5sum "$local_pack_file" | awk '{print $1}')
if [ "$remote_file_hash" != "$local_file_hash" ]; then
	Write_Log "Local file hash [$local_file_hash] did not match remote file hash [$remote_file_hash]" "ERROR"
	Write_Log "Remove broken archive [$local_pack_file]" "WARNING"
	{ out_remove_pack=$( (rm -f "$local_pack_file") 2>&1 1>&3-) ;} 3>&1
	ret_remove_pack=$?
	if [ $ret_remove_pack -ne 0 ]; then
		Write_Log "Error during archive removal. Exit code: [$ret_remove_pack]. Details: [$out_remove_pack]" "ERROR"
	fi
	bash "$local_dp_folder"/uninstall.sh true
	exit 22
fi

Write_Log "- Prepare docker dir"
[ ! -d "$local_docker_folder" ] && mkdir -p "$local_docker_folder" >/dev/null 2>&1

Write_Log "- Extract archive"
{ out_extract_tar=$( (tar -xzf "$local_pack_file" -C "$local_docker_folder") 2>&1 1>&3-) ;} 3>&1
ret_extract_tar=$?
if [ "$ret_extract_tar" -ne 0 ]; then
	Write_Log "ERROR extracting archive. Stop installation. Exit code: [$ret_extract_tar]. Details: [$out_extract_tar]" "ERROR"
	{ out_remove_pack=$( (rm -f "$local_pack_file" >/dev/null 2>&1) 2>&1 1>&3-) ;} 3>&1
	ret_remove_pack=$?
	if [ $ret_remove_pack -ne 0 ]; then
		Write_Log "Error during archive removal. Exit code: [$ret_remove_pack]. Details: [$out_remove_pack]" "ERROR"
	fi
	bash "$local_dp_folder"/uninstall.sh true
	exit 23
fi

Write_Log "- Remove archive"
{ out_remove_pack=$( (rm -f "$local_pack_file") 2>&1 1>&3-) ;} 3>&1
ret_remove_pack=$?
if [ $ret_remove_pack -ne 0 ]; then
	Write_Log "Error during archive removal. Exit code: [$ret_remove_pack]. Details: [$out_remove_pack]" "WARNING"
fi

Write_Log "### Prepare local directories and configure automount"

Write_Log "- Prepare DP service dirs"
[ ! -d "$local_dp_db_folder" ] && mkdir -p "$local_dp_db_folder" >/dev/null 2>&1

Write_Log "- Prepare SSH dir for samba and nginx containers"
[ -d "$local_ssh_folder" ] && rm -rf "$local_ssh_folder" >/dev/null 2>&1
mkdir -p "$local_ssh_folder" >/dev/null 2>&1

Write_Log "- Prepare automount dirs"
[ ! -d "$local_automount_folder/report" ] && mkdir -p "$local_automount_folder/report" >/dev/null 2>&1
[ ! -d "$local_automount_folder/img" ] && mkdir -p "$local_automount_folder/img" >/dev/null 2>&1

Write_Log "- Prepare repo dirs"
[ ! -d "$local_repo_folder/software" ] && mkdir -p "$local_repo_folder/software" >/dev/null 2>&1
[ ! -d "$local_repo_folder/service_repo/osdeployments/\$OEM\$" ] && mkdir -p "$local_repo_folder/service_repo/osdeployments/\$OEM\$" >/dev/null 2>&1
[ ! -d "$local_repo_folder/service_repo/osdeployments/Out-of-Box Drivers" ] && mkdir -p "$local_repo_folder/service_repo/osdeployments/Out-of-Box Drivers" >/dev/null 2>&1
[ ! -d "$local_repo_folder/service_repo/osdeployments/pefiles" ] && mkdir -p "$local_repo_folder/service_repo/osdeployments/pefiles" >/dev/null 2>&1
[ ! -d "$local_repo_folder/osimages" ] && mkdir -p "$local_repo_folder/osimages" >/dev/null 2>&1

if [ -d "$local_repo_folder/osimages/\$OEM\$" ] && [ "$(readlink -m "$local_repo_folder/osimages/\$OEM\$" 2>/dev/null)" == "$local_repo_folder/service_repo/osdeployments/\$OEM\$" ]; then
	Write_Log "Link for OEM folder already exists. Skip"
else
	[ -d "$local_repo_folder/osimages/\$OEM\$" ] && mv -f "$local_repo_folder/osimages/\$OEM\$" "$local_repo_folder/osimages/\$OEM\$_bak"
	{ out_lnk_oem=$( (ln -sr "$local_repo_folder/service_repo/osdeployments/\$OEM\$" "$local_repo_folder/osimages/\$OEM\$") 2>&1 1>&3-) ;} 3>&1
	ret_lnk_oem=$?
	if [ $ret_lnk_oem -ne 0 ]; then
		Write_Log "Error during linking OEM folder. Exit code: [$ret_lnk_oem]. Details: [$out_lnk_oem]" "ERROR"
		bash "$local_dp_folder"/uninstall.sh true
		exit 30
	fi
fi

if [ -d "$local_repo_folder/osimages/Out-of-Box Drivers" ] && [ "$(readlink -m "$local_repo_folder/osimages/Out-of-Box Drivers" 2>/dev/null)" == "$local_repo_folder/service_repo/osdeployments/Out-of-Box Drivers" ]; then
	Write_Log "Link for Out-of-Box Drivers folder already exists. Skip"
else
	[ -d "$local_repo_folder/osimages/Out-of-Box Drivers" ] && mv -f "$local_repo_folder/osimages/Out-of-Box Drivers" "$local_repo_folder/osimages/Out-of-Box Drivers_bak"
	{ out_lnk_oob=$( (ln -sr "$local_repo_folder/service_repo/osdeployments/Out-of-Box Drivers" "$local_repo_folder/osimages/Out-of-Box Drivers") 2>&1 1>&3-) ;} 3>&1
	ret_lnk_oob=$?
	if [ $ret_lnk_oob -ne 0 ]; then
		Write_Log "Error during linking Out-of-Box Drivers folder. Exit code: [$ret_lnk_oob]. Details: [$out_lnk_oob]" "ERROR"
		bash "$local_dp_folder"/uninstall.sh true
		exit 31
	fi
fi

if [ -d "$local_repo_folder/osimages/pefiles" ] && [ "$(readlink -m "$local_repo_folder/osimages/pefiles" 2>/dev/null)" == "$local_repo_folder/service_repo/osdeployments/pefiles" ]; then
	Write_Log "Link for pefiles folder already exists. Skip"
else
	[ -d "$local_repo_folder/osimages/pefiles" ] && mv -f "$local_repo_folder/osimages/pefiles" "$local_repo_folder/osimages/pefiles_bak"
	{ out_lnk_pe=$( (ln -sr "$local_repo_folder/service_repo/osdeployments/pefiles" "$local_repo_folder/osimages/pefiles") 2>&1 1>&3-) ;} 3>&1
	ret_lnk_pe=$?
	if [ $ret_lnk_pe -ne 0 ]; then
		Write_Log "Error during linking pefiles folder. Exit code: [$ret_lnk_pe]. Details: [$out_lnk_pe]" "ERROR"
		bash "$local_dp_folder"/uninstall.sh true
		exit 32
	fi
fi

Write_Log "- Move automount to its folder"
{ out_mv_am=$( (mv "${local_dp_folder}/automount.sh" "${local_automount_folder}/automount.sh") 2>&1 1>&3-) ;} 3>&1
ret_mv_am=$?
if [ $ret_mv_am -ne 0 ]; then
	Write_Log "Error during moving automount.sh. Exit code: [$ret_mv_am]. Details: [$out_mv_am]" "ERROR"
	bash "$local_dp_folder"/uninstall.sh true
	exit 33
fi

Write_Log "- Set execute attribute for automount"
{ out_cm_am=$( (chmod +x "${local_automount_folder}/automount.sh") 2>&1 1>&3-) ;} 3>&1
ret_cm_am=$?
if [ $ret_cm_am -ne 0 ]; then
	Write_Log "Error during changing attribute for automount.sh. Exit code: [$ret_cm_am]. Details: [$out_cm_am]" "ERROR"
	bash "$local_dp_folder"/uninstall.sh true
	exit 34
fi

Write_Log "- Create automount watcher"
cat >${local_automount_folder}/automount_watcher.sh <<"EOL"
#!/bin/bash
automount_dir=/opt/colibri/automount
images_dir="${automount_dir}/img"
automount_script="${automount_dir}/automount.sh"
stored_hash="${automount_dir}/automount_hash"

calc_hash=$(ls -Al "$images_dir" | md5sum | awk '{print $1}')

if [ -f "$stored_hash" ]; then
    hash=$(cat "$stored_hash")
    if [[ "${hash,,}" != "${calc_hash,,}" ]]; then
        echo "$calc_hash" > "$stored_hash"
        eval "$automount_script"
    fi
else
    echo "$calc_hash" > "$stored_hash"
    eval "$automount_script"
fi
EOL
if [ ! -f "${local_automount_folder}/automount_watcher.sh" ]; then
    Write_Log "Cron watcher for automount was not created. Stop installation" "ERROR"
    bash "$local_dp_folder"/uninstall.sh true
    exit 35
fi

Write_Log "- Set execute attribute for automount watcher"
{ out_cm_aw=$( (chmod +x "${local_automount_folder}/automount_watcher.sh") 2>&1 1>&3-) ;} 3>&1
ret_cm_aw=$?
if [ $ret_cm_aw -ne 0 ]; then
	Write_Log "Error during changing attribute for automount.sh. Exit code: [$ret_cm_aw]. Details: [$out_cm_aw]" "ERROR"
	bash "$local_dp_folder"/uninstall.sh true
	exit 36
fi

Write_Log "- Create cron regular task for automount"
cat > $local_automount_cron_task <<EOL
0 0 * * *	root	${local_automount_folder}/automount.sh
@reboot		root	${local_automount_folder}/automount.sh
* * * * *	root	${local_automount_folder}/automount_watcher.sh
EOL
chmod 0644 $local_automount_cron_task > /dev/null 2>&1
if [ ! -f "$local_automount_cron_task" ]; then
    Write_Log "Cron regular task for automount was not created. Stop installation" "ERROR"
    bash "$local_dp_folder"/uninstall.sh true
    exit 37
fi


Write_Log "### Configure user and SSH keys"

Write_Log "- Test if docker group created"
if ! grep -qi '^docker:' /etc/group; then
	Write_Log "Docker group 'docker' is not detected. Stop installation" "ERROR"
	bash "$local_dp_folder"/uninstall.sh true
	exit 40
fi

Write_Log "- Create user for managing colibri containers"
if ! grep -qi "^$colibri_user:" /etc/passwd; then
	{ out_crt_usr=$( (useradd --system --create-home "$colibri_user") 2>&1 1>&3-) ;} 3>&1
	ret_crt_usr=$?
	if [ $ret_crt_usr -ne 0 ]; then
		Write_Log "Unable to create service user for Colibri [$colibri_user]. Exit code: [$ret_crt_usr]. Details: [$out_crt_usr]" "ERROR"
		bash "$local_dp_folder"/uninstall.sh true
		exit 41
	fi
fi

Write_Log "- Add created user to 'docker' group"
{ out_mod_usr=$( (usermod -aG docker "$colibri_user") 2>&1 1>&3-) ;} 3>&1
ret_mod_usr=$?
if [ $ret_mod_usr -ne 0 ]; then
	Write_Log "Unable to add [$colibri_user] to group 'docker'. Exit code: [$ret_mod_usr]. Details: [$out_mod_usr]" "ERROR"
	bash "$local_dp_folder"/uninstall.sh true
	exit 42
fi

Write_Log "- Create ssh config user folder in [$colibri_user] profile"
[ ! -d "/home/$colibri_user/.ssh/" ] && sudo -H -u "$colibri_user" bash -c "mkdir -p \"/home/$colibri_user/.ssh\"" >/dev/null 2>&1

Write_Log "- Generate SSH key for [$colibri_user]"
{ out_ssh_gen=$( (sudo -H -u "$colibri_user" bash -c "rm -f \"/home/$colibri_user/id_rsa_colibri_sshfs\" >/dev/null 2>&1; ssh-keygen -t rsa -b 4096 -q -N \"\" -f \"/home/$colibri_user/id_rsa_colibri_sshfs\"") 2>&1 1>&3-) ;} 3>&1
ret_ssh_gen=$?
if [ $ret_ssh_gen -ne 0 ]; then
	Write_Log "Unable to generate an SSH key. Exit code: [$ret_ssh_gen]. Details: [$out_ssh_gen]" "ERROR"
	bash "$local_dp_folder"/uninstall.sh true
	exit 43
fi

Write_Log "- Update SSH private key permissions"
{ out_ssh_prm=$( (sudo -H -u "$colibri_user" bash -c "chmod 0600 \"/home/$colibri_user/id_rsa_colibri_sshfs\"") 2>&1 1>&3-) ;} 3>&1
ret_ssh_prm=$?
if [ $ret_ssh_prm -ne 0 ]; then
	Write_Log "Unable to update SSH private key permissions. Exit code: [$ret_ssh_prm]. Details: [$out_ssh_prm]" "ERROR"
	bash "$local_dp_folder"/uninstall.sh true
	exit 44
fi


Write_Log "- Copy public key to common SSH folder for containers"
cp --preserve=all /home/$colibri_user/id_rsa_colibri_sshfs* "$local_ssh_folder" >/dev/null 2>&1

Write_Log "- Add SSH key to [$colibri_user] authorized keys"
{ out_ssh_add=$( (sudo -H -u "$colibri_user" bash -c "cat \"/home/$colibri_user/id_rsa_colibri_sshfs.pub\" >> \"/home/$colibri_user/.ssh/authorized_keys\"") 2>&1 1>&3-) ;} 3>&1
ret_ssh_add=$?
if [ $ret_ssh_add -ne 0 ]; then
	Write_Log "Unable to append to [$colibri_user]'s ssh authorized keys file. Exit code: [$ret_ssh_add]. Details: [$out_ssh_add]" "ERROR"
	bash "$local_dp_folder"/uninstall.sh true
	exit 45
fi

Write_Log "- Change ownership on automount img task folder"
chown -R ${colibri_user}:${colibri_user} "$local_automount_folder/img"


Write_Log "### Configure & Run containers"

if [ ! -f "$local_docker_folder/.env" ]; then
	Write_Log "Environment file not found. Stop installation" "ERROR"
	bash "$local_dp_folder"/uninstall.sh true
	exit 50
fi

Write_Log "- Update Environment variables"
Write_Log "  - Set DP ID"
Update_Env "$local_docker_folder/.env" "DPID" "$dp_id"
Write_Log "  - Set DP Port to [$dp_port]"
Update_Env "$local_docker_folder/.env" "NGINX_DP_PORT" "$dp_port"
Write_Log "  - Set DP Secret"
Update_Env "$local_docker_folder/.env" "DPSECRET" "$dp_secret"
Write_Log "  - Set SignalR URL to [$dp_url_signalr]"
Update_Env "$local_docker_folder/.env" "APIADDR" "$dp_url_signalr"
dp_fqdn=$(hostname -f 2>/dev/null)
Write_Log "  - Set DP FQDN to [$dp_fqdn]"
Update_Env "$local_docker_folder/.env" "NGINX_DP_FQDN" "$dp_fqdn"
colibri_user_id=$(id -u "$colibri_user")
colibri_group_id=$(id -g "$colibri_user")
Write_Log "  - Set USER NAME to [$colibri_user]"
Update_Env "$local_docker_folder/.env" "USER_NAME" "$colibri_user"
Write_Log "  - Set USER ID to [$colibri_user_id]"
Update_Env "$local_docker_folder/.env" "USER_ID" "$colibri_user_id"
Write_Log "  - Set GROUP NAME to [$colibri_user]"
Update_Env "$local_docker_folder/.env" "GROUP_NAME" "$colibri_user"
Write_Log "  - Set GROUP ID to [$colibri_group_id]"
Update_Env "$local_docker_folder/.env" "GROUP_ID" "$colibri_group_id"


Write_Log "- Processing images"
docker_images=$(find "$local_docker_folder/img/" -name "*.tar")
if [ "$(echo "$docker_images" | wc -l)" -eq 0 ]; then
	Write_Log "No images detected in [$local_docker_folder/img/]" "ERROR"
	bash "$local_dp_folder"/uninstall.sh true
	exit 51
fi

for image in $docker_images; do
	Write_Log "  - Loading image [$image]"
	out_load=""
	ret_load=""
	{ out_load=$( (docker load -i "$image") 2>&1 1>&3-) ;} 3>&1
	ret_load=$?
	if [ $ret_load -ne 0 ]; then
		Write_Log "Failed to load image. Exit code: [$ret_load]. Details: [$out_load]" "ERROR"
		bash "$local_dp_folder"/uninstall.sh true
		exit 52
	fi
	Write_Log "  - Loaded. Remove image file"
	rm -f "$image" >/dev/null 2>&1
done
Write_Log "  - All images loaded"
rmdir "$local_docker_folder/img" >/dev/null 2>&1

Write_Log "  - Rename image tags"
for image in $(docker image ls "*/colibri/*" | awk '{OFS=";"}; NR>1 {print $1,$2,$3}'); do 
	image_repo=$(echo "$image" | awk -F';' '{print $1}')
	image_repo_new=$(echo "$image" | awk -F';' 'gsub("localhost/","",$1) {print $1}')
	image_tag=$(echo "$image" | awk -F';' '{print $2}')
	image_id=$(echo "$image" | awk -F';' '{print $3}')
	docker tag "$image_id" "${image_repo_new}:${image_tag}"
	docker image rm "${image_repo}:${image_tag}"
done

Write_Log "Run Docker Compose"
docker compose -f $local_docker_folder/docker-compose.yml up -d

Write_Log "Wait for all containers become running"
wait_iteration_time_sec=5
iteration_count=1
total_iterations=60 # 5 minutes timeout
total_sec=$((total_iterations * wait_iteration_time_sec))
all_started=0
while [ $iteration_count -lt $total_iterations ] && [ $all_started -eq 0 ]; do
	for image_name in $(docker compose -f "$local_docker_folder/docker-compose.yml" config --images 2>/dev/null); do
		container_name=$( (grep "$image_name" <<< "$(docker compose -f "$local_docker_folder/docker-compose.yml" ps --format '{{.Image}} {{.Name}}' 2>/dev/null)") | awk '{print $2}')
		Write_Log "Image name: [$image_name]. Container name [$container_name]"
		if [ -n "$container_name" ]; then
			status=$(docker container inspect -f '{{.State.Running}}' "$container_name" 2>/dev/null)
			health=$(docker container inspect -f '{{.State.Health.Status}}' "$container_name" 2>/dev/null)
			if [ "$status" != "true" ]; then
				Write_Log "Container [$container_name]. Status is not OK: [$status]" "WARNING"
				all_started=0
				break
			fi
			if [ -n "$health" ] && [ "$health" != "healthy" ]; then
				Write_Log "Container [$container_name] is not yet healthy, status [$health]" "WARNING"
				if [ "$health" == "unhealthy" ]; then
					Write_Log "Container [$container_name] will be restarted" "WARNING"
					docker restart "$container_name" >/dev/null 2>&1
				fi
				all_started=0
				break
			fi
			Write_Log "Container [$container_name] is running and healthy"
			all_started=1
		else
			Write_Log "Container [$container_name] is not started yet"
			all_started=0
			break
		fi
	done
	if [ $all_started -eq 0 ]; then
		iteration_count=$((iteration_count + 1))
		Write_Log "Wait for $wait_iteration_time_sec sec..." "WARNING"
		sleep $wait_iteration_time_sec
		Write_Log "Next try"
	fi
done

if [ $iteration_count -eq $total_iterations ]; then
	Write_Log "Containers are not ready after timeout [$total_sec] sec" "ERROR"
	bash "$local_dp_folder"/uninstall.sh true
	exit 53
fi

Write_Log "Installation completed successfully"