#!/usr/bin/env bash
#
#   Script name: ubconfig
#   Description: Script for configure UBLinux (ublinux.ini)
#   GitLab: https://gitlab.ublinux.ru/
#   Author: Dmitry Razumov asmeron@ublinux.ru
#   Contributors: asmeron@ublinux.ru
#
#   Copyright (c) 2021-2022 UBLinux Development Team <support@ublinux.ru>
#
#   This program is free software; you can redistribute it and/or modify
#   it under the terms of the GNU General Public License as published by
#   the Free Software Foundation; either version 2 of the License, or
#   (at your option) any later version.
#
#   This program is distributed in the hope that it will be useful,
#   but WITHOUT ANY WARRANTY; without even the implied warranty of
#   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
#   GNU General Public License for more details.
#
#   You should have received a copy of the GNU General Public License
#   along with this program.  If not, see <http://www.gnu.org/licenses/>.

VERSION_SCRIPT="1.1"

# Exit Immediately if a command fails
#set -o errexit

#################################
###   :::   C O L O R S   :::   #
#################################
set_color(){
#http://abload.de/img/bash-color-chartmxjbp.png
    export BBC=$'\e[1;34m'
    export RBC=$'\e[1;31m'
    export WBC=$'\e[1m'
    export EC=$'\e[0m'

    export txtblk='\033[0;30m' # Black - Regular
    export txtred='\033[0;31m' # Red			# prompt: error color
    export txtgrn='\033[0;32m' # Green			# prompt: success color
    export txtylw='\033[0;33m' # Yellow			# prompt: waring color
    export txtblu='\033[0;34m' # Blue			
    export txtpur='\033[0;35m' # Purple
    export txtcyn='\033[0;36m' # Cyan			# prompt: info color
    export txtwht='\033[0;37m' # White
    export bldblk='\033[1;30m' # Black - Bold
    export bldred='\033[1;31m' # Red			# prompt: bold error color
    export bldgrn='\033[1;32m' # Green			# prompt: bold success color
    export bldylw="\033[1;33m" # Yellow                 # prompt: bold warning color
    export bldblu='\033[1;34m' # Blue				
    export bldpur='\033[1;35m' # Purple
    export bldcyn="\033[1;36m" # Cyan                   # prompt: bold info color
    export bldwht="\033[1;37m" # White			# prompt: bold default color

    export undblk='\033[4;30m' # Black - Underline
    export undred='\033[4;31m' # Red

    export bakblk='\033[40m'   # Black - Background
    export bakred='\033[41m'   # Red
    export badgrn='\033[42m'   # Green

    export txtrst='\033[0m'    # Text Reset		# prompt: default color
}


#######################################
###   :::   F U N C T I O N S   :::   #
#######################################

check_root(){
    if [[ ${EUID:-$(id -u)} > 0 ]]; then
	case ${1} in
	    -w  | --warning)	  shift; prompt -w "Please run as root! ${@}" && return 1 ;;
	    -wq | --warning-quit) shift; prompt -wq "Please run as root!" ;;
    	    *) 			  prompt -wq "Please run as root!" ;;
        esac
    fi
}

# Check command availability
has_command(){ command -v $1 &> /dev/null; }

# echo like ... with flag type and display message colors
prompt(){
    [[ -n ${QUIET} ]] && return
    case ${1} in
	-s  | --success)	shift; echo -e "${bldgrn}${@}${txtrst}" ;;    			# print success message
	-sq | --success-quit)	shift; echo -e "${bldgrn}${@}${txtrst}"; exit 1 ;;    		# print success message
	-e  | --error)   	shift; echo -e "${bldred}ERROR:${@}${txtrst}" ;;   		# print error message
	-eq | --error-quit)   	shift; echo -e "${bldred}ERROR:${@}${txtrst}"; exit 1 ;;	# print error message
	-w  | --warning) 	shift; echo -e "${bldylw}WARNING:${bldwht}${@}${txtrst}" ;; 	# print warning message
	-wq | --warning-quit) 	shift; echo -e "${bldylw}WARNING:${bldwht}${@}${txtrst}"; exit 1 ;; # print warning message
	-i  | --info)    	shift; echo -e "${bldcyn}INFO:${txtcyn}${@}${txtrst}" ;;    	# print info message
	-iq | --info-quit)    	shift; echo -e "${bldcyn}INFO:${txtcyn}${@}${txtrst}"; exit 1 ;; # print info message
	*)    			echo -e "$@" ;;							# print all message
    esac
}

