#!/usr/bin/env bash

declare -A config_ubinstall
declare -a BLK_ARRAY

version=2.38

config_default=$(cat <<EOF
#  Configuration file to configure the installer ubinstall

# Language and time zone settings
[language]
# Installer Language
lang=Russian
# System language (ru_RU.UTF-8 by default)
system_lang=
# Regional format for numbers and symbols
regional_format=
# Layout
keymap=us
# time zone
zone=

# Installer configuration
[autoinstall]
# Boot Type
# bootloader=ugpt+bgpt
# The device where the system will be installed
device=sdx
# Determine the size of the system partition (to install next to another system)
size=
# Volume Label
label=ublinux

# bootloader configuration
[bootloader]
# Boot partition name
boot_partition=
# Boot partition type
# bootloader_type=
# Boot loader provider (GRUB, syslinux, etc.)
# bootloader_provider=
# Boot partition label
# label=ublinux

# partition configuration
[storage@system]
# Number of sections
# number_partitions=
# Section Label
# label=ublinux
# There will also be dynamically created partitions here
# (e.g. partition1, partition2, partitionN)
# the value of each variable of the form:
# "partition1=sda1:ext4:/mnt:1928"
# in the form of: "path:file_system:mount_point:size(in Bytes)"
# to create partitions in a manual installation

# obsolete parameters (not used)
[storage@user]
# drive=
# partition_array=
# set_of_partition_to_filesystem_maps=

# obsolete parameters (not used)
[storage@swapfile]
# location=
# size=

# User Configuration
[user]
# Login
user_name=
# User password
user_password=
# Root password
root_password=
# Full user name (with '_')
full_name=
# Perform automatic login (yes/no)
autologin=

# Network Setup
[network]
# Hostname
hostname=ubstation
# Domain name
# domain=local
# Interface name
# interface=enp2s0
# Auto-raise network  (dhcp/static)
# if_setup_toggle=
# Configuration wi-fi (on/off)
# wi-fi=
# Using the default connection type (wifi/ethernet)
# media=

# Configuration dhcp
[network@dhcp]
# Settings Provider dhc
# dhcp_provider=NetworkManager

# Static connection configuration
[network@static]
# ip-address connections
# ip_address=
# Connection mask
# netmask=
# connection gateway
# gateway=
# default dns-server
# dns-server=

# Module configuration (in development)
[modules]
# TBA

# Other settings
[miscellaneous]
# Type of installation:
# "install-fast" - Quick installation (with default settings)
# "near" - Installation next to another system
# "part" - installation into an existing partition of another system
# "grub-upd" - bootloader update
# "grub-install" - bootloader installation
# "os-only" - Installing only OS components without user data
# "user-only" - Installing only user data without OS components
# "hybrid-os-user" - Installing OS components and user data on different disk partitions
type_of_install=
# Enable data logging (true/false)
enable_log=true
# Enable debug mode (true/false)
enable_debug=false
# Default password
default_password=ublinux
# Format the partition before installing (true/false)
formatting_part=

EOF
)

sgn_txt_ublinux=$(cat <<EOF
Не удаляйте этот файл, иначе UBLinux не сможет загрузиться
Вы можете передать параметр 'sgnfile=...' чтобы указать другое имя,
в отличие от оригинального. Это может быть полезно, если у вас
используется несколько разных вариантов UBLinux.

Don't delete this file, else UBLinux won't work.
You may use 'sgnfile=...' boot parameter to search for a different name
than the default. This can be useful if you need to store several
linux-live distros on one machine.
EOF
)

sgn_txt_ublinux_data=$(cat <<EOF
Не удаляйте этот файл, иначе UBLinux не сможет найти данные локальных настроек.
Вы можете передать параметр 'sgndatafile=...' чтобы указать другое имя,
в отличие от оригинального. Это может быть полезно, если у вас
используется несколько разных вариантов UBLinux.

Don't delete this file, else UBLinux won't find local data files.
You may use 'sgndatafile=...' boot parameter to search for a different name
than the default. This can be useful if you need to store several
linux-live distros on one machine.
EOF
)

msg_version="ubinstall, version %s
Copyright (C) 2020 Ubiteh, Inc.
License GPLv3+: GNU GPL version 3 or later <http://ublinux.ru>"

msg_usage="Ublinux console installation
    Usage:    %s [-d][-i][-if][-ns][-sip][-gu][-gi][-gpc][-glb][-l][-h]

    -gpc | --get_path_conf
        Create a configuration file
    
    -glb | --get_list_block
        Get list of block device

    -r | --real
        Running the installation without this key will lead to a test
        installation without actually copying files and creating partitions
        on the disk
    
    -g | --gen_config
        Generate an empty configuration file
    
    -c=* | --config=*
        Use your own configuration file.
        An example file can be created using the -g | --gen-config key

    -h | --help
        Show a hint"

i18n() {
    local key="$1"; shift
    printf "$(gettext -s "$key")" "$@"
}

