#!/usr/bin/env bash
#
#   Script name: upac
#   Description: Package manager UBLinux
#   GitLab: https://gitlab.ublinux.ru/
#   Author: Dmitry Razumov asmeron@ublinux.ru
#   Contributors: asmeron@ublinux.ru
#
#   Copyright (c) 2021-2023 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

# Extended pattern matching: https://www.gnu.org/software/bash/manual/html_node/Pattern-Matching.html#Pattern-Matching
#shopt -s extglob

#################################
###   :::   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(){
    [[ ${DEBUG} == yes ]] && return 0
    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; }

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

# 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}"
    cat <<EOF
${0##*/} version: ${VERSION_SCRIPT}
Copyright © 2019-2023 Dmitry Razumov
This program is free software, you can redistribute it under the terms of the GNU GPL.
EOF
}

usage(){
    cat <<EOF
Usage:  ${0##*/} [<backend>] <action> [options] <package(s)>

Backends:
  pacman	Select backend package manager pacman
 *yay		Select backend package manager yay (Default)
  pamac		Select backend package manager pamac
  ubur		Select build package from UBUR repository
  
Meta:
  help          Show this help

Options:
  -h, --help	   Show this help
      --nocolor    Show without color message
  -q, --quiet	   Quiet mode
  -V, --version	   Show package version

Use 'upac [-h --help]' with backend and action for available options

Examples:
${0##*/} ubur --help
EOF
}

usage_ubur(){
    cat <<EOF
Available actions for ubur:
  upac ubur --version     
  upac ubur --help, -h     [action]
  upac ubur search         [options] <package(s)>
D:upac ubur list           [options] <package(s)>
  upac ubur info           [options] <package(s)>
  upac ubur install        [options] <package(s)>
  upac ubur reinstall      [options] <package(s)>
  upac ubur remove         [options] [package(s)]
D:upac ubur checkupdates   [options]
D:upac ubur update,upgrade [options]
D:upac ubur clone          [options] <package(s)>
  upac ubur build          [options] [package(s)]
  upac ubur clean          [options]
EOF
}

usage_ubur_search(){
    cat <<EOF
Search for packages or files, multiple search terms can be specified

upac ubur search [options] <package(s)/file(s)>

Options:
  --quiet, -q     : only print names
EOF
}

usage_ubur_info(){
    cat <<EOF
Display package details, multiple packages can be specified

upac ubur info <package(s)>
EOF
}

usage_ubur_install(){
    cat <<EOF
Install packages from repositories, path or url

upac ubur install [options] <package(s),group(s)>

options:
  --download-only	: download all packages but do not install/upgrade anything
  --no-confirm		: bypass any and all confirmation messages
EOF
}

usage_ubur_reinstall(){
    cat <<EOF
Reinstall packages from repositories, path or url

upac ubur reinstall [options] <package(s),group(s)>

options:
  --download-only	: download all packages but do not install/upgrade anything
  --no-confirm		: bypass any and all confirmation messages
EOF
}

usage_ubur_remove(){
    cat <<EOF
Remove packages

upac ubur remove [options] [package(s),group(s)]

options:
  --no-confirm   : bypass any and all confirmation messages
EOF
}

usage_ubur_build(){
    cat <<EOF
Build packages

upac ubur build [options] [package(s),group(s)]

options:
  --no-confirm   : bypass any and all confirmation messages
EOF
}

help(){
    #usage_version
    if [[ ${BACKEND} == 'ubur' ]]; then
        if [[ -n ${UBUR_SEARCH} ]]; then 
    	    usage_ubur_search
        elif [[ -n ${UBUR_INFO} ]]; then 
    	    usage_ubur_info
        elif [[ -n ${UBUR_INSTALL} ]]; then 
    	    usage_ubur_install
        elif [[ -n ${UBUR_REINSTALL} ]]; then 
    	    usage_ubur_reinstall
        elif [[ -n ${UBUR_REMOVE} ]]; then 
    	    usage_ubur_remove
        elif [[ -n ${UBUR_BUILD} ]]; then 
    	    usage_ubur_build
        else 
    	    usage_ubur
        fi
    elif [[ ${BACKEND} == 'pacman' ]]; then
	usage_pacman
    elif [[ ${BACKEND} == 'yay' ]]; then
	usage_yay
    elif [[ ${BACKEND} == 'pamac' ]]; then
	usage_pamac
    else
    	    usage
    fi

#    [[ -n $1 ]] || usage
#    [[ $1 == "yay" ]] && usage_yay
#    [[ $1 == "pacman" ]] && usage_pacman
#    [[ $1 == "pamac" ]] && usage_pamac
    exit 0
}
usage_pacman(){
    /usr/bin/pacman --help | sed "s/pacman/upac/g"
}
usage_yay(){
    /usr/bin/yay --help | sed "s/yay/upac/g"
}
usage_pamac(){
    /usr/bin/pacman --help | sed "s/pamac/upac/g"
}


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
	    pacman | PACMAN)	BACKEND="${1,,}"; END_OF_OPT=1 ;;
	    yay | YAY)		BACKEND="${1,,}"; END_OF_OPT=1 ;;
	    pamac | PAMAC)	BACKEND="${1,,}"; END_OF_OPT=1 ;;
	    ubur | UBUR)	BACKEND="${1,,}" ;;

	    search)		[[ ${BACKEND} == 'ubur' ]] && UBUR_SEARCH=yes ;;
	    list)		[[ ${BACKEND} == 'ubur' ]] && UBUR_LIST=yes ;;
	    info)		[[ ${BACKEND} == 'ubur' ]] && UBUR_INFO=yes ;;
	    install)		[[ ${BACKEND} == 'ubur' ]] && UBUR_INSTALL=yes ;;
	    reinstall)		[[ ${BACKEND} == 'ubur' ]] && UBUR_REINSTALL=yes ;;
	    remove)		[[ ${BACKEND} == 'ubur' ]] && UBUR_REMOVE=yes ;;
	    checkupdates)	[[ ${BACKEND} == 'ubur' ]] && UBUR_CHECKUPDATES=yes ;;
	    update|upgrade)	[[ ${BACKEND} == 'ubur' ]] && UBUR_UPDATE=yes ;;
	    clone)		[[ ${BACKEND} == 'ubur' ]] && UBUR_CLONE=yes ;;
	    build)		[[ ${BACKEND} == 'ubur' ]] && UBUR_BUILD=yes ;;
	    clean)		[[ ${BACKEND} == 'ubur' ]] && UBUR_CLEAN=yes ;;
	    --download-only)	[[ ${BACKEND} == 'ubur' ]] && UBUR_INSTALL_DOWNLOAD_ONLY=yes ;;
	    --noconfirm)	[[ ${BACKEND} == 'ubur' ]] && UBUR_INSTALL_NOCONFIRM="--noconfirm" ;;
	    
	    --nocolor)	   	NOCOLOR=yes;;
	    -h | --help | help)	help ;;
	    -q | --quiet)     	QUIET=1; QUIET_SYSTEMCTL="--quiet"; 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[@]}"
    REQUEST_ARGS=("${POSITIONAL_ARGS[@]}")
    [[ -n ${BACKEND} ]] || BACKEND="yay"
    [[ -n $@ ]] && PACKAGES="$@" || help
}