usage_version(){
    printf "%s  %s\n" "${0##*/}" "version: ${VERSION_SCRIPT}"
}
usage(){
    cat <<EOF
Configure UBLinux

Usage:  ${0##*/} [OPTIONS...] {COMMAND} {SECTION}  ...

Commands:
  get		Get configuration option | Получить параметр конфигурации
  set 		Set configuration option | Установить параметр конфигурации
  remove 	Remove option of a configuration | Удалить параметр конфигурации

Meta Commands:
  help          Show this help

Options for get:
  -r, --raw	  Show only values, without name variables | Показать только значения, без имен переменных
  -s, --source=<SOURCE>
		  Configuration as source| Источник конфигурации
   *glo | global  Configuration file as source: ublinux.ini
    sys | system  Configuration file as source: /etc/ublinux/*
    def | default Configuration file as source: /usr/lib/ublinux/os-config
    <file>        Configuration file as source, global ublinux.ini format: <FILE.ini>
  -d, --default   Before loading the source, additionally include the default 
		  settings file /usr/lib/ublinux/os-config
  -c, --compare   Compare configuration, system and global configuration files

Options for set:
  -t, --target
   *		  Without the specified option, are used *global *system
   *glo | global  Only configuration file as target: ublinux.ini
   *sys | system  Only configuration file as target: /etc/ublinux/*
    <file>        Configuration file as target, global ublinux.ini format: <FILE.ini>
  -n, --noexecute Do not execute system configuration commands for option

Options for remove:
  -t, --target
   *		  Without the specified option, are used *global *system
   *glo | global  Only configuration file as target: ublinux.ini
   *sys | system  Only configuration file as target: /etc/ublinux/*
    <file>        Configuration file as target, global ublinux.ini format: <FILE.ini>
  -n, --noexecute Do not execute system configuration commands for option

Options:
  -h, --help	  Show this help
  -h, --help=<SECTION>
	    	  Show help by section
  -q, --quiet	  Quiet mode
  -V, --version	  Show package version

Known sections:
  config 	/etc/ublinux/config
  network 	/etc/ublinux/network
  kiosk		/etc/ublinux/kiosk

Examples:
${0##*/} get config HOSTNAME
${0##*/} get / DOMAIN
${0##*/} --raw get / DOMAIN
${0##*/} get /
${0##*/} --source system get /
${0##*/} --source global get /
${0##*/} --compare get config
${0##*/} --default --source system get config DEFAULTPASSWD
${0##*/} set config HOSTNAME=myhost 
${0##*/} set network DOMAIN=domain.ru NETWORK[all]="+ipv4.dns 192.168.1.1"
${0##*/} remove network DOMAIN
${0##*/} remove network DOMAIN[] NETWORK[]
${0##*/} remove network DOMAIN[*]
EOF
}
usage_config(){
    cat <<EOF
Configure UBLinux
Usage:  ${0##*/} {COMMAND} {SECTION} [OPTIONS...] ...

Options section: config
  HOSTNAME=<HOSTNAME>   Host name | Имя машины
EOF
}
usage_network(){
    cat <<EOF
Configure UBLinux
Usage:  ${0##*/} {COMMAND} {SECTION} [OPTIONS...] ...

Options section: network
  DOMAIN=<DOMAIN>	Domain configuration | Подключение к AD серверу

EOF
}
usage_kiosk(){
    cat <<EOF
Configure UBLinux
Usage:  ${0##*/} {COMMAND} {SECTION} [OPTIONS...] ...

Options section: kiosk
    cat <<EOF
EOF
}
help(){
    usage_version
    [[ -n $1 ]] || usage
    [[ $1 == "config" ]] && usage_config
    [[ $1 == "network" ]] && usage_network
    [[ $1 == "kiosk" ]] && usage_kiosk
    exit 0
}
arguments(){
# Pre-process options to:
# - expand -xyz into -x -y -z
# - expand --longopt=arg into --longopt arg
    local ARGV=()
    local END_OF_OPT=
    while [[ $# -gt 0 ]]; do
	arg="$1"; shift
	case "${END_OF_OPT}${arg}" in
	    --) ARGV+=("$arg"); END_OF_OPT=1 ;;
	    --*=*)ARGV+=("${arg%%=*}" "${arg#*=}") ;;
	    --*) ARGV+=("$arg") ;;
	    -*) for i in $(seq 2 ${#arg}); do ARGV+=("-${arg:i-1:1}"); done ;;
	    *) ARGV+=("$arg") ;;
	esac
    done
# Apply pre-processed options
    set -- "${ARGV[@]}"
# Parse options
    local END_OF_OPT=
    local POSITIONAL_ARGS=()
    [[ -z $@ ]] && usage && exit 0
    while [[ $# -gt 0 ]]; do
	case "${END_OF_OPT}${1}" in
	    get | GET)		   COMMAND="${1,,}"; END_OF_OPT=1 ;;
	    set | SET)		   COMMAND=${1,,}; END_OF_OPT=1 ;;
	    remove | REMOVE)	   COMMAND=${1,,}; END_OF_OPT=1 ;;
	    -r | --raw)    	   RAW=1 ;;	    
	    -c | --compare)    	   COMPARE=1 ;;
	    -s | --source) 	   shift; SOURCE="$1" ;;
	    -d | --default)	   LOAD_DEFAULT=1 ;;
	    -t | --target) 	   shift; TARGET="$1" ;;
	    -n | --noexecute) 	   SET_NOEXECUTE=1 ;;
	    -h | --help | help)	   shift; help $1;;
	    -q | --quiet)     	   QUIET=1; QUIET_ARG="-q" ;;
	    -V | --version)	   usage_version; exit 0 ;;
	    --stdin)        	   READ_STDIN=1 ;;
	    --)             	   END_OF_OPT=1 ;;
	    -*|--*)         	   prompt -w "Unrecognized argument, skiped: $1" >&2  ;;
	    *)              	   POSITIONAL_ARGS+=("$1") ;;
	esac
	shift
    done
# Restore positional parameters
    set -- "${POSITIONAL_ARGS[@]}"
    [[ ${COMMAND} == 'get' ]] && REQUEST_ARGS="$@"
    [[ ${COMMAND} == 'set' ]] && REQUEST_ARGS="$@"
    [[ ${COMMAND} == 'remove' ]] && REQUEST_ARGS="$@"
    [[ ${COMMAND} == 'get' && -z ${SOURCE} ]] && SOURCE="global"
    [[ -n ${SOURCE} ]] && case "${SOURCE}" in
	glob | global)	SOURCE="global" ;;
	sys  | system)	SOURCE="system" ;;
	def  | default)	SOURCE="default" ;;
	*)		[[ -f ${SOURCE} ]] || prompt -eq " Unrecognized sources !" ;;
    esac
    [[ -n ${TARGET} ]] && case "${TARGET}" in
	glob | global)	TARGET="global" ;;
	sys  | system)	TARGET="system" ;;
	*)		[[ -f ${TARGET} ]] || prompt -eq " Unrecognized target !" ;;
    esac
}