# ini_read_config() ###########################################################################################
#		$1 - read from file /path/filename.conf (ex. ${file_config}"), 
#		     if not found file then read variable default config txt (ex. "${default_config}") 
#		$2 - name variable associative array (ex. "ubinstall_config")
#		declare -A ubinstall_config
#		ini_read_config "${config}" "ubinstall_config"
#		ex. ubinstall_config["block.field"]="new"
#		Плюсы :
#		    1. можно иметь несколько загруженых файлов конфигураций
#		    2. можно получить доступ ко всем именам блоков через массив
#		    3. к именам field нет ограничений, хоть пробелы
##############################################################################################################
ini_read_config() {
    [[ -f $1 ]] && local config_txt=$(cat $1) || local config_txt=$1
    if [[ -n $2 ]]; then
	local -n array_config=$2
	local sep="." # Separate first block [block.field]=value
	while IFS='=' read -r key value; do
		array_config[${key}]=${value}
	done < <(printf "%s\n" "${config_txt}" |
		awk -v sep="${sep}" '/^\[/{ app=substr($0,2,length-2) }
				    /=/ { sub(/^[ \t]+/,"");
				    sub(/[ \t]+=[ \t]+/,"=");
				   if (( $0 !~ /^[#;/]/ ) && ( app != /""/ ))
				    {print app sep $0}
				    }')
    fi
}

ini_write_config() {
    local -n array_config=$2
    [[ ! -f $1 ]] && echo "ERROR: file $1 not found!" && exit 1
    case "$3" in
	new)
		echo > $1
		for key in "${!array_config[@]}"; do 
			printf '[%s]=%s\n' "$key" "${array_config[$key]}"
		done | sort -t = -k 1 >> $1
	;;
	change | *)
	    local sep="."
	    for key in "${!array_config[@]}"; do
            if [[ ${key} == *${sep}* ]]; then
                sed -i "/^\[${key%%${sep}*}]/,/^\[.*]/{s|^[ \t]\+||; s|[ \t]\+=[ \t]\+|=|; s|^${key#*${sep}}=.*|${key#*${sep}}=${array_config[$key]}|}" "${1}"
            else
                sed -i "/^\[$2]/,/^\[.*]/{s/^[ \t]\+//; s/[ \t]\+=[ \t]\+/=/; s/^${key}=.*/${key}=${array_config[$key]}/}" "${1}"
            fi
	    done
	;;
    esac
}

check_root(){
    if [[ "$(id -nu)" != "root" ]]; then
	echo "$(i18n "Options %s must be run as root" $1)"
	echo "###############################################################################" 1>&3
    	echo "#### $(i18n "Error: Options %s must be run as root" $1)" 1>&3
    	echo "###############################################################################" 1>&3
	echo "$(i18n "${msg_usage}" "$(basename $0)")" 1>&3 
#"
	return 1
#	exit 1
    fi
}

_init_(){
    # Define exit codes
    ERR_C=-1	# Error code
    OK_C=0 	# OK button is pressed
    CANCEL_C=1 	# Cancel button is pressed
    HELP_C=2	# Help code
    EXTRA_C=3 	# Extra button is pressed
    ESC_C=255 	# ESC button is pressed

    path_root=""
#    ROOT_DIR="/mnt/livemedia/other/ubinstall"
    path_ubinstall_tmp="${path_root}/tmp/ubinstall"
    [[ ! -d "${path_ubinstall_tmp}" ]] && install -m 777 -d ${path_ubinstall_tmp}
    PATH_UBBOOT_LIB="/usr/lib/ubboot"
    PATH_UBBOOT_TEMPLATE="/usr/share/ubboot"

    export TEXTDOMAIN=$(basename "$0")
    export TEXTDOMAINDIR="${path_root}/usr/share/locale"

    log_file="${path_root}/var/log/ubinstall.log"
    echo 1>/dev/null 2>&1 > ${log_file} && chmod 666 ${log_file} 1>/dev/null 2>&1
    progressbar_file="${path_ubinstall_tmp}/ubinstall_progress.log"
    echo "0.01|$(i18n "Starting installation")" > "${progressbar_file}"
    chmod 666 "${progressbar_file}" 1>/dev/null 2>&1
# Initialize file config ublinux.conf
    config_file_etc="${path_root}/etc/ublinux/ubinstall.conf"
    config_file_current="${path_ubinstall_tmp}/ubinstall.conf"
    ([[ -f "${config_file_etc}" ]] && [[ ! -f "${config_file_current}" ]] && cp -f ${config_file_etc} ${config_file_current}) || ([[ ! -f "${config_file_current}" ]] && echo "${config_default}" > ${config_file_current})
    chmod 666 ${config_file_current}
    ini_read_config "${config_file_current}" "config_ubinstall"

    if which mkpasswd2 &>/dev/null ; then
        passCmd="mkpasswd2 -m gost-yescrypt"
    else
        passCmd="openssl passwd -6"
    fi
}

create_empty_config(){
    path_new_config="$HOME/ubinstall.conf"
    [ ! -f "$path_new_config" ] && echo "$config_default" > "$path_new_config"
    ini_read_config "$path_new_config" "config_ubinstall"
    for i in ${!config_ubinstall[@]}; do
        config_ubinstall[$i]=""
    done
    ini_write_config "${path_new_config}" "config_ubinstall"
    echo -e "$(i18n "The configuration file is generated by the path"):\n${path_new_config}\n" >&4
}

read_custom_config(){
    local path="$1"

    [ ! -f "$path" ] && return 1

    config_file_current="$path"
    ini_read_config "${config_file_current}" "config_ubinstall"
}

drive_info(){
    partprobe /dev/$1	# Информируем ядро об изменении разделов
    echo -e "################################################################"
    echo -e "#### $(i18n "Drive info: %s" "fdisk -l /dev/$1") ####" 
    echo -e "0.01|$(i18n "Checking drive")" >&5
    fdisk -l /dev/$1
    echo -e "\n################################################################"
    echo -e "#### $(i18n "Drive info: %s" "sgdisk -p /dev/$1") ####"
    echo -e "0.01|$(i18n "Checking drive")" >&5
    sgdisk -p /dev/$1
    echo -e "\n################################################################"
    echo -e "#### $(i18n "Drive info: %s" "sgdisk -O /dev/$1") ####"
    echo -e "0.01|$(i18n "Checking drive")" >&5
    sgdisk -O /dev/$1
}

drive_umount_allparts(){
    sync; sync
    sleep 1
    [[ $(which fuser 2>/dev/null) ]] && [[ -b /dev/$1 ]] && fuser -cuk /dev/$1* 
    umount /dev/$1* &>/dev/null
##    umount -Rl /dev/$1* &>/dev/null
    swapoff -a &>/dev/null
    [[ -n $2 ]] && umount /mnt/$1* &>/dev/null || umount /mnt/$1/* &>/dev/null
    [[ -n $2 ]] && rm -rf /mnt/$1* &>/dev/null || rm -rf /mnt/$1 &>/dev/null
    sleep 0.5
}

drive_partitioning(){
#### Destroy MBR or GPT or other
    echo -e "\n################################################################" 1>&3
    echo "$(i18n "Destroy MBR or GPT on drive: %s" "/dev/$1")" 1>&3
    echo -e "0.02|$(i18n "Partition drive: destroy mbr or gpt on drive")" >&5
### dd if=/dev/zero of=/dev/$1 bs=446 count=1 || return 1; }				# replace X with the target drive letter.    
    [[ -n ${arg_real} ]] && { wipefs -a -f /dev/$1 || return 1; }			# zap GPT and MBR - core/util-linux
    [[ -n ${arg_real} ]] && { sgdisk -Z /dev/$1 || return 1; }				# zap GPT and MBR, create GPT - extra/gptfdisk
    echo "$(i18n "Clear partition table on drive: %s" "/dev/$1")" 1>&3
    echo -e "0.03|$(i18n "Partition drive: clear partition table")" >&5
    [[ -n ${arg_real} ]] && { sgdisk -o /dev/$1 || return 1; }				# clear partition table
    [[ -n ${arg_real} ]] && { sgdisk -a=2048 /dev/$1 || return 1; }			# aligment
    echo "$(i18n "Create partition \"%s\" on drive: %s" "bios_boot" "/dev/$1")" 1>&3
    echo -e "0.04|$(i18n "Partition drive: create partitions")" >&5
    [[ -n ${arg_real} ]] && { sgdisk -a=2048 -n 0:0:+2M -c 0:"bios_boot" -t 0:ef02 /dev/$1 || return 1; }	# create partition
    echo "$(i18n "Create partition \"%s\" on drive: %s" "efi" "/dev/$1")" 1>&3
    echo -e "0.05|$(i18n "Partition drive: create partitions")" >&5
    [[ -n ${arg_real} ]] && { sgdisk -a=2048 -n 0:0:+320M -c 0:"efi" -t 0:ef00 /dev/$1 || return 1; }	# create partition
    echo "$(i18n "Create partition \"%s\" on drive: %s" ${config_ubinstall["autoinstall.label"]} "/dev/$1")"1>&3
    echo -e "0.06|$(i18n "Partition drive: create partitions")" >&5
    [[ -n ${arg_real} ]] && { sgdisk -a=2048 -n 0:0:0 -c 0:${config_ubinstall["autoinstall.label"]} -t 0:8300 /dev/$1 || return 1; }	# create partition
    echo "$(i18n "Create hybrid MBR \"%s\" on drive: %s" "1:2" "/dev/$1")" 1>&3
    echo -e "0.07|$(i18n "Partition drive: create hybrid MBR on drive")" >&5
    [[ -n ${arg_real} ]] && { sgdisk -h 2:3 /dev/$1 || return 1; }					# create hybrid MBR partnum[:partnum...][:EE]
    echo "$(i18n "Set boot atribute partition \"%s\" on drive: %s" "1" "/dev/$1")" 1>&3
    echo -e "0.08|$(i18n "Partition drive: set boot atribute partition on drive")" >&5
    [[ -n ${arg_real} ]] && { sgdisk -A 1:set:2 /dev/$1 || return 1; }					# set boot atribute
    partprobe /dev/$1
    sync; sleep 1
    echo 3 > /proc/sys/vm/drop_caches
    sleep 1
}

make_fs(){
    echo "$(i18n "Make fat32 on partition \"%s\": %s" "efi" "/dev/$(lsblk -no kname,partlabel /dev/$1 | grep efi | cut -d' ' -f1)")" 1>&3
    echo -e "0.10|$(i18n "Make file system")" >&5	#"
    [[ -n ${arg_real} ]] && { mkfs.fat -F32 -n EFI /dev/$(lsblk -no kname,partlabel /dev/$1 | grep efi | cut -d' ' -f1) || return 1; }
    echo "$(i18n "Make ext4 on partition \"%s\": %s" $2 "/dev/$(lsblk -no kname,partlabel /dev/$1 | grep $2 | cut -d' ' -f1)")" 1>&3
    echo -e "0.11|$(i18n "Make file system")" >&5	#"
    [[ -n ${arg_real} ]] && { mkfs.ext4 -F -L $2 /dev/$(lsblk -no kname,partlabel /dev/$1 | grep $2 | cut -d' ' -f1) || return 1; }
    sync; sleep 1
    echo 3 > /proc/sys/vm/drop_caches
    sleep 1
}

drive_mount(){
    echo "$(i18n "Make dirrectory: %s" "/mnt/$1/efi")" 1>&3
    echo -e "0.12|$(i18n "Mount file system")" >&5
    [[ -n ${arg_real} ]] && { mkdir -p /mnt/$1/efi || return 1; }
    echo "$(i18n "Make dirrectory: %s" "/mnt/$1/root")" 1>&3
    echo -e "0.13|$(i18n "Mount file system")" >&5
    [[ -n ${arg_real} ]] && { mkdir -p /mnt/$1/root || return 1; }
    echo "$(i18n "Mount dirrectory device: %s to path: %s" "/dev/$(lsblk -no kname,partlabel /dev/$1 | grep efi | cut -d' ' -f1)" "/mnt/$1/efi")" 1>&3
    echo -e "0.14|$(i18n "Mount file system")" >&5
    [[ -n ${arg_real} ]] && { mount /dev/$(lsblk -no kname,partlabel /dev/$1 | grep efi | cut -d' ' -f1) /mnt/$1/efi || return 1; }
    echo "$(i18n "Mount dirrectory device: %s to path: %s" "/dev/$(lsblk -no kname,partlabel /dev/$1 | grep $2 | cut -d' ' -f1)" "/mnt/$1/root")" 1>&3
    echo -e "0.15|$(i18n "Mount file system")" >&5
    [[ -n ${arg_real} ]] && { mount /dev/$(lsblk -no kname,partlabel /dev/$1 | grep $2 | cut -d' ' -f1) /mnt/$1/root || return 1; }
    sleep 0.5
}

install_grub(){
    echo -e "0.16|$(i18n "Install grub")" >&5
    [[ -z $2 ]] && [[ -n ${arg_real} ]] && (mkdir -p /mnt/$1/root/boot || return 2); [[ $? -eq 2 ]] && return 1
    echo "$(i18n "Install %s" "GRUB target=x86_64-efi")" 1>&3
    echo -e "0.17|$(i18n "Install grub: %s" "GRUB target=x86_64-efi")" >&5
    [[ -n ${arg_real} ]] && grub-install --target=x86_64-efi --efi-directory=/mnt/$1/efi --boot-directory=/mnt/$1/root/boot --removable --recheck \
    && find /mnt/$1/efi -ipath "*/efi/boot/*" -iname "bootx64.efi" -exec install -D -t /mnt/$1/efi/EFI/UBLINUX {} +
    echo "$(i18n "Install %s" "GRUB target=i386-efi")" 1>&3
    echo -e "0.18|$(i18n "Install grub: %s" "GRUB target=i386-efi")" >&5
    [[ -n ${arg_real} ]] && grub-install --target=i386-efi --efi-directory=/mnt/$1/efi --boot-directory=/mnt/$1/root/boot --removable --recheck \
    && find /mnt/$1/efi -ipath "*/efi/boot/*" -iname "bootia32.efi" -exec install -D -t /mnt/$1/efi/EFI/UBLINUX {} +
    echo "$(i18n "Install %s" "GRUB target=i386-pc")" 1>&3
    echo -e "0.19|$(i18n "Install grub: %s" "GRUB target=i386-pc")" >&5
    [[ -n ${arg_real} ]] && { [[ -z $2 ]] && grub-install --target=i386-pc --boot-directory=/mnt/$1/root/boot --recheck /dev/$1 || \
                                            grub-install --target=i386-pc --boot-directory=/mnt/$1/root/boot --recheck /dev/${1::-1}; }
    sync; sleep 1
    echo 3 > /proc/sys/vm/drop_caches
    sleep 1
}

install_uefi_menu(){
    local INSTALL_DEVICE=$1
    command -v efibootmgr &>/dev/null || return 0
    echo "$(i18n "Install UEFI entry")" 1>&3
    echo -e "0.19|$(i18n "Install UEFI entry: %s" "\EFI\Boot\bootx64.efi")" >&5
    # Найти и удалить имеющуюся запись
    FIND_RECORD_EFI=$(efibootmgr -- | grep 'UBLinux' | sed -Ern 's/Boot([[:digit:]]+). .*/\1/p') #'
    [[ -z ${FIND_RECORD_EFI} ]] || efibootmgr -b ${FIND_RECORD_EFI} -B
    local PATH_PART_EFI= FIND_PART_EFI=
    if mountpoint --quiet /mnt/${INSTALL_DEVICE}/efi; then
    # После устанновки GRUB раздел EFI примонтирован, получить устройство от примонтированного раздела
        PATH_PART_EFI="/mnt/${INSTALL_DEVICE}/efi"
        FIND_PART_EFI=$(findmnt --first-only --noheadings --output=SOURCE ${PATH_PART_EFI})
    else
    # Найти первый раздел с меткой EFI
        FIND_PART_EFI=$(blkid --output device --match-token LABEL="EFI" -c /dev/null /dev/${INSTALL_DEVICE}*)
        [[ -n ${FIND_PART_EFI} ]] || FIND_PART_EFI=$(blkid --output device --match-token PARTLABEL="efi" -c /dev/null /dev/${INSTALL_DEVICE}*)
        if [[ -n ${FIND_PART_EFI} ]]; then
            mkdir -p /mnt/${INSTALL_DEVICE/}/efi
            mount ${FIND_PART_EFI} /mnt/${INSTALL_DEVICE}/efi
            PATH_PART_EFI="/mnt/${INSTALL_DEVICE}/efi"
        fi
    fi
    if [[ ${FIND_PART_EFI} =~ ^(/dev/.*)([[:digit:]]+)$ ]]; then
        DEVICE_EFI="${BASH_REMATCH[1]}"
        NUM_PART_EFI="${BASH_REMATCH[2]}"
        local FIND_LOADER=
        [[ -z ${FIND_LOADER} ]] && FIND_LOADER=$(find ${PATH_PART_EFI} -ipath "*/efi/ublinux/*" -type f -iname "bootx64.efi" 2>/dev/null | sed "s|${PATH_PART_EFI}||g" | tr '/' '\\')
        [[ -z ${FIND_LOADER} ]] && FIND_LOADER=$(find ${PATH_PART_EFI} -ipath "*/efi/ublinux/*" -type f -iname "grubx64.efi" 2>/dev/null | sed "s|${PATH_PART_EFI}||g" | tr '/' '\\')
        [[ -z ${FIND_LOADER} ]] && FIND_LOADER=$(find ${PATH_PART_EFI} -ipath "*/efi/boot/*" -type f -iname "bootx64.efi" 2>/dev/null | sed "s|${PATH_PART_EFI}||g" | tr '/' '\\')
        [[ -z ${FIND_LOADER} ]] && FIND_LOADER=$(find ${PATH_PART_EFI} -ipath "*/efi/boot/*" -type f -iname "grubx64.efi" 2>/dev/null | sed "s|${PATH_PART_EFI}||g" | tr '/' '\\')
        [[ -z ${FIND_LOADER} ]] && FIND_LOADER=$(find ${PATH_PART_EFI} -type f -iname "bootx64.efi" 2>/dev/null | sed "s|${PATH_PART_EFI}||g" | tr '/' '\\')
        [[ -z ${FIND_LOADER} ]] && FIND_LOADER=$(find ${PATH_PART_EFI} -type f -iname "grubx64.efi" 2>/dev/null | sed "s|${PATH_PART_EFI}||g" | tr '/' '\\')
        [[ -n ${arg_real} && -n ${DEVICE_EFI} && -n ${NUM_PART_EFI} && -n ${FIND_LOADER} ]] \
        && efibootmgr --create --disk ${DEVICE_EFI} --part ${NUM_PART_EFI} --label "UBLinux" --loader "${FIND_LOADER}"
    fi
}

rootcopy(){
    path_copy_src="/memory/data/from/0"
    path_copy_dst="/mnt/$1/root"
    echo "## $(i18n "Copy BOOT configurations") ##" 1>&3
    echo -e "0.20|$(i18n "Copying file system: clear old files")" >&5
    [[ -n ${arg_real} ]] && rm -rdf ${path_copy_dst}/boot/grub/themes
    echo -e "0.21|$(i18n "Creating skeleton /boot/grub/ublinux , /ublinux/ , /ublinux-data/")" >&5
    [[ -n ${arg_real} ]] && /usr/lib/ubboot/ubboot-skel create -udgt --path-media ${path_copy_dst}
    # Предыдущая команд устанавливет скелет тем граба, ниже лишнее и может привести к незагрузке, если в источнике установки другая версия габа
    #echo -e "0.21|$(i18n "Copying file system: extract boot files")" >&5
    #[[ -n ${arg_real} ]] && tar xJf ${path_copy_src}/ublinux/boot.tar.xz -C ${path_copy_dst}/
    echo "## $(i18n "Copy UBLINUX to file systems") ##" 1>&3
    echo -e "0.22|$(i18n "Copying file system")" >&5
    [ -n ${arg_real} ] && rsync -av --info=progress2 --stats "${path_copy_src}/ublinux" "${path_copy_dst}/" --exclude='ublinux-*.sgn' | \
                            stdbuf -oL tr '\r' '\n' | \
                            tee >(awk -v desc="$(i18n "Copying file system")" -v fPath="${path_copy_src}/" '/^ / { print "0.22|"desc"|"$1"|"$2 ; fflush() ;  next } $0 { print "# " fPath$0  }' >&5) | \
                            awk -v fPath="${path_copy_src}" '/\// && !/,/ { print fPath$0 ; fflush() ; next }' 1>&3
    echo -e "0.87|$(i18n "Update signature")" >&5
    [[ -n ${arg_real} ]] && /usr/lib/ubboot/ubboot-skel update -s --path-media ${path_copy_dst}
    echo -e "0.87|$(i18n "Copying file system")" >&5
    [[ -n ${arg_real} ]] && tar xJf ${path_copy_src}/ublinux/ublinux-data.tar.xz -C ${path_copy_dst}/ --exclude='ublinux-*.sgn'
    # [[ -n ${arg_log} ]] && echo -e "------- 100\n------- 100" 1>&5 || true
#    sync; sleep 1
    echo 3 > /proc/sys/vm/drop_caches
    sleep 1
}

_install_fast_(){
    echo -e "################################################################" 1>&3
    echo -e "#### $(i18n "STARTING FAST INSTALLATIONS %s" "$(date)") ####" 1>&3
    if [[ -b /dev/${config_ubinstall["autoinstall.device"]} ]]; then
	drive_info ${config_ubinstall["autoinstall.device"]}
	    echo -e "0.02|$(i18n "Unmounting parts")" >&5
	drive_umount_allparts ${config_ubinstall["autoinstall.device"]}
	    echo -e "0.02|$(i18n "Partition drive")" >&5
	drive_partitioning ${config_ubinstall["autoinstall.device"]} || return 1
	    echo -e "0.09|$(i18n "Make file system")" >&5
	make_fs ${config_ubinstall["autoinstall.device"]} ${config_ubinstall["autoinstall.label"]} || return 1
	    echo -e "0.12|$(i18n "Mount file system")" >&5
	drive_mount ${config_ubinstall["autoinstall.device"]} ${config_ubinstall["autoinstall.label"]} || return 1
	    echo -e "0.16|$(i18n "Install grub")" >&5
	install_grub ${config_ubinstall["autoinstall.device"]} || return 1
	    echo -e "0.17|$(i18n "Install UEFI entry")" >&5
	install_uefi_menu ${config_ubinstall["autoinstall.device"]}
	    echo -e "0.20|$(i18n "Copying file system")" >&5
	rootcopy ${config_ubinstall["autoinstall.device"]} || return 1
	    echo -e "0.93|$(i18n "Finishing install")" >&5
	post_install "/mnt/${config_ubinstall["autoinstall.device"]}/root"
	    echo -e "0.99|$(i18n "Unmounting parts")" >&5
	drive_umount_allparts ${config_ubinstall["autoinstall.device"]}
	    echo -e "0.99|$(i18n "Checking the disk for errors")" >&5
	check_part_after_install ${config_ubinstall["autoinstall.device"]}
	    echo -e "1.00|$(i18n "Installation is complete!")" >&5
##	drive_info ${config_ubinstall["autoinstall.device"]}
	    echo -e "################################################################" 1>&3 
	    echo -e "#### $(i18n "CONGRATULATIONS! EVERYTHING IS FINE!") ####" 1>&3 
	    echo -e "#### $(i18n "FAST INSTALLATION IS COMPLETE!") ####" 1>&3 
    else
	    echo -e "#### $(i18n "Device %s is not block!" "/dev/${config_ubinstall["autoinstall.device"]}") ####" 1>&3 && return 1
    fi
}

post_install(){
    local path=$1
    local pathRootUblinux="${path}/ublinux"
    local pathRootUblinuxData="${path}/ublinux-data"

    echo -e "0.96|$(i18n "Finishing install")" >&5
    find ${pathRootUblinux} -type d -exec chmod -R 644 {} \; -exec chmod 755 {} \; -exec chown -R root:root {} \;
    echo -e "0.97|$(i18n "Finishing install")" >&5
    find ${pathRootUblinux} -maxdepth 1 -type f -exec chmod -R 400 {} +

    echo -e "0.98|$(i18n "Finishing install")" >&5
    [[ -n ${arg_real} ]] ||  return 1
    ubconfig --target "${pathRootUblinuxData}/ublinux.ini" set [system] FIRSTSTART=yes #&>/dev/null
    [[ ${config_ubinstall[user.autologin]} == yes ]] && ubconfig --target "${pathRootUblinuxData}/ublinux.ini" set [desktop] AUTOLOGINUSER=yes #&>/dev/null
    [[ -z ${config_ubinstall[user.root_password]} ]] || ubconfig --target "${pathRootUblinuxData}/ublinux.ini" set [users] DEFAULTROOTPASSWD="'${config_ubinstall[user.root_password]}'" #&>/dev/null
    [[ -z ${config_ubinstall[user.user_name]} ]] || ubconfig --target "${pathRootUblinuxData}/ublinux.ini" set [users] DEFAULTUSER=${config_ubinstall[user.user_name]} #&>/dev/null
    [[ -n ${config_ubinstall[user.user_password]} ]] || config_ubinstall[user.user_password]="x"
#    [[ -z ${config_ubinstall[user.user_name]} ]] || ubconfig --target "${pathRootUblinuxData}/ublinux.ini" set [users] NEEDEDUSERS="'${config_ubinstall[user.user_name]}:1000:${config_ubinstall[user.user_password]}:${config_ubinstall[user.full_name]:1:-1}'" #&>/dev/null
    [[ -z ${config_ubinstall[user.user_name]} ]] || ubconfig --target "${pathRootUblinuxData}/ublinux.ini" set [users] USERADD[${config_ubinstall[user.user_name]}]="'${config_ubinstall[user.full_name]:1:-1}:1000:x:x:x:${config_ubinstall[user.user_password]}'" #&>/dev/null
    [[ -z ${config_ubinstall[network.hostname]} ]] || ubconfig --target "${pathRootUblinuxData}/ublinux.ini" set [system] HOSTNAME=${config_ubinstall[network.hostname]} #&>/dev/null
    [[ -z ${config_ubinstall[language.zone]} ]] || ubconfig --target "${pathRootUblinuxData}/ublinux.ini" set [clock] ZONE=${config_ubinstall[language.zone]} #&>/dev/null
    #[[ ${config_ubinstall[language.lang]} == "Russia" ]] && ubconfig --target "${pathRootUblinuxData}/ublinux.ini" set [locale] LANG="ru_RU.UTF-8" LOCALE="en_US.UTF-8,ru_RU.UTF-8" #&>/dev/null
    [[ ${config_ubinstall[language.lang]} == "English" ]] && ubconfig --target "${pathRootUblinuxData}/ublinux.ini" set [locale] LANG="en_US.UTF-8" LOCALE="en_US.UTF-8" #&>/dev/null
    #[[ -z ${config_ubinstall[language.keymap]} ]] || ubconfig --target "${pathRootUblinuxData}/ublinux.ini" set [keyboard] KEYTABLE=${config_ubinstall[language.keymap]} #&>/dev/null
}

check_part_after_install(){
    local path="$1"
    while read -r line; do
        if [ -n "$line" ]; then
            echo "$(i18n "Checking %s for errors" "$line")" 1>&3
            e2fsck -vfy "$line"
        fi
    done < <(lsblk "/dev/$path" -o path,fstype | grep -E 'ext[234]' | awk '{print $1}')
}

setup_in_part(){
    declare -a KNAME_ARR
    declare -a MNT_KNAME
    local part_name=${config_ubinstall["autoinstall.device"]}
    local part_numb=$(echo -n "${part_name}" | tail -c 1)
    local curr_device=${part_name::-1}
    local mount_dest="/mnt"
    local sys_root_kname=""
    local astra=""
    local rosa=""
    local alt=""
    local redos=""

    drive_umount_allparts ${curr_device}

    while read -r line
    do
        KNAME_ARR+=("${line}")
    done < <(lsblk -o kname,type,parttypename,mountpoint "/dev/${curr_device}" | awk '{if ($2 == "part" && $3 != "Extended" && $4 != "swap" && ($4 == "" || $5 == "")) print $1;}')

    echo -e "################################################################" 1>&3
    echo -e "#### $(i18n "STARTING INSTALLATIONS IN EXISTING PART %s" "$(date)") ####" 1>&3
    if [ -b /dev/${part_name} ];then
        echo -e "0.01|$(i18n "Start installation")" >&5
        copy_grub_cfg_for_exist_part
        echo -e "0.22|$(i18n "Copying file system")" >&5
        copy_os_for_exist_part ${mount_dest}/${part_name} ${mount_dest}/${sys_root_kname} || return 1
        echo -e "0.90|$(i18n "Finishing install")" >&5
        post_install ${mount_dest}/${part_name}
        echo -e "0.99|$(i18n "Finishing install")" >&5
        drive_umount_allparts ${curr_device} 1
        echo -e "0.99|$(i18n "Checking the disk for errors")" >&5
        check_part_after_install ${curr_device}
        echo -e "1.00|$(i18n "Installation is complete!")" >&5
        echo -e "################################################################" 1>&3 
        echo -e "#### $(i18n "CONGRATULATIONS! EVERYTHING IS FINE!") ####" 1>&3 
        echo -e "#### $(i18n "INSTALLATION IN EXISTING PART IS COMPLETE!") ####" 1>&3
    else
        echo -e "#### $(i18n "Device %s is not block!" "/dev/${part_name}") ####" 1>&3 && return 1
    fi
}

copy_grub_cfg_for_exist_part(){
    echo -e "## $(i18n "Copy grub.cfg from insall OS") ##" 1>&3
    echo -e "0.10|$(i18n "Settings")" >&5
    for i in ${!KNAME_ARR[@]}
    do
        [[ -n ${arg_real} ]] && mkdir -p "${mount_dest}/${KNAME_ARR[i]}" 
        [[ -n ${arg_real} ]] && mount "/dev/${KNAME_ARR[i]}" "${mount_dest}/${KNAME_ARR[i]}" 2>/dev/null
        tmp="${mount_dest}/${KNAME_ARR[i]}/boot/grub/grub.cfg"
        if [ -f ${tmp} ]
        then
            sleep 0.5
            sys_root_kname=$(echo ${KNAME_ARR[i]} | awk '{print $1}')
            if [ -z $1 ]; then
                astra=$(cat ${tmp} | grep -a 'astra')
                rosa=$(cat ${tmp} | grep -a 'rosa')
                alt=$(cat ${tmp} | grep -a 'alt')
                redos=$(cat ${tmp} | grep -a 'redos')
                [[ -n ${arg_real} ]] && [[ -n "${astra}" ]] && mkdir -p "${mount_dest}/${KNAME_ARR[i]}/boot/grub/astra" && \
                    cp "${mount_dest}/${KNAME_ARR[i]}/boot/grub/grub.cfg" "${mount_dest}/${KNAME_ARR[i]}/boot/grub/astra/grub.cfg"

                [[ -n ${arg_real} ]] && [[ -n "${rosa}" ]] && mkdir -p "${mount_dest}/${KNAME_ARR[i]}/boot/grub/rosa" && \
                    cp "${mount_dest}/${KNAME_ARR[i]}/boot/grub/grub.cfg" "${mount_dest}/${KNAME_ARR[i]}/boot/grub/rosa/grub.cfg"
                
                [[ -n ${arg_real} ]] && [[ -n "${alt}" ]] && mkdir -p "${mount_dest}/${KNAME_ARR[i]}/boot/grub/alt" && \
                    cp "${mount_dest}/${KNAME_ARR[i]}/boot/grub/grub.cfg" "${mount_dest}/${KNAME_ARR[i]}/boot/grub/alt/grub.cfg"
                
                [[ -n ${arg_real} ]] && [[ -n "${redos}" ]] && mkdir -p "${mount_dest}/${KNAME_ARR[i]}/boot/grub/redos" && \
                    cp "${mount_dest}/${KNAME_ARR[i]}/boot/grub/grub.cfg" "${mount_dest}/${KNAME_ARR[i]}/boot/grub/redos/grub.cfg"
                
                [[ -n ${arg_real} ]] && [[ -z "${astra}" ]] && [[ -z "${rosa}" ]] && [[ -z "${alt}" ]] && [[ -z "${redos}" ]] && \
                    mkdir -p "${mount_dest}/${KNAME_ARR[i]}/boot/grub/other" && \
                    cp "${mount_dest}/${KNAME_ARR[i]}/boot/grub/grub.cfg" "${mount_dest}/${KNAME_ARR[i]}/boot/grub/other/grub.cfg"
            fi
        fi
    done
}

copy_os_for_exist_part(){
    local root_path="/memory/data/from/0"
    local ublinux_root="$root_path/ublinux"

    if [ -z $3 ];then
        echo "## $(i18n "Copy UBLINUX to file systems") ##" 1>&3
        echo -e "0.22|$(i18n "Copying file system")" >&5
        [ -n ${arg_real} ] && rsync -av --info=progress2 --stats "$ublinux_root" "$1/" | \
                            stdbuf -oL tr '\r' '\n' | \
                            awk -v desc="$(i18n "Copying file system")" -v fPath="$root_path/" '/^ / { print "0.22|"desc"|"$1"|"$2 ; fflush() ;  next } $0 { print "# " fPath$0  }' >&5
        echo -e "0.87|$(i18n "Copying file system")" >&5
        [[ -n ${arg_real} ]] && { tar xJf "$ublinux_root/ublinux-data.tar.xz" -C $1/ || return 1; }
	echo "## $(i18n "Copy BOOT configurations") ##" 1>&3
	echo -e "0.87|$(i18n "Copying grub")" >&5
	[[ -n ${arg_real} ]] && { tar xJf "$ublinux_root/boot.tar.xz" -C $2/ boot/grub/ublinux || return 1; }
        echo -e "0.90|$(i18n "Updating skeleton /boot/grub/ublinux /ublinux/ /ublinux-data/")" >&5
	[[ -n ${arg_real} ]] && /usr/lib/ubboot/ubboot-skel update -udgts --path-media $1
    fi
    echo -e "0.89|$(i18n "Create files")" >&5
    [[ -n ${arg_real} ]] && { ubconfig --target "$1/ublinux-data/ublinux.ini" set [system] FIRSTSTART=yes || return 1; }
    #sync; 
    echo 3 > /proc/sys/vm/drop_caches
    sleep 1
}

setup_near_other_os(){
    declare -a OLD_KNAME_ARR
    local efi_part_numb
    local find_win=0
    local find_lin=0
    local part_name=${config_ubinstall["autoinstall.device"]}
    local part_numb=$(echo -n "${part_name}" | tail -c 1)
    local curr_device=${part_name::-1}
    local part_type_name=$(lsblk -o kname,parttypename /dev/${curr_device} | grep "${part_name}" | awk '{print $2;}')
    local disk_label=${config_ubinstall["autoinstall.label"]}
    local first_sec=$(fdisk -l "/dev/${curr_device}" | grep "/dev/${part_name}" | awk '{print $2;}')
    [[ "${first_sec}" == "*" ]] && first_sec=$(fdisk -l "/dev/${curr_device}" | grep "/dev/${part_name}" | awk '{print $3;}') && \
        local last_sec=$(fdisk -l "/dev/${curr_device}" | grep "/dev/${part_name}" | awk '{print $4;}') || \
        local last_sec=$(fdisk -l "/dev/${curr_device}" | grep "/dev/${part_name}" | awk '{print $3;}')
    local empty_part_numb=""
    local new_bios_part_numb=""
    local new_efi_part_numb=""

    [[ "${part_type_name}" == *"Linux"* ]] && find_lin=1
    [[ "${part_type_name}" == *"HPFS/NTFS/exFAT"* ]] && find_win=1

    echo -e "0.01|$(i18n "Start installation")" >&5

    while read -r line
    do
        OLD_KNAME_ARR+=("${line}")
    done < <(lsblk -o KNAME,TYPE "/dev/${curr_device}" | awk '{if ($2 == "part") print $1;}')

    echo -e "0.02|$(i18n "Start installation")" >&5

    for i in ${!OLD_KNAME_ARR[@]}
    do
        local tmp_info_disk=$(fdisk -l /dev/${curr_device} | grep ${OLD_KNAME_ARR[i]})
        [[ "${tmp_info_disk}" == *"*"*"FAT"* ]] && efi_part_numb=$(echo -n "${OLD_KNAME_ARR[i]}" | tail -c 1)
    done

    echo -e "0.03|$(i18n "Start installation")" >&5

    [[ "${find_lin}" == 1 ]] && [[ "${find_win}" == 0 ]] && [[ -z "${config_ubinstall["autoinstall.size"]}" ]] && local free_blocks=$(($(tune2fs -l "/dev/${part_name}" | grep '^Free blocks' | awk '{print $3}')*8))
    [[ "${find_win}" == 1 ]] && [[ "${find_lin}" == 0 ]] && [[ -z "${config_ubinstall["autoinstall.size"]}" ]] && local free_blocks=$((${last_sec}-$(ntfsresize --info "/dev/${part_name}" | grep '^Space in use' | awk '{print $5}')*2048))
    ([[ "${find_lin}" == 1 ]] || [[ "${find_win}" == 1 ]]) && [[ -n "${config_ubinstall["autoinstall.size"]}" ]] && local free_blocks=$((${config_ubinstall["autoinstall.size"]}*2097152))

    echo -e "0.04|$(i18n "Start installation")" >&5

    [[ -z "${config_ubinstall["autoinstall.size"]}" ]] && local half_blocks_size=$(echo "scale=1; ${free_blocks}/2" | bc | sed 's/\.[0-9]*//')
    [[ -z "${config_ubinstall["autoinstall.size"]}" ]] && local first_part_value=${half_blocks_size} || local first_part_value=${free_blocks}
    local first_part_done=$((${first_sec}+${first_part_value}-1))
    local last_part_start=$((${first_part_done}+1))
    local second_part_value=$((${last_sec}-${last_part_start}))

    if [ ${find_lin} == 1 ]; then
        echo -e "################################################################" 1>&3
        echo -e "#### $(i18n "STARTING NEAR INSTALLATIONS %s" "$(date)") ####" 1>&3
        echo -e "0.01|$(i18n "Start installation")" >&5
        drive_umount_allparts ${curr_device} || return 1
        echo -e "0.02|$(i18n "Prepare disk for install")" >&5
        prepare_disk_for_near_install "$((${second_part_value}*512/1024))K" $((${first_part_value}*512)) || return 1
        echo -e "0.04|$(i18n "Partition disk")" >&5
        partition_disk_for_near_install "${part_numb}" "${curr_device}" "${efi_part_numb}" "${disk_label}" "${first_part_done}" "${last_part_start}" || return 1
        echo -e "0.06|$(i18n "Formatting disk")" >&5
        formattig_disk_for_near_install
        echo -e "0.08|$(i18n "Mount parts")" >&5
        mount_drives_for_near_install || return 1
        echo -e "0.15|$(i18n "Install grub")" >&5
        install_grub ${curr_device}
	echo -e "0.17|$(i18n "Install UEFI entry")" >&5
	install_uefi_menu ${curr_device}
        echo -e "0.19|$(i18n "Configure grub")" >&5
        config_grub_for_near_install
        echo -e "0.20|$(i18n "Copying file system")" >&5
        rootcopy ${curr_device} || return 1
        echo -e "0.95|$(i18n "Finishing install")" >&5
        post_install /mnt/${curr_device}/root/ublinux
        echo -e "0.99|$(i18n "Finishing install")" >&5
        drive_umount_allparts ${curr_device} || return 1
        echo -e "0.99|$(i18n "Checking the disk for errors")" >&5
        check_part_after_install ${curr_device}
        echo -e "1.00|$(i18n "Installation is complete!")" >&5
        echo -e "################################################################" 1>&3
        echo -e "#### $(i18n "CONGRATULATIONS! EVERYTHING IS FINE!") ####" 1>&3
        echo -e "#### $(i18n "NEAR INSTALLATION IS COMPLETE!") ####" 1>&3
    elif [ ${find_win} == 1 ]; then
        echo "$(i18n "Not working with Windows!")" 1>&3 && return 1
    fi

}

prepare_disk_for_near_install(){
    echo "$(i18n "Check part %s on errors and fix" "/dev/${part_name}")" 1>&3
    echo -e "0.02|$(i18n "Prepare disk for install: check part")" >&5
    [[ -n ${arg_real} ]] && e2fsck -f -y -v -C 0 "/dev/${part_name}"
    
    echo "$(i18n "Resizing part %s" "/dev/${part_name}")" 1>&3
    echo -e "0.03|$(i18n "Prepare disk for install: resize part")" >&5
    [[ -n ${arg_real} ]] && (resize2fs -p "/dev/${part_name}" $1 || return 2); [[ $? -eq 2 ]] && return 1

    echo "$(i18n "Move data from right")" 1>&3
    echo -e "0.04|$(i18n "Prepare disk for install: move data in end")" >&5
    [[ -n ${arg_real} ]] && e2image -ra -p -O $2 "/dev/${part_name}"
}

partition_disk_for_near_install(){
    declare -a NEW_KNAME_ARR
    declare -a KNAME_ARR
    local temp=""
    local part_numb="$1"
    local curr_device="$2"
    local efi_part_numb="$3"
    local disk_label="$4"
    local first_part_done="$5"
    local last_part_start="$6"

    echo "$(i18n "Partition disk")" 1>&3
    echo -e "0.05|$(i18n "Partition disk")" >&5
    [[ -n ${arg_real} ]] && (sgdisk -g -d ${part_numb} /dev/${curr_device} || return 2); [[ $? -eq 2 ]] && return 1
    [[ -n ${arg_real} ]] && (sgdisk -g -a=1 -n 0:${last_part_start}:0 /dev/${curr_device} || return 2); [[ $? -eq 2 ]] && return 1

    echo "$(i18n "Create partition \"%s\" on drive: %s" "bios_boot" "/dev/${curr_device}")" 1>&3
    echo -e "0.05|$(i18n "Partition disk")" >&5
    [[ -n ${arg_real} ]] && (sgdisk -g -a=2048 -n 0:0:+1M -c 0:"bios_boot" -t 0:ef02 /dev/${curr_device} || return 2); [[ $? -eq 2 ]] && return 1
    [[ -z ${efi_part_numb} ]] && echo "$(i18n "Create partition \"%s\" on drive: %s" "efi" "/dev/${curr_device}")" 1>&3
    echo -e "0.05|$(i18n "Partition disk")" >&5
    [[ -z ${efi_part_numb} ]] && [[ -n ${arg_real} ]] && (sgdisk -g -a=2048 -n 0:0:+2M -c 0:"efi" -t 0:ef00 /dev/${curr_device} || return 2); [[ $? -eq 2 ]] && return 1
    echo "$(i18n "Create partition \"%s\" on drive: %s" ${disk_label} "/dev/${curr_device}")" 1>&3
    echo -e "0.05|$(i18n "Partition disk")" >&5
    [[ -n ${arg_real} ]] && (sgdisk -g -a=2048 -n 0:0:${first_part_done} -c 0:${disk_label} -t 0:8300 /dev/${curr_device} || return 2); [[ $? -eq 2 ]] && return 1

    while read -r line
    do
        NEW_KNAME_ARR+=("${line}")
    done < <(lsblk -o KNAME,TYPE "/dev/${curr_device}" | awk '{if ($2 == "part") print $1;}')

    for i in ${!NEW_KNAME_ARR[@]}; do
        for j in ${!OLD_KNAME_ARR[@]}; do
            [[ "${NEW_KNAME_ARR[i]}" == "${OLD_KNAME_ARR[j]}" ]] && temp="" && break || temp=${NEW_KNAME_ARR[i]}
        done
        [[ -n ${temp} ]] && KNAME_ARR+=(${temp})
    done

    echo -e "0.22|$(i18n "Partition disk")" >&5
    empty_part_numb=$(echo -n "${KNAME_ARR[${#KNAME_ARR[@]}-1]}" | tail -c 1)
    [[ -z ${efi_part_numb} ]] && new_efi_part_numb=$((${empty_part_numb}-1)) && new_bios_part_numb=$((${empty_part_numb}-2)) || \
        new_bios_part_numb=$(echo -n "${KNAME_ARR[${#KNAME_ARR[@]}-2]}" | tail -c 1)

    if [ -z ${efi_part_numb} ]; then
        echo "$(i18n "Create hybrid MBR \"%s\" on drive: %s" "${new_efi_part_numb}:${empty_part_numb}" "/dev/${curr_device}")" 1>&3
        echo -e "0.23|$(i18n "Partition disk")" >&5
        [[ -n ${arg_real} ]] && (sgdisk -g -h ${new_efi_part_numb}:${empty_part_numb} /dev/${curr_device} || return 2); [[ $? -eq 2 ]] && return 1
        echo "$(i18n "Set boot atribute partition \"%s\" on drive: %s" "${new_bios_part_numb}" "/dev/${curr_device}")" 1>&3
        echo -e "0.24|$(i18n "Partition disk")" >&5
        [[ -n ${arg_real} ]] && (sgdisk -g -A ${new_bios_part_numb}:set:${new_efi_part_numb} /dev/${curr_device} || return 2); [[ $? -eq 2 ]] && return 1
    else
        echo "$(i18n "Create hybrid MBR \"%s\" on drive: %s" "${efi_part_numb}:${empty_part_numb}" "/dev/${curr_device}")" 1>&3
        echo -e "0.25|$(i18n "Partition disk")" >&5
        [[ -n ${arg_real} ]] && (sgdisk -g -h ${efi_part_numb}:${empty_part_numb} /dev/${curr_device} || return 2); [[ $? -eq 2 ]] && return 1
        echo "$(i18n "Set boot atribute partition \"%s\" on drive: %s" "${new_bios_part_numb}" "/dev/${curr_device}")" 1>&3
        echo -e "0.26|$(i18n "Partition disk")" >&5
        [[ -n ${arg_real} ]] && (sgdisk -g -A ${new_bios_part_numb}:set:${efi_part_numb} /dev/${curr_device} || return 2); [[ $? -eq 2 ]] && return 1
    fi
    
    partprobe /dev/$1
    sync; sleep 1
    echo 3 > /proc/sys/vm/drop_caches
    sleep 1
}

