#!/bin/bash
#
# prepare-linux.sh - Linux Initial Configuration Script
#
# Purpose: Perform basic preparatory configuration when first using Linux to enable further configurations
# Features:
#   1. Detect or specify distribution type (Arch/Debian/Fedora)
#   2. Install common packages
#   3. Set environment variables and hostname
#   4. Configure Git
#   5. Change default Shell to zsh
#

VERSION="1.5.2"
SCRIPT_NAME="$(basename "$0")"
SCRIPT_FILE="$(readlink -f "$0")"
SCRIPT_FOLDER="$(cd "$(dirname "$0")" && readlink -f "$(pwd)")"

if ! command -v whiptail &> /dev/null; then
    echo -e "\033[31mERROR: whiptail: command no found\033[0m"
    exit 1
fi

# Parse command line arguments
DISTRO=""
SHOW_HELP=false
SHOW_VERSION=false

while [[ $# -gt 0 ]]; do
    case $1 in
        -h|--help)
            SHOW_HELP=true
            shift
            ;;
        -v|--version)
            SHOW_VERSION=true
            shift
            ;;
        --arch)
            DISTRO="Arch based"
            shift
            ;;
        --debian)
            DISTRO="Debian based"
            shift
            ;;
        --fedora)
            DISTRO="Fedora based"
            shift
            ;;
        *)
            echo "Unknown parameter: $1"
            SHOW_HELP=true
            shift
            ;;
    esac
done

# Display version information
if [ "$SHOW_VERSION" = true ]; then
    echo "$SCRIPT_NAME version $VERSION"
    exit 0
fi

# Display help information
if [ "$SHOW_HELP" = true ]; then
    echo "Usage: $SCRIPT_NAME [options]"
    echo ""
    echo "Options:"
    echo "  -h, --help     Display this help information"
    echo "  -v, --version  Display version information"
    echo "  --arch         Specify as Arch-based distribution"
    echo "  --debian       Specify as Debian-based distribution"
    echo "  --fedora       Specify as Fedora-based distribution"
    echo ""
    echo "If no distribution is specified, the script will let the user choose through an interactive menu."
    exit 0
fi

TMP_PKGS_TUI=("git" "ncdu" "duf" "zsh" "zip" "unzip" "unrar" "p7zip" "dtrx" "python3" "ranger" "mc" "rsync" "figlet" "htop" "nano" "neovim" "tree" "screen" "ffmpeg" "axel" "qalc" "curl" "wget" "tmux" "screen" "whiptail" "newt" "libnewt" "ssh" "openssh" "eza" "exa" "python3-pip" "python-pip" "rar" "p7zip-full" "shellcheck" "rename" "perl-rename" "avahi" "avahi-utils" "ffmpeg" "imagemagick" "net-tools")
TMP_PKGS_TUI_SORT=$(printf "%s\n" "${TMP_PKGS_TUI[@]}" | sort)
readarray -t PKGS_TUI <<< "$TMP_PKGS_TUI_SORT"

TMP_PKGS_GUI=("vlc" "smplayer" "gparted" "gnome-disk-utility" "papirus-icon-theme" "alacritty" "dolphin" "konsole" "arandr" "conky" "conky-all" "flatpak" "gimp")
TMP_PKGS_GUI_SORT=$(printf "%s\n" "${TMP_PKGS_GUI[@]}" | sort)
readarray -t PKGS_GUI <<< "$TMP_PKGS_GUI_SORT"

ENVBASE="$(cat <<-EOF
GITAUTO="$HOME/Documents/git"
SYSCFG="$HOME/Documents/git/gitlab.pi/gem/system-config"
SHOW_FIGLET_HOSTNAME="1"
EOF
)"

HOSTSBASE="$(cat <<-EOF
192.168.1.10    pve.me
192.168.1.9     cube.me gitlab.pi
EOF
)"

SSHCONFIG="$(cat <<-EOF
Host *
    ServerAliveInterval 30
EOF
)"

APT_NOBLE_MIRROR="$(cat <<-EOF
deb https://mirrors.aliyun.com/ubuntu/ noble main restricted universe multiverse
deb https://mirrors.aliyun.com/ubuntu/ noble-updates main restricted universe multiverse
deb https://mirrors.aliyun.com/ubuntu/ noble-backports main restricted universe multiverse
deb https://mirrors.aliyun.com/ubuntu/ noble-security main restricted universe multiverse
EOF
)"

