#!/usr/bin/bash
#
# Author: Dmitry Razumov <asmeron@ublinux.com>
# Copyright (c) 2021-2025 UBLinux <support@ublinux.com>
#
# SPDX-License-Identifier: AGPL-3.0-or-later
#
# Initial script for Linux UBLinux
# This script are launching before starting init from initrd script
# Current dir allways must be set to root (/)
# All system path must be relative, except initrd dirs

ENABLED=yes
[[ ${ENABLED} == "yes" ]] || { return 0 2>/dev/null && return 0 || exit 0; }
DEBUGMODE=no

PATH=.:/:/usr/bin:/usr/local/bin:/usr/local/sbin

[[ ! -f /init ]] && { ROOTFS= ; CMD_CHROOT= ; } || { [[ -d /sysroot ]] && ROOTFS="/sysroot" || ROOTFS="."; CMD_CHROOT="chroot ${ROOTFS}"; }
SOURCE=${ROOTFS}/usr/lib/ublinux/functions; [[ -f ${SOURCE} ]] && . ${SOURCE} 2>/dev/null
debug_mode "${SSC_ARGV0:-$0}" "$@"
SOURCE=${ROOTFS}/usr/lib/ublinux/default; [[ -f ${SOURCE} ]] && . ${SOURCE} 2>/dev/null

SYSCONF="${ROOTFS}${SYSCONF}"
SOURCE=${SYSCONF}/config; [[ -f ${SOURCE} ]] && . ${SOURCE} 2>/dev/null
SOURCE=${SYSCONF}/locale; [[ -f ${SOURCE} ]] && . ${SOURCE} 2>/dev/null
SOURCE=${SYSCONF}/keyboard; [[ -f ${SOURCE} ]] && . ${SOURCE} 2>/dev/null

shopt -s extglob

# По сокращённому имени, вернуть полное имя, пример 'get_fullname_lang en' : en_US.UTF-8
get_fullname_lang(){
    local LANG_NEW=$1
    [[ -r ${ROOTFS}/usr/share/i18n/SUPPORTED ]] && local SUPPORTED=$(< ${ROOTFS}/usr/share/i18n/SUPPORTED)
    # Из за того, что нет en_EN, а через груб прилетает просто en, то выбираем en_US.UTF-8
    if [[ ${LANG_NEW} == @("en"|"") ]]; then
        echo "en_US.UTF-8"
    elif [[ ${SUPPORTED} =~ ($'\n'|^)"${LANG_NEW} ".*($'\n'|$) ]]; then
        echo "${LANG_NEW}"
    elif [[ ${SUPPORTED} =~ ($'\n'|^)"${LANG_NEW,,}_${LANG_NEW^^}.UTF-8 ".*($'\n'|$) ]]; then
        echo "${LANG_NEW,,}_${LANG_NEW^^}.UTF-8"
    elif [[ ${SUPPORTED} =~ ($'\n'|^)"${LANG_NEW,,}_${LANG_NEW^^} ".*($'\n'|$) ]]; then
        echo "${LANG_NEW,,}_${LANG_NEW^^}"
    elif [[ ${SUPPORTED} =~ ($'\n'|^)"${LANG_NEW}.UTF-8 ".*($'\n'|$) ]]; then
        echo "${LANG_NEW}.UTF-8"
    elif [[ ${SUPPORTED} =~ ($'\n'|^)("${LANG_NEW,,}_"[:A-Z:]+".UTF-8")" ".*($'\n'|$) ]]; then
        echo "${BASH_REMATCH[2]}"
    elif [[ ${SUPPORTED} =~ ($'\n'|^)("${LANG_NEW,,}_"[:A-Z:]+)" ".*($'\n'|$) ]]; then
        echo "${BASH_REMATCH[2]}"
    else
        echo "en_US.UTF-8"
    fi
}