formattig_disk_for_near_install(){
    if [ -z ${efi_part_numb} ]; then
        echo "$(i18n "Make fat32 on partition \"%s\": %s" "efi" "/dev/${curr_device}${new_efi_part_numb}")" 1>&3
        echo -e "0.06|$(i18n "Formatting disk")" >&5
        [[ -n ${arg_real} ]] && mkfs.fat -F32 -n EFI /dev/${curr_device}${new_efi_part_numb}
    fi
    echo "$(i18n "Make ext4 on partition \"%s\": %s" ${disk_label} "/dev/${curr_device}${empty_part_numb}")" 1>&3
    echo -e "0.07|$(i18n "Formatting disk")" >&5
    [[ -n ${arg_real} ]] && mkfs.ext4 -F -L ${disk_label} /dev/${curr_device}${empty_part_numb}
    sync; sleep 1
    echo 3 > /proc/sys/vm/drop_caches
    sleep 1
}

mount_drives_for_near_install(){
    echo "$(i18n "Restoring the partition size: %s" "/dev/${part_name}")" 1>&3
    echo -e "0.09|$(i18n "Mount parts")" >&5
    resize2fs -p /dev/${part_name}
    echo "$(i18n "Restoring the partition size: %s" "/dev/${curr_device}${empty_part_numb}")" 1>&3
    echo -e "0.11|$(i18n "Mount parts")" >&5
    resize2fs -p /dev/${curr_device}${empty_part_numb}
    echo "$(i18n "Check part %s on errors and fix" "/dev/${part_name}")" 1>&3
    echo -e "0.13|$(i18n "Mount parts")" >&5
    e2fsck -fy /dev/${part_name}
    echo "$(i18n "Check part %s on errors and fix" "/dev/${curr_device}${empty_part_numb}")" 1>&3
    echo -e "0.14|$(i18n "Mount parts")" >&5
    e2fsck -fy /dev/${curr_device}${empty_part_numb}
    echo "$(i18n "Make dirrectory: %s" "/mnt/${curr_device}/efi")" 1>&3
    echo -e "0.15|$(i18n "Mount parts")" >&5
    [[ -n ${arg_real} ]] && mkdir -p /mnt/${curr_device}/efi
    echo "$(i18n "Make dirrectory: %s" "/mnt/${curr_device}/root")" 1>&3
    echo -e "0.15|$(i18n "Mount parts")" >&5
    [[ -n ${arg_real} ]] && mkdir -p /mnt/${curr_device}/root
    if [ -z ${efi_part_numb} ]; then
        echo "$(i18n "Mount dirrectory device: %s to path: %s" "/dev/${curr_device}${new_efi_part_numb}" "/mnt/$1/efi")" 1>&3
        echo -e "0.15|$(i18n "Mount parts")" >&5
        [[ -n ${arg_real} ]] && (mount /dev/${curr_device}${new_efi_part_numb} /mnt/${curr_device}/efi || return 2); [[ $? -eq 2 ]] && return 1
    else
        echo "$(i18n "Mount dirrectory device: %s to path: %s" "/dev/${curr_device}${efi_part_numb}" "/mnt/$1/efi")" 1>&3
        echo -e "0.15|$(i18n "Mount parts")" >&5
        [[ -n ${arg_real} ]] && (mount /dev/${curr_device}${efi_part_numb} /mnt/${curr_device}/efi || return 2); [[ $? -eq 2 ]] && return 1
    fi
    echo "$(i18n "Mount dirrectory device: %s to path: %s" "/dev/${curr_device}${empty_part_numb}" "/mnt/${curr_device}/root")" 1>&3
    echo -e "0.15|$(i18n "Mount parts")" >&5
    [[ -n ${arg_real} ]] && (mount /dev/${curr_device}${empty_part_numb} /mnt/${curr_device}/root || return 2); [[ $? -eq 2 ]] && return 1
}