LOCALE_EN="$(cat <<-EOF
LANGUAGE=en_US.UTF-8
LC_ALL=en_US.UTF-8
LC_TIME=en_US.UTF-8
LC_MONETARY=en_US.UTF-8
LC_ADDRESS=en_US.UTF-8
LC_TELEPHONE=en_US.UTF-8
LC_NAME=en_US.UTF-8
LC_MEASUREMENT=en_US.UTF-8
LC_IDENTIFICATION=en_US.UTF-8
LC_NUMERIC=en_US.UTF-8
LC_PAPER=en_US.UTF-8
LANG=en_US.UTF-8
EOF
)"
LOCALE_CN="$(cat <<-EOF
LANGUAGE=zh_CN.UTF-8
LC_ALL=zh_CN.UTF-8
LC_TIME=zh_CN.UTF-8
LC_MONETARY=zh_CN.UTF-8
LC_ADDRESS=zh_CN.UTF-8
LC_TELEPHONE=zh_CN.UTF-8
LC_NAME=zh_CN.UTF-8
LC_MEASUREMENT=zh_CN.UTF-8
LC_IDENTIFICATION=zh_CN.UTF-8
LC_NUMERIC=zh_CN.UTF-8
LC_PAPER=zh_CN.UTF-8
LANG=zh_CN.UTF-8
EOF
)"
SUPPORTED_ZHHANT="$(cat <<-EOF
zh_HK.UTF-8 UTF-8
zh_TW.UTF-8 UTF-8
EOF
)"
ETC_LOCALEGEN="$(cat <<-EOF
# This file lists locales that you wish to have built. You can find a list
# of valid supported locales at /usr/share/i18n/SUPPORTED, and you can add
# user defined locales to /usr/local/share/i18n/SUPPORTED. If you change
# this file, you need to rerun locale-gen.

# C.UTF-8 UTF-8
en_US.UTF-8 UTF-8
zh_CN.UTF-8 UTF-8
EOF
)"

TMUXCONF="$(cat <<-EOF
# remap prefix from 'C-b' to 'C-a'
#unbind C-b
#set-option -g prefix C-a
#bind-key C-a send-prefix

# Reload config file (change file location to your the tmux.conf you want to use)
bind r source-file ~/.tmux.conf \; display " Reloaded!"
bind -n M-r source-file ~/.tmux.conf \; display " Reloaded!"
bind e split-window -h "nvim ~/.tmux.conf"
bind -n M-e split-window -h "nvim ~/.tmux.conf"

# kill pane
bind -n M-x confirm kill-pane

# Split panes using h and v
bind -n M-h split-window -h
bind -n M-v split-window -v
bind h split-window -h
bind v split-window -v
unbind '"'
unbind %

# Switch panes using Alt-arrow without prefix
bind -n M-Up select-pane -U
bind -n M-Down select-pane -D
bind -n M-Left select-pane -L
bind -n M-Right select-pane -R

# Resizing
bind -r C-Up resize-pane -U 15
bind -r C-Down resize-pane -D 15
bind -r C-Left resize-pane -L 15
bind -r C-Right resize-pane -R 15

# Swap pane
bind > swap-pane -D       # swap current pane with the next one
bind < swap-pane -U       # swap current pane with the previous one

# Pane movement to window
bind j command-prompt -p "Join pane from:"  "join-pane -s '%%'"
bind s command-prompt -p "Send pane to:"  "join-pane -t '%%'"

# Alt j/k key to switch windows 
bind -n M-j previous-window
bind -n M-k next-window

# window management
unbind n
unbind w
bind w new-window -c "#{pane_current_path}"
bind n command-prompt "rename-window '%%'"
bind k confirm kill-window

# Keeping Current Path
bind c new-window -c "#{pane_current_path}"

# Enable mouse control (clickable windows, panes, resizable panes)
set -g mouse on

# Increase History
set-option -g history-limit 100000

# don't rename windows automatically
set-option -g allow-rename off

# Numbering Windows and Panddes
set -g base-index 1
setw -g pane-base-index 1
#set -g renumber-windows on

# Swapping Windows
#bind -r [ swap-window -d -t -1
#bind -r ] swap-window -d -t +1

# DESIGN TWEAKS