_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="/tmp/upac"

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

#    log_file="${path_root}/var/log/ubpac.log"
#    touch ${log_file} && chmod 666 ${log_file} >/dev/null
    
    BIN_PACMAN="/usr/bin/pacman"
    BIN_YAY="/usr/bin/yay"
    BIN_PAMAC="/usr/bin/pamac"
    CACHE_UPAC="${HOME}/.cache/${PKGNAME}"
    install -dm755 ${CACHE_UPAC}
    GIT_UBUR_REPO="https://gitea.ublinux.ru/ubur"
    GIT_UBUR_REPO_SRCINFO="${GIT_UBUR_REPO}/srcinfo"
    PATH_UBUR_REPO_SRCINFO_LOCAL="${CACHE_UPAC}/srcinfo"
}

check_access_ubur(){
    ping -c 1 -W 1 77.88.8.8 >/dev/null 2>&1 || errorexit "Not connected to internet"
}
ubur_repos_update(){
    if [[ -d ${PATH_UBUR_REPO_SRCINFO_LOCAL} ]]; then
	cd ${PATH_UBUR_REPO_SRCINFO_LOCAL}
	git pull &>/dev/null
    else
	cd "${CACHE_UPAC}"
	git clone "${GIT_UBUR_REPO_SRCINFO}" &>/dev/null
    fi
    cd ${PATH_WORK}
}
ubur_package_search(){
    local PACKAGE=$1
    [[ -f ${PATH_UBUR_REPO_SRCINFO_LOCAL}/${PACKAGE} ]] || return 1
}
ubur_package_search_infocompact(){
    local PACKAGE=$1
    cat "${PATH_UBUR_REPO_SRCINFO_LOCAL}/${PACKAGE}" | grep -E "pkgname =|pkgdesc =" | sed "s/pkgname = //g;s/pkgdesc = //g"
}
ubur_package_info(){
    local PACKAGE=$1
    cat "${PATH_UBUR_REPO_SRCINFO_LOCAL}/${PACKAGE}"
}
ubur_package_download(){
    local PACKAGE=$1
    if [[ -d ${CACHE_UPAC}/${PACKAGE} ]]; then
	cd "${CACHE_UPAC}/${PACKAGE}"
	git pull &>/dev/null
    else
	cd "${CACHE_UPAC}"
	git clone "${GIT_UBUR_REPO}/${PACKAGE}" &>/dev/null
    fi
    cd ${PATH_WORK}
}
ubur_package_prebuild(){
    local PACKAGE=$1
    # Если в текущем каталоге откуда вызывается ubur находятся исходные файлы для сборки, то они копируются с заменой в каталог сборки ~/.cache/ubur/<package>/
    while IFS=" = " read -u4 NULL SOURCE; do
	[[ -f ${SOURCE##*/} ]] && cp -af ${SOURCE##*/} ${CACHE_UPAC}/${PACKAGE}/
    done 4< <(cat "${PATH_UBUR_REPO_SRCINFO_LOCAL}/${PACKAGE}" | grep "source = ")
    cd ${PATH_WORK}
}
ubur_package_build(){
    local PACKAGE=$1
    cd "${CACHE_UPAC}/${PACKAGE}"
    makepkg ${UBUR_INSTALL_NOCONFIRM} -cCfrd
    cd ${PATH_WORK}
}
ubur_package_install(){
    #ls -lv "${CACHE_UPAC}/${PACKAGE}"/*.pkg.* 2>/dev/null || prompt -w "Package ${PACKAGE} not installed."
    sudo -E ${BIN_PACMAN} -U ${UBUR_INSTALL_NOCONFIRM} ${CACHE_UPAC}/${PACKAGE}/*.pkg.* || prompt -w "Package ${PACKAGE} not installed."
}

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

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

    REQUEST_ARGS=()
    arguments "$@"
    set -- "${REQUEST_ARGS[@]}"

    [[ -n ${NOCOLOR} ]] || set_color
    _init_

    if [[ ${BACKEND} == 'ubur' ]]; then
	[[ -n ${UBUR_CLEAN} ]] && rm -rdf ${CACHE_UPAC} && prompt -sq "Cache cleaned."
	ubur_repos_update
    	while read -u3 PACKAGE; do
	    [[ -n ${UBUR_REINSTALL} ]] && rm -rdf "${CACHE_UPAC}/${PACKAGE}" && prompt -sq "Source package cleaned, reinstall."
	    if [[ -n ${UBUR_SEARCH} ]]; then
		ubur_package_search ${PACKAGE} || { prompt -w "Package ${PACKAGE} not found."; continue; }
		ubur_package_search_infocompact ${PACKAGE}
	    elif [[ -n ${UBUR_LIST} ]]; then
		true
	    elif [[ -n ${UBUR_INFO} ]]; then
		ubur_package_search ${PACKAGE} || { prompt -w "Package ${PACKAGE} not found."; continue; }
		ubur_package_info ${PACKAGE}
	    elif [[ -n ${UBUR_INSTALL} || -n ${UBUR_REINSTALL} ]]; then
		ubur_package_search ${PACKAGE} || { prompt -w "Package ${PACKAGE} not found."; continue; }
		ubur_package_download ${PACKAGE}
		[[ -z ${UBUR_INSTALL_DOWNLOAD_ONLY} ]] || { prompt -i "Package ${PACKAGE} download to ${CACHE_UPAC}/${PACKAGE}"; continue; }
		ubur_package_prebuild ${PACKAGE}
		ubur_package_build ${PACKAGE}
		[[ -z ${UBUR_BUILD} ]] || { prompt -i "Package ${PACKAGE} build to ${CACHE_UPAC}/${PACKAGE}/"; continue; }
		ubur_package_install ${PACKAGE}
	    elif [[ -n ${UBUR_REMOVE} ]]; then
		sudo -E ${BIN_PACMAN} -R ${UBUR_INSTALL_NOCONFIRM} ${PACKAGE}
	    fi
	done 3< <(tr ' ' '\n' <<< ${PACKAGES})	
    elif [[ ${BACKEND} == 'pacman' ]]; then
	[[ -z $1 ]] && usage_pacman || ${BIN_PACMAN} "$@"
    elif [[ ${BACKEND} == 'yay' ]]; then
	[[ -z $1 ]] && usage_yay || ${BIN_YAY} "$@"
    elif [[ ${BACKEND} == 'pamac' ]]; then
	[[ -z $1 ]] && usage_pamac || ${BIN_PAMAC} "$@"
    fi