config_grub_for_near_install(){
    echo "$(i18n "Make dirrectory: %s" "/mnt/${curr_device}/root/boot/grub/other")" 1>&3
    echo -e "0.19|$(i18n "Configure grub")" >&5
    [[ -n ${arg_real} ]] && mkdir -p /mnt/${curr_device}/root/boot/grub/other
    echo "$(i18n "Make dirrectory: %s" "/mnt/other")" 1>&3
    echo -e "0.19|$(i18n "Configure grub")" >&5
    [[ -n ${arg_real} ]] && mkdir -p /mnt/other
    echo "$(i18n "Mount dirrectory device: %s to path: %s" "/dev/${part_name}" "/mnt/other")" 1>&3
    echo -e "0.19|$(i18n "Configure grub")" >&5
    [[ -n ${arg_real} ]] && mount /dev/${part_name} /mnt/other
    echo "$(i18n "Copy grub.cfg from %s to %s" "/mnt/other/boot/grub" "/mnt/${curr_device}/root/boot/grub/other")" 1>&3
    echo -e "0.19|$(i18n "Configure grub")" >&5
    [[ -n ${arg_real} ]] && cp /mnt/other/boot/grub/grub.cfg /mnt/${curr_device}/root/boot/grub/other/grub.cfg 
    echo "$(i18n "Umount dirrectory: %s" "/mnt/other")" 1>&3
    echo -e "0.19|$(i18n "Configure grub")" >&5
    [[ -n ${arg_real} ]] && umount -l /mnt/other
    echo "$(i18n "Umount partition: %s" "/dev/${part_name}")" 1>&3
    echo -e "0.19|$(i18n "Configure grub")" >&5
    [[ -n ${arg_real} ]] && umount -l /dev/${part_name}
    echo "$(i18n "Delete dirrectory: %s" "/mnt/other")" 1>&3
    echo -e "0.19|$(i18n "Configure grub")" >&5
    [[ -n ${arg_real} ]] && rm -r /mnt/other
}