# don't do anything when a 'bell' rings
#set -g visual-activity off
#set -g visual-bell off
#set -g visual-silence off
#setw -g monitor-activity off
#set -g bell-action none

# clock mode
setw -g clock-mode-colour yellow

# copy mode
setw -g mode-style 'fg=black bg=red bold'

# panes
set -g pane-border-style 'fg=white'
set -g pane-active-border-style 'fg=green'

# statusbar
set -g status-position bottom
set -g status-justify left
#set -g status-style 'fg=black bg=green'
set -g status-style 'fg=white bg=black'

set -g status-left-style 'fg=black bg=green'
set -g status-left ' tmux #H.#S '
set -g status-left-length 100

set -g status-right-style 'fg=black bg=yellow'
set -g status-right ' %Y-%m-%d %H:%M '
set -g status-right-length 100

setw -g window-status-current-style 'fg=black bg=red'
setw -g window-status-current-format ' #I.#W #F '

setw -g window-status-style 'fg=red bg=black'
setw -g window-status-format ' #I.#W #F '

setw -g window-status-bell-style 'fg=yellow bg=red bold'

# messages
set -g message-style 'fg=black bg=green bold'
EOF
)"

HTOPRC="$(cat <<-EOF
# Beware! This file is rewritten by htop when settings are changed in the interface.
# The parser is also very primitive, and not human-friendly.
#fields=0 48 17 18 38 39 40 2 46 47 49 1
#fields=0 46 47 48 49 1
fields=0 46 47 48 1
sort_key=46
sort_direction=-1
tree_sort_key=0
tree_sort_direction=1
hide_kernel_threads=1
hide_userland_threads=0
shadow_other_users=0
show_thread_names=0
show_program_path=1
highlight_base_name=0
highlight_megabytes=1
highlight_threads=1
highlight_changes=0
highlight_changes_delay_secs=5
find_comm_in_cmdline=1
strip_exe_from_cmdline=1
show_merged_command=0
tree_view=0
tree_view_always_by_pid=0
header_margin=1
detailed_cpu_time=0
cpu_count_from_one=0
show_cpu_usage=1
show_cpu_frequency=0
show_cpu_temperature=0
degree_fahrenheit=0
update_process_names=0
account_guest_in_cpu_meter=0
color_scheme=0
enable_mouse=1
delay=15
left_meters=LeftCPUs Memory Swap 
left_meter_modes=1 1 1 
right_meters=RightCPUs Tasks LoadAverage Uptime 
right_meter_modes=1 2 2 2
EOF
)"

NANORC="$(cat <<-EOF
## Make 'nextword' (Ctrl+Right) and 'chopwordright' (Ctrl+Delete)
## stop at word ends instead of at beginnings.

## Enabling Line Numbers
set linenumbers

## Enabling Auto Indentation
set autoindent

## Enable Smooth Scrolling
#set smooth

## Enable Word Wrapping
set softwrap

## When soft line wrapping is enabled, make it wrap lines at blanks
## (tabs and spaces) instead of always at the edge of the screen.
set atblanks

## Setting Tab Size
set tabsize 4

## Automatically Converting Tabs to Spaces
set tabstospaces

## Do not use the line below the title bar, leaving it entirely blank.
set emptyline

## Display a "scrollbar" on the righthand side of the edit window.
set indicator

## Enable mouse support, if available for your system.  When enabled,
## mouse clicks can be used to place the cursor, set the mark (with a
## double click), and execute shortcuts.  The mouse will work in the X
## Window System, and on the console when gpm is running.
# set mouse

## Save a changed buffer automatically on exit; don't prompt.
# set saveonexit

## Put the cursor on the highlighted item in the file browser, and show
## the cursor in the help viewer; useful for people who use a braille
## display and people with poor vision.
# set showcursor

## Use the end of the title bar for some state flags: I = auto-indenting,
## M = mark, L = hard-wrapping long lines, R = recording, S = soft-wrapping.
set stateflags

## Allow nano to be suspended (with ^Z by default).
#set suspendable

## Changing Colors
## e.g.: set titlecolor foregroundColorCode,backgroundColorCode
## white, black, blue, green, red, cyan, yellow, magenta
# set titlecolor bold,lightwhite,blue
# set statuscolor bold,lightwhite,green
# set errorcolor bold,lightwhite,red
# set selectedcolor lightwhite,magenta
# set stripecolor ,yellow
# set scrollercolor cyan
# set numbercolor cyan
# set keycolor cyan
# set functioncolor green