prepare_section(){
    SECTION=$(egrep '^([\[\/]){,1}([\/A-Za-z0-9.-_])+([\/\]]){,1}$' <<< ${1} | tr -d '[]') #'
    [[ ${SECTION} == "" ]] && SECTION="unknown"
    grep -q '^/' <<< ${SECTION} 2>/dev/null || SECTION="/etc/ublinux/${SECTION}"
    SECTION="[${SECTION}]"
}

get_value(){
    # $1 Имя переменной из внешней функции, для заполнения данными
    # $2 Перечень опций для поиска
    # $3 ${FILE_UBLINUX_DATA} как источник данных для анализа
    get_value_config(){
	declare -n VALUE_CONFIG=$1
	shift
	# Из полученных переменных сформировать вывод в зависимости от опции --raw
	write_value_config(){
	    while read -r LINE; do
	        [[ -n ${RAW} ]] && VALUE_CONFIG+="${LINE#*=}\n" || VALUE_CONFIG+="${LINE}\n"
	    done <<< "${1}"
	}
	local FIND_VALUE_CONFIG=${FILE_UBLINUX_DATA}
	# Если секция не указана, то выводим весь файл
	if [[ ${SECTION} == "" || ${SECTION} == "/" || ${SECTION} == "[/]" ]]; then
	    FIND_VALUE_CONFIG=$(egrep -v '^declare|^\[' <<< ${FIND_VALUE_CONFIG})
	    write_value_config "${FIND_VALUE_CONFIG}"
	# Секция указан, ищем запрошенные переменные и выводим
        else
	    # Вырезать искомую секцию из файла конфигурации
    	    if [[ ${!VALUE_CONFIG} != "VALUE_SYSTEM" ]]; then
    		# Экранировать все символы в имени секции
		ESC_SECTION=$(sed 's/[^a-zA-Z0-9,._@%-]/\\&/g' <<< "${SECTION}")
		FIND_VALUE_CONFIG=$(sed -En "/${ESC_SECTION}/,/^\[/p" <<< "${FIND_VALUE_CONFIG}" | grep -v '^\[')
	    fi
	    # Если указан только секция и нет переменных для фильтра
	    if [[ -n ${SECTION} ]] && [[ $@ == "" || $@ == "/" ]]; then
		write_value_config "${FIND_VALUE_CONFIG}"
	    # Указан секция и присутствуют переменные для фильтра
	    else
		for REQUEST_ITEM in "$@"; do
		    if [[ ${REQUEST_ITEM%%=*} =~ "[]"$|"[*]"$ ]]; then
	    		REQUEST_ITEM=$(sed 's/[^a-zA-Z0-9 ]/\\&/g' <<< "${REQUEST_ITEM%%[*}[")
    	    		FIND_VALUE=$(egrep "^${REQUEST_ITEM}" <<< ${FIND_VALUE_CONFIG})
			
		    else
	    		REQUEST_ITEM=$(sed 's/[^a-zA-Z0-9 ]/\\&/g' <<< "${REQUEST_ITEM%%=*}=")
    	    		FIND_VALUE=$(egrep "^${REQUEST_ITEM}" <<< ${FIND_VALUE_CONFIG} | tail -1)
    	    	    fi
    	    	    [[ ${FIND_VALUE} != "" ]] || FIND_VALUE="(null)"
		    write_value_config "${FIND_VALUE}"
		done
	    fi
	fi
    }
    get_value_compare(){
	while read -r REQUEST_ITEM; do
	    egrep -q "^$|(null)" <<< ${REQUEST_ITEM} && continue
	    REQUEST_ITEM_ESC=$(sed 's/[^a-zA-Z0-9 ]/\\&/g' <<< ${REQUEST_ITEM})
	    FIND_VALUE=$(egrep "^${REQUEST_ITEM_ESC}" <<< ${2//\\n/$'\n'})
	    [[ ${FIND_VALUE} == "" ]] && FIND_VALUE="${REQUEST_ITEM}" || continue
	    if [[ -n ${RAW} ]]; then 
		while read -r LINE; do
		    VALUE_COMPARE+="${3}${LINE#*=}\n"
		done <<< ${FIND_VALUE}
	    else
		while read -r LINE; do
		    VALUE_COMPARE+="${3}${LINE}\n"
		done <<< ${FIND_VALUE}
	    fi
	done <<< ${FILE_UBLINUX_DATA//\\n/$'\n'}
    }
    local VALUE_COMPARE=
    local VALUE_GLOBAL=
    local VALUE_SYSTEM=
    local VALUE_DEFAULT=
    local VALUE_MANUAL=
    shift
    if [[ -n ${COMPARE} ]]; then
	FILE_UBLINUX_DATA=$(egrep -v '^\s*#|^\s*$' ${FILE_UBLINUX_CONF})
        get_value_config "VALUE_GLOBAL" "$@"
    	if [[ ${SECTION} == "[/]" ]]; then
    	    FILE_UBLINUX_DATA="$(cat ${PATH_UBLINUX_CURRENT}/* | egrep -v '^\s*#|^\s*$')"
    	    get_value_config "VALUE_SYSTEM" "$@"
	elif [[ -f ${PATH_UBLINUX_CURRENT}/$(tr -d '[]' <<< ${SECTION##*/}) ]]; then
    	    FILE_UBLINUX_DATA=$(cat ${PATH_UBLINUX_CURRENT}/$(tr -d '[]' <<< ${SECTION##*/}) | egrep -v '^\s*#|^\s*$')
    	    get_value_config "VALUE_SYSTEM" "$@"
    	fi
        get_value_compare "${VALUE_GLOBAL}" "${VALUE_SYSTEM}" "Global:"
        get_value_compare "${VALUE_SYSTEM}" "${VALUE_GLOBAL}" "System:"
	echo -en "${VALUE_COMPARE}"
    elif [[ ${SOURCE} == global ]]; then 
	[[ -f ${FILE_UBLINUX_CONF} ]] || return 1
	FILE_UBLINUX_DATA=$(egrep -v '^\s*#|^\s*$' ${FILE_UBLINUX_CONF})
	if [[ ${SECTION} != "" && ${SECTION} != "[/]" && -n ${LOAD_DEFAULT} ]]; then
	    ESC_SECTION=$(sed 's/[^a-zA-Z0-9,._+@%-]/\\&/g' <<< "${SECTION}")
	    FILE_UBLINUX_DATA=$(sed "/${ESC_SECTION}/r"<(echo "$(egrep -v '^\s*#|^\s*$' ${FILE_UBLINUX_DEFAULT})") <<< ${FILE_UBLINUX_DATA}) #"
	fi
        get_value_config "VALUE_GLOBAL" "$@"
        echo -en "${VALUE_GLOBAL}"
    elif [[ ${SOURCE} == system ]]; then
    	if [[ ${SECTION} == "" || ${SECTION} == "[/]" ]]; then
    	    FILE_UBLINUX_DATA=$(cat ${PATH_UBLINUX_CURRENT}/* | egrep -v '^\s*#|^\s*$')
    	    get_value_config "VALUE_SYSTEM" "$@"
	elif [[ -f ${PATH_UBLINUX_CURRENT}/$(tr -d '[]' <<< ${SECTION##*/}) ]]; then
	    [[ -n ${LOAD_DEFAULT} ]] && FILE_DEFAULT_DATA="$(egrep -v '^\s*#|^\s*$' ${FILE_UBLINUX_DEFAULT})\n"
    	    FILE_UBLINUX_DATA=${FILE_DEFAULT_DATA/%\\n/$'\n'}$(cat ${PATH_UBLINUX_CURRENT}/$(tr -d '[]' <<< ${SECTION##*/}) | egrep -v '^\s*#|^\s*$')
    	    get_value_config "VALUE_SYSTEM" "$@"
    	fi
        echo -en "${VALUE_SYSTEM}"
    elif [[ ${SOURCE} == default ]]; then
	[[ -f ${FILE_UBLINUX_DEFAULT} ]] || return 1
	FILE_UBLINUX_DATA=$(egrep -v '^\s*#|^\s*$' ${FILE_UBLINUX_DEFAULT})
	get_value_config "VALUE_DEFAULT" "$@"
	echo -en "${VALUE_DEFAULT}"
    else
	[[ -f ${SOURCE} ]] || return 1
	FILE_UBLINUX_DATA=$(egrep -v '^\s*#|^\s*$' ${SOURCE})
	get_value_config "VALUE_MANUAL" "$@"
	echo -en "${VALUE_MANUAL}"
    fi
}
remove_value(){
    remove_value_local(){
	remove_value_global(){
		# Поиск секции по полному имени с каталогом [/etc/ublinux/name]
		if ESC_SECTION=$(sed 's/[^a-zA-Z0-9,._@%-]/\\&/g' <<< "${SECTION}") && egrep -q "^${ESC_SECTION}" "${FILE_UBLINUX_CONF}"; then
		    true
		# Поиск секции по сокращённому имени без каталога [name]
		elif ESC_SECTION="\[$(tr -d '[]' <<< ${SECTION##*/})\]" && egrep -q "^${ESC_SECTION}" "${FILE_UBLINUX_CONF}"; then
		    true
		else 
		    return 1
		fi
	        # Вырезаем блок по меткам
		FIND_VALUE_CONFIG=$(grep -n "" "${FILE_UBLINUX_CONF}" | sed -E -n "/^[0-9]*:${ESC_SECTION}/,/^[0-9]*:\s*#*\s*\[/p")
		# Если сектор пустой и состоит только из заголовка сектор, то пропуск, иначе последнюю строку следующего сектора вырезаем
		[[ $(head -1 <<< ${FIND_VALUE_CONFIG}) != $(tail -1 <<< ${FIND_VALUE_CONFIG}) ]] || FIND_VALUE_CONFIG=$(sed -E '${/^[0-9]*:\s*#*\s*\[/d;}' <<< ${FIND_VALUE_CONFIG})
		# Нет выбранного блока для анализа
		if [[ ${FIND_VALUE_CONFIG} == "" ]]; then
		    return 1
		# Если после имени указано [] или [*] то удалить все переменные ассациативного массива	
		elif [[ ${NAME_VAR##*\[} =~ ^"]"$|^"*]"$ ]] && SECTION_DATA="$(egrep "^[0-9]*:${ESC_NAME_VAR%%[*}[" <<< ${FIND_VALUE_CONFIG} | cut -d: -f1)" && [[ ${SECTION_DATA} != "" ]]; then 
		    sed -E "${SECTION_DATA//$'\n'/d;}d" -i "${FILE_UBLINUX_CONF}"
		# Поиск прямое совпадение переменной, номер строки в переменную ^A=
		elif SECTION_DATA="$(egrep "^[0-9]*:${ESC_NAME_VAR}=" <<< ${FIND_VALUE_CONFIG} | tail -1 | cut -d: -f1)" && [[ ${SECTION_DATA} != "" ]]; then 
		    # Прямое совпадение найдено, удаление по номеру строки
		    sed -E "${SECTION_DATA}d" -i "${FILE_UBLINUX_CONF}"
		else 
		    return 1
		fi
	}
	remove_value_system(){
	    if [[ -f ${FILE_CONFIG} ]]; then
	        if [[ ${NAME_VAR##*\[} =~ ^"]"$|^"*]"$ ]]; then
	    	    egrep -q "^${ESC_NAME_VAR%%[*}[" "${FILE_CONFIG}" || return 1
		    sed -E "/^${ESC_NAME_VAR%%[*}[/d" -i "${FILE_CONFIG}"
		    egrep -q "^${ESC_NAME_VAR%%[*}[" "${FILE_CONFIG}" &&  return 1
		else
		    egrep -q "^${ESC_NAME_VAR}=" "${FILE_CONFIG}" || return 1
		    sed -E "/^${ESC_NAME_VAR}=/d" -i "${FILE_CONFIG}"
		    egrep -q "^${ESC_NAME_VAR}=" "${FILE_CONFIG}" &&  return 1
		fi
		sed "/^declare -A/d" -i "${FILE_CONFIG}"
		DECLARE_A=$(cat "${FILE_CONFIG}" | egrep "^[A-z0-9_]*\[.*\]=.*" | sed -E "s/\[.*//" | uniq | tr "\n" " ")
		[[ -z ${DECLARE_A} ]] || sed -E -i "1i declare -A ${DECLARE_A}" -i "${FILE_CONFIG}"
	    else
	        return 3
	    fi
	}
	ESC_NAME_VAR="$(sed 's/[^a-zA-Z0-9,._@%-]/\\&/g' <<< "${NAME_VAR}")"
	#FILE_CONFIG="${PATH_UBLINUX_CURRENT}/$(tr -d '[]' <<< "${SECTION##*/}")"
	# Если базовый каталог указанный в секции соответствует системному каталогу /etc/ublinux, то продолжить
	PATH_CONFIG_SECTION=$(sed "s/\[\([a-zA-Z0-9,._@%-/]*\)\].*/\1/;s/.[^/]*$//" <<< "${SECTION}") #"
	[[ ${PATH_CONFIG_SECTION} == ${PATH_UBLINUX_CURRENT} ]] && FILE_CONFIG=$(sed "s/\[\([a-zA-Z0-9,._@%-/]*\)\].*/\1/" <<< "${SECTION}") #"
	if [[ -z ${TARGET} ]]; then
	    remove_value_global; STATUS_GLOBAL=$?
	    remove_value_system; STATUS_SYSTEM=$?
	elif [[ ${TARGET} == global ]]; then
	    remove_value_global; STATUS_GLOBAL=$?
	elif [[ ${TARGET} == system ]]; then
	    remove_value_system; STATUS_SYSTEM=$?
	elif [[ -f ${TARGET} ]]; then
	    FILE_UBLINUX_CONF=${TARGET}
	    remove_value_global; STATUS_GLOBAL=$?
	fi
	[[ ${STATUS_GLOBAL} == 0 ]] && prompt -s "${NAME_VAR} variable remove from global configuration ${FILE_UBLINUX_CONF}"
	[[ ${STATUS_GLOBAL} == 1 ]] && { prompt -w " ${NAME_VAR} variable not remove from global configuration ${FILE_UBLINUX_CONF}"; STATUS=1; }
	[[ ${STATUS_SYSTEM} == 0 ]] && prompt -s "${NAME_VAR} variable remove from system configuration ${FILE_CONFIG}"
	[[ ${STATUS_SYSTEM} == 1 ]] && { prompt -w " ${NAME_VAR} variable not remove from system configuration ${FILE_CONFIG}"; STATUS=1; }
	[[ ${STATUS} == 1 ]] && return 1 || return 0
    }
    shift
    [[ -n "$@" ]] || prompt -eq " not found arguments !"
    for ARG in "$@"; do
	NAME_VAR=${ARG%%=*}; VALUE_VAR=${ARG#*=}
	remove_value_local
	[[ -n ${SET_NOEXECUTE} ]] || select_exec
    done
}
set_value(){
    set_value_local(){
	set_value_global(){
		local SECTION_DATA=
		# Поиск секции по полному имени с каталогом [/etc/ublinux/name]
		if ESC_SECTION=$(sed 's/[^a-zA-Z0-9,._@%-]/\\&/g' <<< "${SECTION}") && egrep -q "^\s*#*\s*${ESC_SECTION}" "${FILE_UBLINUX_CONF}"; then
		    # Если секция закомментирована, то открываем
		    sed -E "s/^\s*#*\s*${ESC_SECTION}/${ESC_SECTION}/" -i "${FILE_UBLINUX_CONF}"
		    # Вырезаем блок по меткам
		    FIND_VALUE_CONFIG=$(grep -n "" "${FILE_UBLINUX_CONF}" | sed -E -n "/^[0-9]*:\s*#*\s*${ESC_SECTION}/,/^[0-9]*:\s*#*\s*\[/p")
		    # Если сектор пустой и состоит только из заголовка сектор, то пропуск, иначе последнюю строку следующего сектора вырезаем
		    [[ $(head -1 <<< ${FIND_VALUE_CONFIG}) != $(tail -1 <<< ${FIND_VALUE_CONFIG}) ]] || FIND_VALUE_CONFIG=$(sed -E '${/^[0-9]*:\s*#*\s*\[/d;}' <<< ${FIND_VALUE_CONFIG})
		# Поиск секции по сокращённому имени без каталога [name]
		elif ESC_SECTION="\[$(tr -d '[]' <<< ${SECTION##*/})\]" && egrep -q "^\s*#*\s*${ESC_SECTION}" "${FILE_UBLINUX_CONF}"; then
		    # Если секция закомментирована, то открываем
		    sed -E "s/^\s*#*\s*${ESC_SECTION}/${ESC_SECTION}/" -i "${FILE_UBLINUX_CONF}"
		    FIND_VALUE_CONFIG=$(grep -n "" "${FILE_UBLINUX_CONF}" | sed -E -n "/^[0-9]*:\s*#*\s*${ESC_SECTION}/,/^[0-9]*:\s*#*\s*\[/p")
		    # Если сектор пустой и состоит только из заголовка сектор, то пропуск, иначе последнюю строку следующего сектора вырезаем
		    [[ $(head -1 <<< ${FIND_VALUE_CONFIG}) != $(tail -1 <<< ${FIND_VALUE_CONFIG}) ]] || FIND_VALUE_CONFIG=$(sed -E '${/^[0-9]*:\s*#*\s*\[/d;}' <<< ${FIND_VALUE_CONFIG})
		# Секция не найдена, вставляем новую секцию в конец файла
		else 
		    echo -e "\n${SECTION}" >> "${FILE_UBLINUX_CONF}"
		    echo -e "${NAME_VAR}=${VALUE_VAR}" >> "${FILE_UBLINUX_CONF}"
		    SECTION_DATA=0
		fi
		# Нет выбранного блока для анализа, т.к. добавлена новая секция в конец файла. Можно убрать, оставил для симметрии
		if [[ ${SECTION_DATA} == 0 || ${FIND_VALUE_CONFIG} == "" ]]; then
		    true
		# Поиск прямое совпадение переменной, номер строки в переменную ^A=
		elif SECTION_DATA="$(egrep "^[0-9]*:${ESC_NAME_VAR}=" <<< ${FIND_VALUE_CONFIG} | tail -1 | cut -d: -f1)" && [[ -n ${SECTION_DATA} ]]; then 
		    # Прямое совпадение найдено, замена по номеру строки
		    sed -E "${SECTION_DATA}s/.*/${ESC_NAME_VAR}=${ESC_VALUE_VAR}/" -i "${FILE_UBLINUX_CONF}"
		# Поиск по косвенному совпадению, песле # коментария имя переменной ^ *#* *A=
		elif SECTION_DATA="$(egrep "^[0-9]*:\s*#*\s*${ESC_NAME_VAR}=" <<< ${FIND_VALUE_CONFIG} | tail -1 | cut -d: -f1)" && [[ -n ${SECTION_DATA} ]]; then
		    # Косвенное сопадение найдено, вставка после номера строки
		    sed -E "${SECTION_DATA}a ${ESC_NAME_VAR}=${ESC_VALUE_VAR}" -i "${FILE_UBLINUX_CONF}"
		# Поиск по косвенному совпадению, после # коментария имя переменной обрезанное до '['  ^ *#* *A[.*]=
		elif SECTION_DATA="$(egrep "^[0-9]*:\s*#*\s*${ESC_NAME_VAR%%\\[*}" <<< ${FIND_VALUE_CONFIG} | tail -1 | cut -d: -f1)" && [[ -n ${SECTION_DATA} ]]; then 
		    # Косвенное сопадение найдено, вставка после номера строки
		    sed -E "${SECTION_DATA}a ${ESC_NAME_VAR}=${ESC_VALUE_VAR}" -i "${FILE_UBLINUX_CONF}"
		# Совпадений не найдено, поиск последней строки блока
		else 
		    SECTION_DATA="$(tail -1 <<< $(egrep -v '^[0-9]*:#*$' <<< ${FIND_VALUE_CONFIG}) | cut -d: -f1)"
		    # Совпадений не найдено, вставляем в конец блока новой строкой
		    [[ -n ${SECTION_DATA} ]] && sed -E "${SECTION_DATA}a ${ESC_NAME_VAR}=${ESC_VALUE_VAR}" -i "${FILE_UBLINUX_CONF}"
		fi
		grep -q "^${ESC_NAME_VAR}=${ESC_VALUE_VAR}$" "${FILE_UBLINUX_CONF}" || return 1
	}
	set_value_system(){
	    [[ -z ${NO_SET_VALUE_SYSTEM} ]] || return 2
	    [[ -f ${FILE_CONFIG} ]] && sed -E "/^${ESC_NAME_VAR}=/d" -i "${FILE_CONFIG}" || touch "${FILE_CONFIG}"
	    echo "${NAME_VAR}=${VALUE_VAR}" >> "${FILE_CONFIG}"
	    grep -q "^${ESC_NAME_VAR}=${ESC_VALUE_VAR}$" "${FILE_CONFIG}" || return 1
	    # Mark associative array
	    DECLARE_A=$(cat "${FILE_CONFIG}" | egrep "^[A-z0-9_]*\[.*\]=.*" | sed -E "s/\[.*//" | uniq | tr "\n" " ")
	    [[ -z ${DECLARE_A} ]] || { sed "/^declare -A/d" -i "${FILE_CONFIG}"; sed -E -i "1i declare -A ${DECLARE_A}" -i "${FILE_CONFIG}"; }
	}
	ESC_NAME_VAR="$(sed 's/[^a-zA-Z0-9,._@%-]/\\&/g' <<< "${NAME_VAR}")"
	ESC_VALUE_VAR="$(sed 's/[^a-zA-Z0-9,._@%-]/\\&/g' <<< "${VALUE_VAR}")"
	#FILE_CONFIG="${PATH_UBLINUX_CURRENT}/$(tr -d '[]' <<< "${SECTION##*/}")"
	# Если базовый каталог указанный в секции соответствует системному каталогу /etc/ublinux, то продолжить
	PATH_CONFIG_SECTION=$(sed "s/\[\([a-zA-Z0-9,._@%-/]*\)\].*/\1/;s/.[^/]*$//" <<< "${SECTION}") #"
	[[ ${PATH_CONFIG_SECTION} == ${PATH_UBLINUX_CURRENT} ]] && FILE_CONFIG=$(sed "s/\[\([a-zA-Z0-9,._@%-/]*\)\].*/\1/" <<< "${SECTION}") || NO_SET_VALUE_SYSTEM=1 #"
	if [[ -z ${TARGET} ]]; then
	    set_value_global; STATUS_GLOBAL=$?
	    set_value_system; STATUS_SYSTEM=$?
	elif [[ ${TARGET} == global ]]; then
	    set_value_global; STATUS_GLOBAL=$?
	elif [[ ${TARGET} == system ]]; then
	    set_value_system; STATUS_SYSTEM=$?
	elif [[ -f ${TARGET} ]]; then
	    FILE_UBLINUX_CONF="${TARGET}"
	    set_value_global; STATUS_GLOBAL=$?
	fi
	[[ ${STATUS_GLOBAL} == 0 ]] && prompt -s "${NAME_VAR} variable added to global configuration ${FILE_UBLINUX_CONF}"
	[[ ${STATUS_GLOBAL} == 1 ]] && { prompt -e " ${NAME_VAR} variable not added to global configuration ${FILE_UBLINUX_CONF}"; STATUS=1; }
	[[ ${STATUS_SYSTEM} == 0 ]] && prompt -s "${NAME_VAR} variable added to system configuration ${FILE_CONFIG}"
	[[ ${STATUS_SYSTEM} == 1 ]] && { prompt -e " ${NAME_VAR} variable not added to system configuration ${FILE_CONFIG}"; STATUS=1; }
	[[ ${STATUS} == 1 ]] && return 1 || return 0
    }
    shift
    [[ -n "$@" ]] || prompt -eq " not found arguments !"
    for ARG in "$@"; do
	NAME_VAR=${ARG%%=*}; VALUE_VAR=${ARG#*=}
	set_value_local
	[[ -n ${SET_NOEXECUTE} ]] || select_exec
    done
}
select_exec(){
    case "${SECTION}" in
	"[/etc/ublinux/config]"|"[config]")
	    case "${NAME_VAR}" in
	        HOSTNAME)	exec_config_hostname ;;
	        *)		true ;;
	    esac
	;;
	"[/etc/ublinux/network]"|"[network]")
    	    case "${NAME_VAR}" in
		'DOMAIN')	exec_network_domain ;;
		'DOMAIN[server]') true ;;
		*)		true ;;
	    esac
	;;
	\[*\])
	    case "${NAME_VAR}" in
	        *)		true ;;
	    esac
	;;
	*) prompt -i " ${SECTION} section not found for execution" ;;
    esac
}

exec_config_hostname(){
    if [[ ${COMMAND} == 'set' ]]; then
	/usr/bin/hostnamectl set-hostname ${VALUE_VAR}
	[[ ${VALUE_VAR} != ${VALUE_VAR#*.} ]] && /usr/bin/ubconfig -q set network DOMAIN="${VALUE_VAR#*.}"
    elif [[ ${COMMAND} == 'remove' ]]; then
	/usr/bin/hostnamectl set-hostname "ublinux"
    fi
}

exec_network_domain(){
    export PARENT="${PKGNAME}"
    if [[ ${COMMAND} == 'set' ]]; then
	/usr/bin/ubdomain-client -q configure
    elif [[ ${COMMAND} == 'remove' ]]; then
	/usr/bin/ubdomain-client -q unconfigure
    fi
}

###############################
###   :::   M A I N   :::   ###
###############################

    PKGNAME=${0##*/}
    PATH_WORK=${PWD}
    set_color

    PATH_UBLINUX_CURRENT="/etc/ublinux"
#PATH_UBLINUX_CURRENT="/tmp/0/etc/ublinux"
    PATH_UBLINUX_CONF="/memory/layer-base/1"
    FILE_UBLINUX_CONF="${PATH_UBLINUX_CONF}/ublinux.ini"
#FILE_UBLINUX_CONF="/tmp/0/ublinux.ini"
    FILE_UBLINUX_DEFAULT="/usr/lib/ublinux/os-config"
#FILE_UBLINUX_DEFAULT="/tmp/0/os-config"
    
    arguments $@
    [[ ${REQUEST_ARGS} == "" ]] || prepare_section ${REQUEST_ARGS}

    if [[ ${COMMAND} == 'get' ]]; then
        get_value ${REQUEST_ARGS}
    elif [[ ${COMMAND} == 'set' ]]; then
	[[ ${REQUEST_ARGS} == "" ]] || set_value ${REQUEST_ARGS}
    elif [[ ${COMMAND} == 'remove' ]]; then
	[[ ${REQUEST_ARGS} == "" ]] || remove_value ${REQUEST_ARGS}
    fi






#_init_(){
#    export BIN_MKMOD="mkubm"
#    export mnctlPath="/etc/NetworkManager"
#    export tmpUblinuxChng="/tmp/ublinux/connections"
#
#    export excludeFiles=$(mktemp -p /dev/shm)
#    export arg_modules_path=$(realpath /memory/layer-base/*/modules | tail -n1)
#    export path_tmp="$tmpUblinuxChng/$(date '+%Y.%m.%d')-connections"
#}
#_init_
#mkdir -p $path_tmp || exit 1
#[[ -n $arg_modules_path ]] && rsync -aAXruR --exclude-from="$excludeFiles" "$mnctlPath" "$path_tmp" && cd $arg_modules_path || exit 1
#eval ${BIN_MKMOD} -l $(find $tmpUblinuxChng -maxdepth 1 -mindepth 1 -iname '*connections') -o "$(date '+%Y.%m.%d')-connections.ubm" || exit 1
#rm -rf $path_tmp || exit 1