grub_update(){
    declare -a KNAME_ARR
    local mount_dest="/mnt"
    local curr_device="${config_ubinstall["bootloader.boot_partition"]}"
    local sys_root_kname=""

    drive_umount_allparts ${curr_device}

    while read -r line; do
        KNAME_ARR+=("${line}")
    done < <(lsblk -o kname,type,parttypename,mountpoint "/dev/${curr_device}" | awk '{if ($2 == "part" && $3 != "Extended" && ($4 == "" || $5 == "")) print $1;}')
    echo -e "################################################################" 1>&3
    echo -e "#### $(i18n "STARTING UPDATE GRUB CONFIGURATION %s" "$(date)") ####" 1>&3
    swapoff -a
    echo -e "0.05|$(i18n "Configure grub")" >&5
    copy_grub_cfg_for_exist_part
    # copy_boot_config || return 1
    echo -e "0.19|$(i18n "Copying file system")" >&5
    copy_os_for_exist_part ${mount_dest}/${curr_device} ${mount_dest}/${sys_root_kname} 1 || return 1
    echo -e "0.90|$(i18n "Finishing install")" >&5
    drive_umount_allparts ${curr_device}
    echo -e "1.00|$(i18n "Installation is complete!")" >&5
    echo -e "################################################################" 1>&3
    echo -e "#### $(i18n "CONGRATULATIONS! EVERYTHING IS FINE!") ####" 1>&3
    echo -e "#### $(i18n "UPDATE GRUB CONFIGURATION IS COMPLETE!") ####" 1>&3
}