## In root's .nanorc you might want to use:
# set titlecolor bold,lightwhite,magenta
# set statuscolor bold,lightwhite,magenta
# set errorcolor bold,lightwhite,red
# set selectedcolor lightwhite,cyan
# set stripecolor ,yellow
# set scrollercolor magenta
# set numbercolor magenta
# set keycolor lightmagenta
# set functioncolor magenta

## ## Syntax coloring ##
## For all details, see 'man nanorc', section SYNTAX HIGHLIGHTING.

## To include most of the existing syntax definitions, you can do:
include "/usr/share/nano/*.nanorc"

## Or you can select just the ones you need.  For example:
# include "/usr/share/nano/html.nanorc"
# include "/usr/share/nano/python.nanorc"
# include "/usr/share/nano/sh.nanorc"

## In /usr/share/nano/extra/ you can find some syntaxes that are
## specific for certain distros or for some less common languages.

## ## Key bindings ##
## For all details, see 'man nanorc', section REBINDING KEYS.

## The <Ctrl+Delete> keystroke deletes the word to the right of the cursor.
## On some terminals the <Ctrl+Backspace> keystroke produces ^H, which is
## the ASCII character for backspace, so it is bound by default to the
## backspace function.  The <Backspace> key itself produces a different
## keycode, which is hard-bound to the backspace function.  So, if you
## normally use <Backspace> for backspacing and not ^H, you can make
## <Ctrl+Backspace> delete the word to the left of the cursor with:
# bind ^H chopwordleft main

## If you would like nano to have keybindings that are more "usual",
## such as ^O for Open, ^F for Find, ^H for Help, and ^Q for Quit,
## then uncomment these:
#bind ^Q exit all
#bind ^S savefile main
#bind ^W writeout main
#bind ^O insert main
#bind ^H help all
#bind ^H exit help
#bind ^F whereis all
#bind ^G findnext all
#bind ^F whereis all
#bind ^G findnext all
#bind ^B wherewas all
#bind ^D findprevious all
#bind ^R replace main
#bind M-X flipnewbuffer all
#bind ^X cut all
#bind ^C copy main
#bind ^V paste all
#bind ^P location main
#bind ^A mark main
#unbind ^K main
#unbind ^U all
#unbind ^N main
#unbind ^Y all
#unbind M-J main
#unbind M-T main
#bind ^T gotoline main
#bind ^T gotodir browser
#bind ^Y speller main
#bind M-U undo main
#bind M-R redo main
#bind ^U undo main
#bind ^E redo main
#set multibuffer
EOF
)"

function _press_any() {
    PA_PROMPT="\033[1;33m>>> Press any key to continue...\n\033[0m"
    read -n1 -s -r -p "$(echo -e "$PA_PROMPT")" key
}

function user_permission() {
    local addgroups=("root" "sudo" "wheel")
    for g in "${addgroups[@]}"; do
        # Check if group exists
        if ! getent group "$g" > /dev/null 2>&1; then
            continue
        fi
        
        echo -e "\033[1;33m=> \033[1;32mAdding $USER to group ${g}\033[0m"
        if command -v usermod &> /dev/null; then
            sudo usermod -aG "$g" "$USER"
        elif command -v adduser &> /dev/null; then
            sudo adduser "$g" "$USER"
        elif command -v useradd &> /dev/null; then
            sudo useradd "$g" "$USER"
        fi
    done
    if (whiptail --title "[$SCRIPT_NAME] /etc/sudoer" --yes-button "Edit" --no-button "Skip" --yesno "Add line '$USER    ALL = (ALL) NOPASSWD: ALL'" 15 60) then
        sudo cp /etc/sudoers /etc/sudoers.bak
        grep -qxF "$USER    ALL = (ALL) NOPASSWD: ALL" /etc/sudoers || sudo echo "$USER    ALL = (ALL) NOPASSWD: ALL" | sudo tee -a /etc/sudoers
        sudo visudo
    fi
}

function ssh_config() {
    cfgdir="$HOME/.ssh"
    if [ ! -d "$cfgdir" ]; then
        mkdir -p "$cfgdir"
    fi
    if [ ! -f "$cfgdir/config" ]; then
        touch "$cfgdir/config"
    fi
    echo -e "\033[1;33m=> \033[1;32mConfiguring $cfgdir/config\033[0m"
    echo "$SSHCONFIG" | tee --append "$cfgdir/config"
}