exec_01_set_locale(){
    # Не учитываем нстройку LOCALE из env ядра, при отсутствии в конфигурации
    local LOCALE=
    [[ -f ${SYSCONF}/locale && $(< ${SYSCONF}/locale) =~ (^|$'\n')LOCALE=\"?\'?([^$'\n'\"\']+)\"?\'?($'\n'|$) ]] && LOCALE=${BASH_REMATCH[2]} || LOCALE="en_US.UTF-8"
    local LANG=
    [[ -f ${SYSCONF}/locale && $(< ${SYSCONF}/locale) =~ (^|$'\n')LANG=\"?\'?([^$'\n'\"\']+)\"?\'?($'\n'|$) ]] && LANG=${BASH_REMATCH[2]} || LANG="en_US.UTF-8"
#        LOCALE=${LOCALE:-en_US.UTF-8}

    local LANG_NEW=$(cmdline_value lang)
    # Если работает в initramfs при загрузке и параметр ядра задан, то используем заданный параметр. Иначе из текущего окружения ${LANG}
    #[[ -n ${LANG_NEW} && -n ${ROOTFS} ]] && LANG_NEW="$(get_fullname_lang ${LANG_NEW})" #|| LANG_NEW=$(get_fullname_lang ${LANG})
    #if  [[ ! -f ${SYSCONF}/locale ]] || [[ ! "${LOCALE}" =~ (^|,)${LANG_NEW}(,|$) ]]; then
    #if [[ -n ${ROOTFS} && -n ${LANG_NEW} ]]; then
    if [[ -n ${LANG_NEW} ]]; then
        LANG_NEW="$(get_fullname_lang ${LANG_NEW})"
        [[ ${LANG_NEW} != @("C.UTF-8"|"POSIX"|"C") && ! "${LOCALE}" =~ (^|,)${LANG_NEW}(,|$) ]] && LOCALE="${LOCALE:+${LOCALE},}${LANG_NEW}"
    fi
    LANG="$(get_fullname_lang ${LANG})"
    [[ ${LANG} != @("C.UTF-8"|"POSIX"|"C") && ! "${LOCALE}" =~ (^|,)${LANG}(,|$) ]] && LOCALE="${LOCALE:+${LOCALE},}${LANG}"
    # Сохраняем значачение, только при загрузке системы
    if [[ -n ${ROOTFS} ]]; then
            [[ -f ${SYSCONF}/locale ]] && sed "/^LOCALE=/d" -i "${SYSCONF}/locale"
            echo "LOCALE=\"${LOCALE}\"" >> "${SYSCONF}/locale"
    fi

    # Проверка локалий в системе, и если не совпадают, то генерация
    if [[ ${FORCE_LOCALE_GEN} != "yes" && -f ${ROOTFS}/usr/lib/locale/locale-archive ]]; then
        LOCALE_CONF=${LOCALE//-/}; LOCALE_CONF=${LOCALE_CONF,,}; LOCALE_CONF=${LOCALE_CONF//,/$'\n'}; LOCALE_CONF=$(sort -fu <<< ${LOCALE_CONF})
        LOCALE_SYSTEM=$(${CMD_CHROOT} localedef --list-archive | sort -fu); LOCALE_SYSTEM=${LOCALE_SYSTEM,,}
        [[ "${LOCALE_CONF}" == "${LOCALE_SYSTEM}" ]] || FORCE_LOCALE_GEN=yes
    else
	FORCE_LOCALE_GEN=yes
    fi
    if [[ ${FORCE_LOCALE_GEN} == "yes" ]]; then
        # Комментируем все локализации
        sed -E "s/^([^#]+)/#\1/g" -i ${ROOTFS}/etc/locale.gen
        # Открываем комменарии нужных локалий
        for SELECT_LOCALE in ${LOCALE//@(,|;)/ }; do
            [[ -n ${SELECT_LOCALE} ]] || continue
            sed -E "s/^#${SELECT_LOCALE} /${SELECT_LOCALE} /g" -i ${ROOTFS}/etc/locale.gen
        done
        # Генерируем локаль
        ${CMD_CHROOT} locale-gen &>/dev/null
    fi
}

exec_02_set_lang(){
    # Не учитываем нстройку LANG из env
    local LANG=
    [[ -f ${SYSCONF}/locale && $(< ${SYSCONF}/locale) =~ (^|$'\n')LANG=\"?\'?([^$'\n'\"\']+)\"?\'?($'\n'|$) ]] && LANG=${BASH_REMATCH[2]} || LANG="en_US.UTF-8"
    local LANG_NEW=$(cmdline_value lang)
    if [[ -n ${ROOTFS} && -n ${LANG_NEW} ]]; then
        LANG="$(get_fullname_lang ${LANG_NEW})"
        [[ -f ${SYSCONF}/locale ]] && sed "/^LANG=/d" -i "${SYSCONF}/locale"
        echo "LANG=\"${LANG}\"" >> "${SYSCONF}/locale"
    else
	LANG="$(get_fullname_lang ${LANG})"
    fi
    [[ ${LANG} == @("C.UTF-8"|"POSIX"|"C") ]] && LANG="en_US.UTF-8"

    # Проверка выбранного языка в системе, и если не совпадает, то устанавливаем
    if [[ -w ${ROOTFS}/etc/locale.conf && ! $(< ${ROOTFS}/etc/locale.conf) =~ (^|$'\n')"LANG=${LANG}"($'\n'|$) ]] || [[ ! -f ${ROOTFS}/etc/locale.conf ]]; then
        # Устанавливаем локаль
        ${CMD_CHROOT} env LANG="${LANG}" LANGUAGE="${LANG}" LC_CTYPE="${LANG}" LC_NUMERIC="${LANG}" \
        LC_TIME="${LANG}" LC_COLLATE="${LANG}" LC_MONETARY="${LANG}" LC_MESSAGES="${LANG}" LC_PAPER="${LANG}" \
        LC_NAME="${LANG}" LC_ADDRESS="${LANG}" LC_TELEPHONE="${LANG}" LC_MEASUREMENT="${LANG}" \
        LC_IDENTIFICATION="${LANG}" locale > ${ROOTFS}/etc/locale.conf 2>/dev/null

        [[ -n ${ROOTFS} ]] || set_lang_live
    fi
    #; unset LANG; source /etc/profile.d/locale.sh"

    # Если имеются языкозависимые файлы, то копируем в корень
    [[ -d ${ROOTFS}/usr/share/ublinux/langs/${LANG} ]] && cp -pfr ${ROOTFS}/usr/share/ublinux/langs/${LANG}/* ${ROOTFS}/
}

set_lang_live(){
    if [[ $(readlink -fq /usr/bin/init 2>/dev/null) =~ "lib/systemd/systemd"$ ]]; then
        systemctl daemon-reexec
    fi
}

exec_03_set_vconsole(){
    local LANG=
    [[ -f ${SYSCONF}/locale && $(< ${SYSCONF}/locale) =~ (^|$'\n')LANG=\"?\'?([^$'\n'\"\']+)\"?\'?($'\n'|$) ]] && LANG=${BASH_REMATCH[2]} || LANG="en_US.UTF-8"
    local LANG_NEW=$(cmdline_value lang)
    if [[ -n ${ROOTFS} && -n ${LANG_NEW} ]]; then
        LANG="$(get_fullname_lang ${LANG_NEW})"
    else
        LANG="$(get_fullname_lang ${LANG})"
    fi
    [[ $(declare -p CONSOLE_FONT 2>/dev/null) =~ "declare -A" ]] || declare -A CONSOLE_FONT
    [[ $(declare -p CONSOLE_FONT_MAP 2>/dev/null) =~ "declare -A" ]] || declare -A CONSOLE_FONT_MAP
    [[ $(declare -p CONSOLE_FONT_UNIMAP 2>/dev/null) =~ "declare -A" ]] || declare -A CONSOLE_FONT_UNIMAP
    [[ $(declare -p CONSOLE_KEYMAP 2>/dev/null) =~ "declare -A" ]] || declare -A CONSOLE_KEYMAP
    [[ $(declare -p CONSOLE_KEYMAP_TOGGLE 2>/dev/null) =~ "declare -A" ]] || declare -A CONSOLE_KEYMAP_TOGGLE
    # Зададим /etc/vconsole.conf
    local SET_VCONSOLE=
    local VCONSOLE_FILE="${ROOTFS}/etc/vconsole.conf"
    if [[ -n ${CONSOLE_FONT} ]]; then
        SET_VCONSOLE+="FONT=${CONSOLE_FONT}"$'\n'
    elif [[ -n ${CONSOLE_FONT[${LANG%%_*}]} ]]; then
        SET_VCONSOLE+="FONT=${CONSOLE_FONT[${LANG%%_*}]}"$'\n'
    fi
    if [[ -n ${CONSOLE_FONT_MAP} ]]; then
        SET_VCONSOLE+="FONT_MAP=${CONSOLE_FONT_MAP}"$'\n'
    elif [[ -n ${CONSOLE_FONT_MAP[${LANG%%_*}]} ]]; then
        SET_VCONSOLE+="FONT_MAP=${CONSOLE_FONT_MAP[${LANG%%_*}]}"$'\n'
    fi
    if [[ -n ${CONSOLE_FONT_UNIMAP} ]]; then
        SET_VCONSOLE+="FONT_UNIMAP=${CONSOLE_FONT_UNIMAP}"$'\n'
    elif [[ -n ${CONSOLE_FONT_UNIMAP[${LANG%%_*}]} ]]; then
        SET_VCONSOLE+="FONT_UNIMAP=${CONSOLE_FONT_UNIMAP[${LANG%%_*}]}"$'\n'
    fi
    if [[ -n ${CONSOLE_KEYMAP} ]]; then
        SET_VCONSOLE+="KEYMAP=${CONSOLE_KEYMAP}"$'\n'
    elif [[ -n ${CONSOLE_KEYMAP[${LANG%%_*}]} ]]; then
        SET_VCONSOLE+="KEYMAP=${CONSOLE_KEYMAP[${LANG%%_*}]}"$'\n'
    fi
    if [[ -n ${CONSOLE_KEYMAP_TOGGLE} ]]; then
        SET_VCONSOLE+="KEYMAP_TOGGLE=${CONSOLE_KEYMAP_TOGGLE}"$'\n'
    elif [[ -n ${CONSOLE_KEYMAP_TOGGLE[${LANG%%_*}]} ]]; then
        SET_VCONSOLE+="KEYMAP_TOGGLE=${CONSOLE_KEYMAP_TOGGLE[${LANG%%_*}]}"$'\n'
    fi
    if [[ -n ${XKBLAYOUT} ]]; then
        SET_VCONSOLE+="XKBLAYOUT=${XKBLAYOUT}"$'\n'
    elif [[ -n ${XKBLAYOUT[${LANG%%_*}]} ]]; then
        SET_VCONSOLE+="XKBLAYOUT=${XKBLAYOUT[${LANG%%_*}]}"$'\n'
    fi
    if [[ -n ${XKBMODEL} ]]; then
        SET_VCONSOLE+="XKBMODEL=${XKBMODEL}"$'\n'
    elif [[ -n ${XKBMODEL[${LANG%%_*}]} ]]; then
        SET_VCONSOLE+="XKBMODEL=${XKBMODEL[${LANG%%_*}]}"$'\n'
    fi
    if [[ -n ${XKBVARIANT} ]]; then
        SET_VCONSOLE+="XKBVARIANT=${XKBVARIANT}"$'\n'
    elif [[ -n ${XKBVARIANT[${LANG%%_*}]} ]]; then
        SET_VCONSOLE+="XKBVARIANT=${XKBVARIANT[${LANG%%_*}]}"$'\n'
    fi
    if [[ -n ${XKBOPTIONS} ]]; then
        SET_VCONSOLE+="XKBOPTIONS=${XKBOPTIONS}"$'\n'
    elif [[ -n ${XKBOPTIONS[${LANG%%_*}]} ]]; then
        SET_VCONSOLE+="XKBOPTIONS=${XKBOPTIONS[${LANG%%_*}]}"$'\n'
    fi
    if [[ -n ${SET_VCONSOLE} ]]; then
	SET_VCONSOLE="\
# Written by /ublinux/rc.preinit.d/53-language, read by manual.
# Use 'ubconfig set [locale] CONSOLE_FONT= CONSOLE_KEYMAP= CONSOLE_KEYMAP_TOGGLE=' to update this file.
${SET_VCONSOLE}
"
	if [[ -f "${VCONSOLE_FILE}" ]]; then
    	    [[ "$(< ${VCONSOLE_FILE})" == "${SET_VCONSOLE}" ]] || echo -n "${SET_VCONSOLE}" > "${VCONSOLE_FILE}"
	else
    	    echo -n "${SET_VCONSOLE}" > "${VCONSOLE_FILE}"
	fi
	[[ -n ${ROOTFS} ]] || set_vconsole_live
    fi
}

set_vconsole_live(){
    if [[ $(readlink -fq /usr/bin/init 2>/dev/null) =~ "lib/systemd/systemd"$ ]]; then
        #systemctl --quiet start systemd-vconsole-setup.service
	# Настроить шрифт и раскладку клавиатуры виртуальной консоли  из /etc/vconsole.conf использует loadkeys setfont
	[[ -x /usr/lib/systemd/systemd-vconsole-setup ]] && /usr/lib/systemd/systemd-vconsole-setup
    else
        #setfont ?
        #loadkeys ?
        true
    fi
}

################
##### MAIN #####
################

    # Если файл подключен как ресурс с функциями, то выйти
    return 0 2>/dev/null && return 0
    if [[ -z $@ ]]; then
        while read -r FUNCTION; do
            $"${FUNCTION##* }"
        done < <(declare -F | grep "declare -f exec_")
    else
        FUNCTION=
        while [[ $# -gt 0 ]]; do
            # Что-бы передавать пустые параметры как аргументы, нужно для соблюдения очередности и кол-ва, отключил [[ -z ${1} ]] || {}
            #[[ -z ${1} ]] || { declare -f "${1}" &>/dev/null && FUNCTION+="; ${1}" || FUNCTION+=" '${1}'"; }
            declare -f "${1}" &>/dev/null && FUNCTION+="; ${1}" || FUNCTION+=" '${1}'"
            shift
        done
        eval ${FUNCTION#*; }
    fi
    true