grub_install_main(){
    declare -a KNAME_ARR
    local mount_dest="/mnt"
    local curr_device=${config_ubinstall["bootloader.boot_partition"]}
    local sys_root_kname=""

    drive_umount_allparts ${curr_device}

    while read -r line
    do
        KNAME_ARR+=("${line}")
    done < <(lsblk -o kname,type,parttypename,mountpoint "/dev/${curr_device}" | awk '{if ($2 == "part" && $3 != "Extended" && ($4 == "" || $5 == "")) print $1;}')

    echo -e "################################################################" 1>&3
    echo -e "#### $(i18n "STARTING INSTALLATION GRUB  %s" "$(date)") ####" 1>&3
    swapoff -a
    # mount_all_parts
    echo -e "0.05|$(i18n "Configure grub")" >&5
    copy_grub_cfg_for_exist_part 1
    echo -e "0.15|$(i18n "Install grub")" >&5
    install_grub ${sys_root_kname} 1
    echo -e "0.17|$(i18n "Install UEFI entry")" >&5
    install_uefi_menu ${sys_root_kname}
    echo -e "0.90|$(i18n "Finishing install")" >&5
    # grub_install
    drive_umount_allparts ${curr_device}
    echo -e "1.00|$(i18n "Installation is complete!")" >&5
    echo -e "################################################################" 1>&3
    echo -e "#### $(i18n "CONGRATULATIONS! EVERYTHING IS FINE!") ####" 1>&3
    echo -e "#### $(i18n "INSTALLATION GRUB IS COMPLETE!") ####" 1>&3
}