function locale_setup() {
    USE_LANGUAGE=$(whiptail --title "[$SCRIPT_NAME] Language" --menu "Choose the language you use:" 15 60 4 "en_US.UTF-8" "" "zh_CN.UTF-8" "" 3>&1 1>&2 2>&3)
    exitstatus=$?
    if [ $exitstatus = 0 ]; then
        if (whiptail --title "[$SCRIPT_NAME] Locale" --yes-button "Yes" --no-button "No" --yesno "Change the content of file /etc/default/locale to language '${USE_LANGUAGE}', and remove all languages but 'en_US.UTF-8 UTF-8' in file /var/lib/locales/supported.d/en" 15 60) then
            echo -e "\033[1;33m=> \033[1;32m/etc/default/locale\033[0m"
            if [ "${USE_LANGUAGE}" = "en_US.UTF-8" ]; then
                echo "${LOCALE_EN}" | sudo tee /etc/default/locale
            elif [ "${USE_LANGUAGE}" = "zh_CN.UTF-8" ]; then
                echo "${LOCALE_CN}" | sudo tee /etc/default/locale
            fi

            if [ ! -d /var/lib/locales/supported.d/ ]; then
                sudo mkdir -p /var/lib/locales/supported.d/
            fi
            if [ "${USE_LANGUAGE}" = "zh_CN.UTF-8" ]; then
                if [ ! -f /var/lib/locales/supported.d/zh-han ]; then
                    sudo touch /var/lib/locales/supported.d/zh-han
                fi
                echo -e "\033[1;33m=> \033[1;32m/var/lib/locales/supported.d/zh-han\033[0m"
                echo "zh_CN.UTF-8 UTF-8" | sudo tee /var/lib/locales/supported.d/zh-han

                if [ ! -f /var/lib/locales/supported.d/zh-hans ]; then
                    sudo touch /var/lib/locales/supported.d/zh-hans
                fi
                echo -e "\033[1;33m=> \033[1;32m/var/lib/locales/supported.d/zh-hans\033[0m"
                echo "zh_CN.UTF-8 UTF-8" | sudo tee /var/lib/locales/supported.d/zh-hans

                if [ ! -f /var/lib/locales/supported.d/zh-hant ]; then
                    sudo touch /var/lib/locales/supported.d/zh-hant
                fi
                echo -e "\033[1;33m=> \033[1;32m/var/lib/locales/supported.d/zh-hant\033[0m"
                echo "${SUPPORTED_ZHHANT}" | sudo tee /var/lib/locales/supported.d/zh-hant
            fi
            if [ ! -f /var/lib/locales/supported.d/en ]; then
                sudo touch /var/lib/locales/supported.d/en
            fi
            echo -e "\033[1;33m=> \033[1;32m/var/lib/locales/supported.d/en\033[0m"
            echo "en_US.UTF-8 UTF-8" | sudo tee /var/lib/locales/supported.d/en
            
            echo -e "\033[1;33m=> \033[1;32m/etc/locale.gen\033[0m"
            echo "$ETC_LOCALEGEN" | sudo tee /etc/locale.gen

            echo -e "\033[1;33m=> \033[1;32msudo locale-gen\033[0m"
            sudo locale-gen
        fi
    fi
}

function pkg_mirror_echo() {
    local distro="$1"
    if [[ -n "$distro" ]]; then
        if [ "$distro" = "Debian based" ]; then
            echo -e "\033[32mListing package manager mirror for distro \033[0m$distro\033[0m"
            echo "$APT_NOBLE_MIRROR"
            whiptail --title "[$SCRIPT_NAME]" --msgbox "$APT_NOBLE_MIRROR" 18 78
        fi
        return 0
    else
        echo -e "\033[31mERROR: Failed to update packages for distro $distro\033[0m"
        return 1
    fi
}

function pkg_update() {
    local distro="$1"
    if [[ -n "$distro" ]]; then
        echo -e "\033[32mUpdating package(s) for distro \033[0m$distro\033[0m"
        if [ "$distro" = "Arch based" ]; then
            sudo pacman -Syyu --noconfirm
            return $?
        elif [ "$distro" = "Debian based" ]; then
            sudo apt update && sudo apt upgrade -y
            return $?
        elif [ "$distro" = "Fedora based" ]; then
            sudo dnf update -y
            return $?
        fi
    else
        echo -e "\033[31mERROR: Failed to update packages for distro $distro\033[0m"
        return 1
    fi
}