install_hibrid_os_user(){
    echo -e "################################################################" 1>&3
    echo -e "#### $(i18n "STARTING HYBRID INSTALLATION  %s" "$(date)") ####" 1>&3
    echo -e "0.01|$(i18n "Start installation")" >&5
    swapoff -a
    #
    #
    #
    echo -e "1.00|$(i18n "Installation is complete!")" >&5
    echo -e "################################################################" 1>&3
    echo -e "#### $(i18n "CONGRATULATIONS! EVERYTHING IS FINE!") ####" 1>&3
    echo -e "#### $(i18n "HYBRID INSTALLATION IS COMPLETE!") ####" 1>&3
}

install_user_only(){
    echo -e "################################################################" 1>&3
    echo -e "#### $(i18n "STARTING USER ONLY INSTALLATION  %s" "$(date)") ####" 1>&3
    echo -e "0.01|$(i18n "Start installation")" >&5
    swapoff -a
    rootcopy_folder_only "ublinux-data"
    echo -e "1.00|$(i18n "Installation is complete!")" >&5
    echo -e "################################################################" 1>&3
    echo -e "#### $(i18n "CONGRATULATIONS! EVERYTHING IS FINE!") ####" 1>&3
    echo -e "#### $(i18n "USER ONLY INSTALLATION IS COMPLETE!") ####" 1>&3
}

install_os_only(){
    echo -e "################################################################" 1>&3
    echo -e "#### $(i18n "STARTING OS ONLY INSTALLATION  %s" "$(date)") ####" 1>&3
    echo -e "0.01|$(i18n "Start installation")" >&5
    swapoff -a
    rootcopy_folder_only "ublinux"
    echo -e "1.00|$(i18n "Installation is complete!")" >&5
    echo -e "################################################################" 1>&3
    echo -e "#### $(i18n "CONGRATULATIONS! EVERYTHING IS FINE!") ####" 1>&3
    echo -e "#### $(i18n "OS ONLY INSTALLATION IS COMPLETE!") ####" 1>&3
}

rootcopy_folder_only(){
    local root_path="/memory/data/from/0"
    local folder_name="$1"
    local folder_path="$root_path/$folder_name"

    local curr_part=${config_ubinstall["autoinstall.device"]}
    local curr_device=${curr_part::-1}
    local disk_label=${config_ubinstall["autoinstall.label"]}
    local format=${config_ubinstall["miscellaneous.formatting_part"]}

    if [[ "$format" == "true" ]]; then
        echo -e "0.08|$(i18n "Formatting disk")" >&5
        [[ -n ${arg_real} ]] && umount /dev/${curr_part}
        echo "$(i18n "Make ext4 on partition \"%s\": %s" ${disk_label} "/dev/${curr_part}")" 1>&3
        [[ -n ${arg_real} ]] && mkfs -t ext4 /dev/${curr_part}
    fi

    echo -e "0.14|$(i18n "Mount parts")" >&5
    [[ -n ${arg_real} ]] && mkdir /mnt/"$curr_part"
    [[ -n ${arg_real} ]] && mount /dev/$curr_part /mnt/"$curr_part"

    ([[ "$format" == "false" ]] || [[ -d "/mnt/"$curr_part"/$folder_name" ]]) && rm -rf "/mnt/$curr_part/$folder_name/"

    echo "## $(i18n "Copy UBLINUX to file systems") ##" 1>&3
    echo -e "0.22|$(i18n "Copying file system")" >&5
    [[ -n ${arg_real} ]] && rsync -av --info=progress2 --stats "$folder_path" "/mnt/"$curr_part"" | \
                        stdbuf -oL tr '\r' '\n' | \
                        tee >(awk -v desc="$(i18n "Copying file system")" -v fPath="$root_path/" '/^ / { print "0.22|"desc"|"$1"|"$2 ; fflush() ;  next } $0 { print "# " fPath$0  }' >&5) | \
                        awk -v fPath="$root_path/" '/\// && !/,/ { print fPath$0 ; fflush() ; next }' 1>&3
    
    echo -e "0.90|$(i18n "Updating skeleton /boot/grub/ublinux /ublinux/ /ublinux-data/")" >&5
    [[ -n ${arg_real} ]] && /usr/lib/ubboot/ubboot-skel update -udgts --path-media ${path_copy_dst}
#    echo -e "0.90|$(i18n "Copying file system")" >&5
#    generate_signature "/mnt/"$curr_part""

    echo -e "0.95|$(i18n "Finishing install")" >&5
    drive_umount_allparts ${curr_device}
}



##############
  #### MAIN #### 
    ##############
[[ -z $1 ]] && set - "--help"
while [[ -n $1 ]]; do
    case $1 in
        -a | --a) 
            echo "Found the $1 option = $2"
            shift
        ;;
        -gpc | --get_path_conf)
            arg_get_path_conf="-gpc"
        ;;
        -glb | --get_list_block)
            arg_get_list_block="-glb"
        ;;
        -h | --help)
            arg_help="-h"
        ;;
        -lib=* | --lib=*)
            arg_libpath="${1#*=}"
        ;;
        -r | --real)
            arg_real="-r"
        ;;
        -g | --gen-config)
            arg_config="-conf"
        ;;
        -c=* | --config=*)
            arg_config_path="${1#*=}"
        ;; 
        *)
            exit 1
        ;;
    esac
    shift # Удалить один аргумент
done

_init_

[[ ! -f ${log_file} ]] && config_ubinstall["miscellaneous.enable_log"]="false"

[[ "${config_ubinstall["miscellaneous.enable_log"]}" == "true" ]] && [[ "${config_ubinstall["miscellaneous.enable_debug"]}" == "true" ]] && exec 4>&1 1>>${log_file} 2>&1 3>&1 5>${progressbar_file}    # -l -d	Логируем STDOUT>,STDERR>,3> в лог файл, 4> в консоль
[[ "${config_ubinstall["miscellaneous.enable_log"]}" == "true" ]] && [[ "${config_ubinstall["miscellaneous.enable_debug"]}" == "false" ]] && exec 4>&1 1>/dev/null 2>>${log_file} 3>&2 5>${progressbar_file}	# -l 	Логируем STDERR>,3> в лог файл, 4> в консоль, не выводить STDOUT>
[[ "${config_ubinstall["miscellaneous.enable_log"]}" == "false" ]] && [[ "${config_ubinstall["miscellaneous.enable_debug"]}" == "true" ]] && exec 4>&1 3>&1 5>${progressbar_file}    # -d	Работать с консоль обычно, без логирования 4>,3>,5> в &1 консоли
[[ "${config_ubinstall["miscellaneous.enable_log"]}" == "false" ]] && [[ "${config_ubinstall["miscellaneous.enable_debug"]}" == "false" ]] && exec 4>&1 3>&1 1>/dev/null 2>&1 5>${progressbar_file}   # Нет опций, логируем 3>,4> в &1 консоли, не выводить STDOUT>,STDERR>,5>

### EXCUTE
[[ -n ${arg_help} ]] && echo "$(i18n "${msg_version}" "${version}")" >&4 && echo "$(i18n "${msg_usage}" "$(basename $0)")" >&4 && exit 0
[[ -n "${arg_config}" ]] && create_empty_config && exit 0
[[ -n "$arg_config_path" ]] && ( read_custom_config "$arg_config_path" || echo -e "$(i18n "The configuration file cannot be read %s:" "$arg_config_path")" >&4d && exit 1 )
[[ -n ${arg_get_path_conf} ]] && ( echo "${config_file_current}" >&4 && exit 0 )
[[ -n ${arg_get_list_block} ]] && while read -r line; do echo -e "$line" >&4; done < <( lsblk -rbo maj:min,name,path,type,parttypename,fstype,label,size,fsavail,fsuse%,mountpoint,tran,vendor,model,ro | sed 's/:/\ /' | sort -nk1 -nk2 | sed 's/\ /|/'| awk '{if ($4 == "disk" || $4 == "part") print $0;}' | sed 's/\ /:/g;s/::/:-:/g;s/::/:-:/g;s/:$/:-/' ) && exit 0
[[ "${config_ubinstall["miscellaneous.type_of_install"]}" == "install-fast" ]] && ( check_root "${config_ubinstall["miscellaneous.type_of_install"]}" && _install_fast_ || (echo -e "#### $(i18n "SOMETHING WENT WRONG!") ####\n#### $(i18n "INSTALLATION IS NOT COMPLETE!") ####\n\n" 1>&3 && exit 1))
[[ "${config_ubinstall["miscellaneous.type_of_install"]}" == "near" ]] && ( check_root "${config_ubinstall["miscellaneous.type_of_install"]}" && setup_near_other_os || (echo -e "#### $(i18n "SOMETHING WENT WRONG!") ####\n#### $(i18n "INSTALLATION IS NOT COMPLETE!") ####\n\n" 1>&3 && exit 1))
[[ "${config_ubinstall["miscellaneous.type_of_install"]}" == "part" ]] && ( check_root "${config_ubinstall["miscellaneous.type_of_install"]}" && setup_in_part || (echo -e "#### $(i18n "SOMETHING WENT WRONG!") ####\n#### $(i18n "INSTALLATION IS NOT COMPLETE!") ####\n\n" 1>&3 && exit 1))
[[ "${config_ubinstall["miscellaneous.type_of_install"]}" == "grub-upd" ]] && ( check_root "${config_ubinstall["miscellaneous.type_of_install"]}" && grub_update || (echo -e "#### $(i18n "SOMETHING WENT WRONG!") ####\n#### $(i18n "UPDATE GRUB CONFIGURATION IS NOT COMPLETE!") ####\n\n" 1>&3 && exit 1))
[[ "${config_ubinstall["miscellaneous.type_of_install"]}" == "grub-install" ]] && ( check_root "${config_ubinstall["miscellaneous.type_of_install"]}" && grub_install_main || (echo -e "#### $(i18n "SOMETHING WENT WRONG!") ####\n#### $(i18n "INSTALL GRUB IS NOT COMPLETE!") ####\n\n" 1>&3 && exit 1))
[[ "${config_ubinstall["miscellaneous.type_of_install"]}" == "os-only" ]] && ( check_root "${config_ubinstall["miscellaneous.type_of_install"]}" && install_os_only || (echo -e "#### $(i18n "SOMETHING WENT WRONG!") ####\n#### $(i18n "INSTALLATION IS NOT COMPLETE!") ####\n\n" 1>&3 && exit 1))
[[ "${config_ubinstall["miscellaneous.type_of_install"]}" == "user-only" ]] && ( check_root "${config_ubinstall["miscellaneous.type_of_install"]}" && install_user_only || (echo -e "#### $(i18n "SOMETHING WENT WRONG!") ####\n#### $(i18n "INSTALLATION IS NOT COMPLETE!") ####\n\n" 1>&3 && exit 1))
[[ "${config_ubinstall["miscellaneous.type_of_install"]}" == "hibrid-os-user" ]] && ( check_root "${config_ubinstall["miscellaneous.type_of_install"]}" && install_hibrid_os_user || (echo -e "#### $(i18n "SOMETHING WENT WRONG!") ####\n#### $(i18n "INSTALLATION IS NOT COMPLETE!") ####\n\n" 1>&3 && exit 1))

exit 0