function pkg_install() {
    local distro="$1"
    shift
    local pkgs=("$@")
    if [[ -n "$distro" && ${#pkgs[@]} -gt 0 ]]; then
        for p in "${pkgs[@]}"; do
            echo -e "\033[32mInstalling package \033[33m$p\033[32m for distro \033[0m$distro\033[0m"
            if [ "$distro" = "Arch based" ]; then
                sudo pacman -S --noconfirm --needed "$p"
            elif [ "$distro" = "Debian based" ]; then
                sudo apt install -y "$p"
            elif [ "$distro" = "Fedora based" ]; then
                sudo dnf install --skip-unavailable -y "$p"
            fi
        done
    else
        echo -e "\033[31mERROR: Failed to install packages for distro $distro\033[0m"
        return 1
    fi
}

function apply_tmuxconf() {
    local config_tgt="$HOME/.tmux.conf"
    echo -e "\033[1;32m=>\033[1;33m Applying configurations to $config_tgt\033[0m"
    echo "$TMUXCONF" | tee "$config_tgt"
}

function apply_htoprc() {
    local htop_config_dir="$HOME/.config/htop"
    if [ ! -d "$htop_config_dir" ]; then
        mkdir -p "$htop_config_dir"
    fi
    echo -e "\033[1;32m=>\033[1;33m Applying configurations to $htop_config_dir/htoprc\033[0m"
    echo "$HTOPRC" | tee "$htop_config_dir/htoprc"
}

function apply_nanorc() {
    echo -e "\033[1;32m=>\033[1;33m Applying configurations to /etc/nanorc\033[0m"
    echo "$NANORC" | sudo tee /etc/nanorc
}

#####№######################№№##

# Check if running in non-interactive mode (piped execution)
if [ ! -t 0 ]; then
    echo -e "\033[31mERROR: This script must be run in an interactive shell, not through piping.\033[0m"
    echo -e "\033[31mPlease download the script and execute it directly:\033[0m"
    echo -e "\033[31m  curl -fsSL https://hotodogo.com/sh/prepare-linux.sh -o prepare-linux.sh\033[0m"
    echo -e "\033[31m  chmod +x prepare-linux.sh\033[0m"
    echo -e "\033[31m  ./prepare-linux.sh\033[0m"
    exit 1
fi

# If no distribution is specified via parameters, select through an interactive menu
if [ -z "$DISTRO" ]; then
    DISTRO=$(whiptail --title "[$SCRIPT_NAME] Distro" --menu "Choose the Linux Distro to continue:" 18 60 4 \
        "Arch based" "" \
        "Debian based" "" \
        "Fedora based" "" \
        3>&1 1>&2 2>&3)
    exitstatus=$?
    if [ $exitstatus != 0 ]; then
        echo "User cancelled operation"
        exit 1
    fi
else
    echo -e "\033[32mDistribution specified:\033[0m $DISTRO"
fi

echo -e "\033[32mDistro\033[0m: $DISTRO"

if (whiptail --title "[$SCRIPT_NAME] User Permission" --yes-button "Continue" --no-button "Skip" --yesno "Do you want to config user permission?" 15 60) then
    user_permission
    _press_any
fi

if (whiptail --title "[$SCRIPT_NAME] Locale" --yes-button "Continue" --no-button "Skip" --yesno "Do you want to config locale?" 15 60) then
    ## Locale
    echo -e "\033[1;33mConfiguring locale...\033[0m"
    locale_setup
    _press_any
fi

if pkg_mirror_echo "$DISTRO"; then
    _press_any
fi

if (whiptail --title "[$SCRIPT_NAME] Packages" --yes-button "Continue" --no-button "Skip" --yesno "Do you want to udpate and install packages?" 15 60) then
    ## INSTALL PACKAGES
    echo -e "\033[1;33mUpdating Packages...\033[0m"
    pkg_update "$DISTRO"
    echo -e "\033[1;33mInstalling Packages...\033[0m"
    for pkg in "${PKGS_TUI[@]}"; do
        if ! pkg_install "$DISTRO" "$pkg"; then
            _press_any
        fi
    done
    _press_any
    if (whiptail --title "[$SCRIPT_NAME] GUI Packages" --yes-button "Continue" --no-button "Skip" --yesno "Do you want to install GUI packages?" 15 60) then
        ## INSTALL PACKAGES
        echo -e "\033[1;33mInstalling GUI Packages...\033[0m"
        for pkg in "${PKGS_GUI[@]}"; do
            if ! pkg_install "$DISTRO" "$pkg"; then
                _press_any
            fi
        done
        _press_any
    fi
fi

if (whiptail --title "[$SCRIPT_NAME] ENV Setup" --yes-button "Continue" --no-button "Skip" --yesno "Do you want to setup the environment (hosts, hostname, etc...)?" 15 60) then
    ## ENV SETUP
    echo -e "\033[1;33mSetting-up Environment...\033[0m"
    # /etc/environment 
    grep -qxF "$ENVBASE" /etc/environment || echo "$ENVBASE" | sudo tee --append /etc/environment
    # /etc/hostname
    NEW_HOSTNAME="$(whiptail --title "[$SCRIPT_NAME] Hostname" --inputbox "Hostname for your computer" 18 60 "$(hostname)" 3>&1 1>&2 2>&3)"
    if [ -n "$NEW_HOSTNAME" ]; then
        echo "$NEW_HOSTNAME" | sudo tee /etc/hostname
    fi
    # /etc/hosts
    grep -qxF "$HOSTSBASE" /etc/hosts || echo "$HOSTSBASE" | sudo tee --append /etc/hosts
    # python3
    if [ -e /usr/local/bin/python3 ]; then
        sudo rm -f /usr/local/bin/python3
    fi
    sudo ln -s /usr/bin/python3 /usr/local/bin/
    # ssh
    ssh_config
    # Dirs
    MAKEPATH=("$HOME/Documents/git/gitlab.pi")
    for mp in "${MAKEPATH[@]}"; do
        if [ ! -e "$mp" ]; then
            echo -e "\033[1;32mMaking directory $\033[0m$mp\033[0m"
            if ! mkdir -p "$mp" 2>/dev/null; then
                sudo mkdir -p "$mp"
            fi
        fi
    done
    # tmux
    apply_tmuxconf
    # htop
    apply_htoprc
    # nanorc
    apply_nanorc
    _press_any
fi

if (whiptail --title "[$SCRIPT_NAME] SHELL" --yes-button "Continue" --no-button "Skip" --yesno "Do you want to change your SHELL to zsh?" 15 60) then
    ## CHANGE SHELL
    zsh_path="$(which zsh | tr ' ' '\n' | head -n 1)"
    if [ -n "$zsh_path" ]; then
        echo -e "\033[1;33mChanging SHELL to $zsh_path...\033[0m"
        chsh -s "$zsh_path" && sudo chsh -s "$zsh_path"
    fi
    _press_any
fi

if (whiptail --title "[$SCRIPT_NAME] Git" --yes-button "Continue" --no-button "Skip" --yesno "Do you want to config git?" 15 60) then
    ## GIT CONFIG
    echo -e "\033[1;33mConfiguring Git...\033[0m"
    G_UNAME="$(whiptail --title "[$SCRIPT_NAME] Git User" --inputbox "" 15 60 "Ezra" 3>&1 1>&2 2>&3)"
    if [ -n "$G_UNAME" ]; then
        git config --global user.name "$G_UNAME"
    fi
    G_EMAIL="$(whiptail --title "[$SCRIPT_NAME] Git E-mail" --inputbox "" 15 60 "ezra@hotodogo.com" 3>&1 1>&2 2>&3)"
    if [ -n "$G_EMAIL" ]; then
        git config --global user.email "$G_EMAIL"
        git config --global pull.rebase false
        git config --global credential.helper store
        git config --global core.quotepath false
        git config --global http.postBuffer 524288000
    fi
    G_EDITOR=$(whiptail --title "[$SCRIPT_NAME] Git Editor" --menu "Choose the editor you use:" 16 60 8 \
        "nano" "" \
        "micro" "" \
        "nvim" "" \
        "code" "" \
        "emacs" "" \
        "mousepad" "" \
        "gedit" "" \
        3>&1 1>&2 2>&3)
    exitstatus_git=$?
    if [ $exitstatus_git = 0 ]; then
        git config --global core.editor "$G_EDITOR"
    fi
    _press_any
fi

echo -e "\033[1;33mDone...\033[0m"
