#!/bin/bash
SOURCE="$0"
source /usr/lib/elive-tools/functions
EL_REPORTS="1"
. gettext.sh
TEXTDOMAIN="elive-tools"
export TEXTDOMAIN


# include sbin in our PATH since its needed sometimes, and there's nothing wrong by using it!
if [[ "$PATH" != *"/usr/sbin"* ]] ; then
    # needed for: laptop-detect
    export PATH="${PATH}:/usr/local/sbin:/usr/sbin:/sbin"
fi


# TODO: since we install our own drivers, can we remove the package libgl1-mesa-dri ? (because it wastes 100 MB from installation), will need some betatestings

NVIDIA_LOGFILE="/var/log/nvidia-privative-drivers-install.log"

#===  FUNCTION  ================================================================
#          NAME:  log_machine_status
#   DESCRIPTION:  logs a machine-readable message to stdout and the logfile
#===============================================================================
log_machine_status(){
    echo "$@" | tee -a "$NVIDIA_LOGFILE"
}

#===  FUNCTION  ================================================================
#          NAME:  usage
#   DESCRIPTION:  Shows the usage help, don't exit
#===============================================================================
usage(){
    #
    # if -a : should return true in case of installed or false if install failed
    #           already installed? already running?
    # if -i : will ask the user which version to install (suggesting the best option to use)
    # if -f : only for debug purposes, but should install successfully too
    #
    echo -e "Usage: $(basename $BASH_SOURCE) [options]"
    echo -e "  -a: auto install"
    echo -e "  -d: detect only (return true or false if we have nvidia or not)"
    echo -e "  -l: live mode (pre-ask if want to install, more interactive)"
    echo -e "  -f: force install (if no nvidia cards are found)"
    echo -e "  -q: quiet mode"
    echo -e "  -h: help usage"
    echo -e "  -c: check only (tell which version of the drivers we need)"
    echo -e "  -t: test driver only (if the driver is correctly installed and working)"
    echo -e "  -m: model (version of drivers) to use"
    echo -e "      - like:  current, tesla-418, tesla-450, tesla-460, legacy-390xx legacy-340xx, legacy-304xx, legacy-173xx, legacy-96xx"
    #echo -e "  -s: simulate mode (simulate that you have the specified model hardware" # not needed, we have enough hardware with nvidia to test on, and real tests are better
    echo -e "  -x: extra features to install, like cuda, optix, icd, etc"
    echo -e "  -u: uninstall drivers"
    echo -e "  -s: safe mode: do not remove modules"
    echo -e "  -v: verbose mode"
}

#===  FUNCTION  ================================================================
#          NAME:  rmmod_nvidia
#   DESCRIPTION:  removes any nvidia module
#===============================================================================
rmmod_nvidia(){
    local module nvidia_modules

    if ((is_safe_mode)) ; then
        return 0
    fi

    if [[ -n "$_NVIDIA_VERSION" ]] ; then
        nvidia_modules="nvidia-legacy-${_NVIDIA_VERSION} nvidia-tesla-${_NVIDIA_VERSION}"
    fi
    # unload
    for module in nvidia nvidia-current ${_NVIDIA_MODULE} ${nvidia_modules} nvidia-drm nvidia-current-drm nvidia-modeset nvidia-current-modeset nvidia-uvm nvidia-current-uvm nvidia-peermem nvidia-current-peermem
    do
        rmmod "$module" 2>/dev/null || true
    done

    # force
    if lsmod | grep -qs "^nvidia" ; then
        if ((is_mode_force)) ; then
            for module in nvidia nvidia-current ${_NVIDIA_MODULE} ${nvidia_modules} nvidia-drm nvidia-current-drm nvidia-modeset nvidia-current-modeset nvidia-uvm nvidia-current-uvm nvidia-peermem nvidia-current-peermem
            do
                rmmod -f "$module" 2>/dev/null || true
            done
        fi
    fi

    # check
    if lsmod | grep -qs "^nvidia" ; then
        el_info "unable to unload nvidia modules:\n$(lsmod | grep -i "^nvidia" )\n$( rmmod -f nvidia nvidia-drm nvidia-modeset 2>&1 )"
        return 1
    fi
}

#===  FUNCTION  ================================================================
#          NAME:  check_driver
#   DESCRIPTION:  check if is already installed
#    PARAMETERS:  -
#       RETURNS:  true | false
#===============================================================================
check_driver(){
    # we should have enough with only this file, if is not installed it should have been removed!
    if ((is_xorg_template_wanted)) ; then
        if ! [[ -s "/etc/X11/xorg.conf.d/20-nvidia.conf" ]] ; then
            return 1
        fi
    fi
    # but wee need also to make sure that is 'correctly' installed
    if ! load_driver ; then
        return 1
    fi
}
#===  FUNCTION  ================================================================
#          NAME:  load_driver
#   DESCRIPTION:  loads the nvidia module
#    PARAMETERS:  -
#       RETURNS:  -
#===============================================================================
load_driver(){
    # pre {{{
    el_debug
    local i nvidia_modules

    # }}}

    # load driver
    if which nvidia-modprobe 1>/dev/null 2>&1 ; then
        nvidia-modprobe
        nvidia-modprobe -m
        nvidia-modprobe -l
        nvidia-modprobe -s
    fi

    # always load the drm module otherwise it will not work
    nvidia_modules="$( find "/lib/modules/$(uname -r)/updates" -type f -iname '*nvidia*ko*' | psort --  -p "nvidia-legacy-${_NVIDIA_VERSION}" -p "${_NVIDIA_VERSION}" | grep -vE "(uvm|modeset|peermem)" | grep "nvidia.*drm" )"
    for i in $nvidia_modules
    do
        i="$( basename "${i%%.ko*}" )"
        el_info "running: modprobe $i"

        if modprobe "$i" ; then
            break
        fi
    done
    unset nvidia_modules

    if ! lsmod | grep -qs "^nvidia" ; then
        nvidia_modules="$( find "/lib/modules/$(uname -r)/updates" -type f -iname '*nvidia*ko*' | psort --  -p "nvidia-legacy-${_NVIDIA_VERSION}" -p "${_NVIDIA_VERSION}" | grep -vE "(uvm|modeset|drm|peermem)" )"

        if [[ -n "$nvidia_modules" ]] ; then
            for i in $nvidia_modules
            do
                i="$( basename "${i%%.ko*}" )"
                _NVIDIA_MODULE="${i}"
                el_info "running: modprobe $_NVIDIA_MODULE"

                if modprobe "$_NVIDIA_MODULE" ; then
                    break
                fi
            done
        fi
    fi

    if [[ -z "$_NVIDIA_MODULE" ]] ; then
        _NVIDIA_MODULE="$( lsmod | grep "^nvidia" | awk '{print $1}' | tail -1 )"
    fi

    # check
    if [[ "$( echo "$nvidia_modules" | grep -c . )" -gt 1 ]] ; then
        el_warning "more than one nvidia module found: \n$nvidia_modules"
    fi

    # simulate that it worked
    if ((is_mode_simulate)) ; then
        return 0
    fi

    if lsmod | grep -qs "^nvidia" ; then
        return 0
    else
        #el_error "unable to load nvidia module: \ndmesg:\n$(dmesg | tail -n 6)\nmodules found:\n$nvidia_modules"
        #sleep 4
        return 1
    fi
}
#===  FUNCTION  ================================================================
#          NAME:  check_hardware
#   DESCRIPTION:  check the hardware if has or not the graphic card
#    PARAMETERS:  -
#       RETURNS:  -
#===============================================================================
check_hardware(){
    # pre {{{
    el_debug
    #el_security_function_loop || return 0

    # we don't need to check if we have the hardware if we want to uninstall the driver
    if ((is_mode_uninstall)) ; then
        return 0
    fi

    # }}}
    # detect if we have the hardware with nvidia {{{
    # pci-id with nvidia on first graphic card
    #_DEVICE="$( lspci -mn | awk '/03(00|80|02)/ { print $3$4 }' | sed -e 's|"||g' | tr '[a-z]' '[A-Z]' | grep -E '^(10DE|12D2)' | head -n1)"
    _DEVICE="$( lspci -mn | awk '$2 ~ /^"?03/ { print $3$4 }' | tr -d ' "' | tr '[a-z]' '[A-Z]' | grep -E '^(10DE|12D2)' | head -n1)"

    if echo "${_DEVICE}" | grep -qs -E '^(10DE|12D2)' ; then
        el_debug "nvidia card found on pci-id"
        is_nvidia_card_found=1
    fi

    if ((is_mode_simulate)) ; then
        is_nvidia_card_found=1
        # we also want/need to force the install because there's no real hardware here
        is_mode_force=1
    fi

    # check if hardware has nvidia
    # Seems like a more reliable way than using VGA for the detect is: lspci -nn | grep '\[03'
    if lspci | grep -qsiE "\W+(VGA|3D|2D|Display)\W+.*\W+nvidia\W+" ; then
        el_debug "nvidia card found in lspci"
        is_nvidia_card_found=1
    fi

    # force or exit?
    if ! ((is_nvidia_card_found)) ; then
        if ((is_mode_force)) ; then
            el_info "Force mode in a machine where is not detected nvidia card"
            is_nvidia_card_found=1
            log_machine_status "NVIDIA_CARD_DETECTED: FORCED"
        else
            el_info "No nvidia graphic cards found on this machine"
            log_machine_status "NVIDIA_CARD_DETECTED: FALSE"
            exit 1
        fi
    else
        log_machine_status "NVIDIA_CARD_DETECTED: TRUE (${_DEVICE:-unknown})"
    fi

    # in mode check we dont want to install, just to check
    if ((is_mode_detect)) ; then
        el_info "Nvidia card detected"
        exit 0
    fi

    # - detect if we have the hardware with nvidia }}}
    # detect optimus cards {{{
    if [[ "$( lspci | grep -E "\W+(VGA|3D|2D|Display)\W+" | wc -l )" -gt "1" ]] && ! [[ "$( lspci | grep -E "\W+(VGA|3D|2D|Display)\W+" | grep -iE "\W+(VGA|3D|2D|Display)\W+.*\W+nvidia\W+" | wc -l )" -gt "1" ]] ; then
        is_multiple_cards=1
        if laptop-detect ; then
            is_optimus=1
            touch /tmp/.nvidia_optimus
            log_machine_status "NVIDIA_OPTIMUS_DETECTED: TRUE"
        fi
    fi
    # }}}
}
#===  FUNCTION  ================================================================
#          NAME:  detect_driver_version
#   DESCRIPTION:  detect or ask which version of the driver to use
#    PARAMETERS:  -
#       RETURNS:  -
#===============================================================================
detect_driver_version(){
    # pre {{{
    local prev_dir file
    prev_dir="$(pwd)"

    el_debug

    if el_check_variables "driver_version" 1>/dev/null 2>&1 ; then
        el_debug "Selected ${driver_version} version of drivers to use"
        _NVIDIA_VERSION="$driver_version"
        echo "$_NVIDIA_VERSION" > /tmp/.nvidia-version
        #_NVIDIA_MODULE="nvidia" # should be always this one in all the versions, or maybe not?
        return 0
    fi

    if ! el_check_variables "_DEVICE" 1>/dev/null 2>&1 ; then
        # pci-id with nvidia on first graphic card
        #_DEVICE="$( lspci -mn | awk '/03(00|80|02)/ { print $3$4 }' | sed -e 's|"||g' | tr '[a-z]' '[A-Z]' | grep -E '^(10DE|12D2)' | head -n1)"
        _DEVICE="$( lspci -mn | awk '/ "03/ { print $3$4 }' | sed -e 's|"||g' | tr '[a-z]' '[A-Z]' | grep -E '^(10DE|12D2)' | head -n1)"
    fi

    if ! el_check_variables "_DEVICE" 1>/dev/null 2>&1 ; then
        if ((is_mode_force)) ; then
            if [[ -z "$driver_version" ]] ; then
                NOREPORTS=1 el_warning "Going to install the nvidia drivers but you didn't say which version, assuming 'current' then..."
                driver_version="current"
            fi
        else
            el_error "You have no Nvidia graphic cards, use -f if you want to force the install, lspci -mn:\n$(lspci -mn)\n$( lspci | grep -E "\W+(VGA|3D|2D|Display)\W+" )"
        fi
    fi

    # mark it
    if [[ -n "$driver_version" ]] ; then
        _NVIDIA_VERSION="$driver_version"
        echo "$_NVIDIA_VERSION" > /tmp/.nvidia-version
    fi

    # }}}

    el_info "Reading Packages..."

    # try to search for ID's {{{
    #
    # first on your system installed id's
    for _NVIDIA_IDS in /usr/lib/nvidia/current/nvidia.ids $(ls /usr/lib/nvidia/legacy*/nvidia.ids 2>/dev/null | sort -V -r ) $(ls /usr/lib/nvidia/tesla*/nvidia.ids 2>/dev/null | sort -V -r )
    do
        if [ -e "${_NVIDIA_IDS}" ]
        then
            if grep -qs "${_DEVICE}" ${_NVIDIA_IDS}
            then
                _NVIDIA_VERSION="$(basename $(dirname ${_NVIDIA_IDS}))"
                echo "$_NVIDIA_VERSION" > /tmp/.nvidia-version
                _NVIDIA_MODULE="$(echo nvidia-${_NVIDIA_VERSION} | sed -e 's|-current$||')"

                break
            fi
        fi
    done

    # if nothing found, search in already-downloaded packages (if we are in live mode we should have them already there)
    if [[ -z "$_NVIDIA_VERSION" ]] ; then
        # installed ones
        if ls /var/cache/apt/archives/xserver-xorg-video-nvidia*deb 1>/dev/null 2>&1 ; then
            # unpack downloaded ones for scan
            cd /var/cache/apt/archives/
            el_debug "Not ID's found on installed packages, unpacking not-installed ones..."
        else
            if ((is_mode_live)) ; then
                el_debug "You are in mode_live, skipping the pre-download of packages for this mode..."
            else
                # download from urls for scan
                el_info "Not ID's found on installed packages, downloading them..."
                if el_verify_internet fast ; then
                    mkdir -p /var/tmp/tmp-nvidia
                    cd /var/tmp/tmp-nvidia

                    for packagename in $( LC_ALL=C apt-cache search xserver-xorg-video-nvidia | grep -v "nouveau" | awk '{print $1}' | sort -V -r | tr '\n' ' ' )
                    do
                        url_repository="$( LC_ALL=C apt-cache madison ${packagename} | tr ' ' '\n' | grep http | head -1 )"
                        while read -ru 3 line
                        do
                            #url_package_dir="${url_repository%/}/${line%/*}/"
                            if [[ -x "$(which wget)" ]] ; then
                                el_debug "downloading: ${line##*/}"
                                wget -q "${url_repository%/}/${line}"
                            fi
                        done 3<<< "$( LC_ALL=C apt-cache show "${packagename}" 2>/dev/null | grep -F "Filename:" | sed -e 's|^Filename: ||g' | sort -u )"
                    done
                else
                    NOREPORTS=1 el_error "no connection to internet found"
                fi
            fi
        fi
        # for any of the places where we are (cd), let's scan the opened files:
        for file in xserver-xorg-video-nvidia*deb
        do
            # Unpack packages to get the ID's !
            dpkg -x "$file" ./tmp-nvidia/
            # optimize space, remove unneeded files:
            find tmp-nvidia -type f -iname '*_nvidia\.so*' -delete
            find tmp-nvidia -type f -iname '*nvidia_drv\.so*' -delete
            find tmp-nvidia -type f -iname '*libglx\.so*' -delete
            find tmp-nvidia -type f -iname '*\.so' -delete
            rm -rf tmp-nvidia/usr/share
        done

        # get the version
        for _NVIDIA_IDS in ./tmp-nvidia/usr/lib/nvidia/current/nvidia.ids $(ls ./tmp-nvidia/usr/lib/nvidia/legacy*/nvidia.ids 2>/dev/null | sort -V -r ) $(ls ./tmp-nvidia/usr/lib/nvidia/tesla*/nvidia.ids 2>/dev/null | sort -V -r )
        do
            if [ -e "${_NVIDIA_IDS}" ]
            then
                if grep -qs "${_DEVICE}" ${_NVIDIA_IDS}
                then
                    el_info "Compatible with version: $(basename $(dirname ${_NVIDIA_IDS}))"
                    if [[ -z "$_NVIDIA_VERSION" ]] ; then
                        _NVIDIA_VERSION="$(basename $(dirname ${_NVIDIA_IDS}))"
                        echo "$_NVIDIA_VERSION" > /tmp/.nvidia-version
                        _NVIDIA_MODULE="$(echo nvidia-${_NVIDIA_VERSION} | sed -e 's|-current$||')"
                    fi
                fi
            fi
        done
        rm -rf tmp-nvidia 2>/dev/null

        cd "$prev_dir"
        rm -rf /var/cache/apt/archives/tmp-nvidia 2>/dev/null
        rm -rf /var/tmp/tmp-nvidia 2>/dev/null
    fi

    # }}}
    # show result found {{{
    if [[ -n "$_NVIDIA_VERSION" ]] ; then
        el_info "Version of Nvidia for your machines is: ${_NVIDIA_VERSION}"
        el_info "Module to load for your nvidia card is: ${_NVIDIA_MODULE}"
    else
        # if we have nothing found we should tell the user what to do
        if ((is_mode_check)) ; then
            el_info "Seems like we cannot detect the package of nvidia that you need for your graphic card, things that you can do:"
            el_info " * Update your packages list (apt-get update) and try again"


            el_info " * Maybe your version of nvidia is not yet included in Elive, but it should be backported soon"
            el_info "Run the command nvidia-detect to see what it says"
        else
            if ((is_mode_auto)) ; then
                el_error "Unable to autodetect the version that you need, exiting"
                # if we cannot detect we cannot continue!
                exit 1
            fi
        fi
    fi

    # if we only  want to check, we don't need to do anything more here, just exit
    if [[ -n "$_NVIDIA_VERSION" ]] ; then
        if ((is_mode_check)) ; then
            echo -e "The Nvidia drivers for your machine is: $_NVIDIA_VERSION"
            exit
        # UPDATE: deprecated, included in the next dialog
        # else
        #     # suggest the version to use
        #     if ! ((is_mode_auto)) ; then
        #         local message_version_suggest
        #         message_version_suggest="$( printf "$( eval_gettext "The probable version of the Nvidia driver that you need is '%s'. If it doesn't work, try with a different version." )" "$_NVIDIA_VERSION" )"
        #
        #         dialog --timeout 80 --clear --colors --backtitle "Elive Systems: Use Ctrl-L to redraw, Enter to confirm" \
        #             --title "Suggested Version" \
        #             --msgbox "$message_version_suggest" \
        #             0 0
        #     fi
        fi

        # preselect to not ask later
        # Update: never preselect the driver for the user, let him pick which one wants to use, sometimes a version works better than another and also this can be a problem with the fallback "current" version
        #if ! ((is_mode_simulate)) ; then
            #nvidia_version_live_preselected="$_NVIDIA_VERSION"
        #fi

    else
        NOREPORTS=1 el_warning "Unable to detect the version of nvidia you need, assuming 'current'"
        sleep 1

        if ! ((is_mode_auto)) ; then
            local message_version_suggest
            message_version_suggest="$( printf "$( eval_gettext "The version of the driver that you need for your Nvidia card has not been detected. This can happen when your card is not supported by the available drivers. In any case, we suggest that you find the right version through trial and error." )" )"

            dialog --timeout 80 --clear --colors --backtitle "Elive Systems: Use Ctrl-L to redraw, Enter to confirm" \
                --title "Unable to detect driver version needed" \
                --msgbox "$message_version_suggest" \
                0 0
        fi
    fi

    if [[ -z "$_NVIDIA_VERSION" ]] ; then
        NOREPORTS=1 el_warning "Unable to detect the version of nvidia you need, assuming 'current'"
        _NVIDIA_VERSION="current"
        echo "$_NVIDIA_VERSION" > /tmp/.nvidia-version
    fi

    # examples of results:
    #_NVIDIA_VERSION=current
    #_NVIDIA_MODULE=nvidia
    #_NVIDIA_VERSION=legacy-304xx
    #_NVIDIA_MODULE=nvidia-legacy-304xx


    cd "$prev_dir"

    # - show result found }}}
}
#===  FUNCTION  ================================================================
#          NAME:  interactive_ask_privative
#   DESCRIPTION:  ask to the user if wants to install the privative driver or not
#    PARAMETERS:  -
#       RETURNS:  -
#===============================================================================
interactive_ask_privative(){
    # pre {{{
    local ret
    el_debug


    # }}}
    # ask if want to install the privative one or the free {{{
    if echo "${_CMDLINE}" | LC_ALL=C grep -qsE "onlyfree" ; then
        echo -e "Using free-drivers only because 'onlyfree' is set in your boot parameters" 1>&2
        ret=1
    else

        if ((is_mode_live)) ; then

            # warn if low memory that the process can fail!
            memory="$( cat /proc/meminfo | grep -i Memtotal | tail -1 | awk '{print $2}' )"
            if [[ "${memory}" -lt "640000" ]] && ! ((is_mode_auto)) ; then

                local message_low_memory
                message_low_memory="$( printf "$( eval_gettext "Your computer has low RAM, so installing large packages in live mode might not work, try installing Elive on your hard drive and then install the packages, once Elive is installed, boot with 'init 1' to skip the graphical system and run the command '%s -a' to start the installation again." )" "$(basename $0)" )"

                dialog --timeout 80 --clear --colors --backtitle "Elive Systems: Use Ctrl-L to redraw, Enter to confirm" \
                    --title "Low Memory Computer" \
                    --msgbox "$message_low_memory" \
                    0 0
            fi

            # don't ask if mode auto, assume yes
            if ((is_mode_auto)) || ((is_mode_already_run)) ; then
                ret=0
            else
                local message_title
                message_title="$( printf "$( eval_gettext "Nvidia Graphics Card" )" "" )"
                local message_message
                message_message="$( printf "$( eval_gettext "Do you want to install Nvidia's closed-source graphical drivers? Some computers require them, while others perform better with the open driver. We recommend trying all the available options to determine which one is more suitable for your computer." )" )"
                local message_extra
                message_extra="$( printf "$( eval_gettext "Select 'no' if you want to use the open-source drivers." )" "" )"


                dialog --timeout 60 --clear --colors --backtitle "Elive Systems: Use Ctrl-L to redraw, Enter to confirm" \
                    --title "$message_title" \
                    --yesno "$message_message\n\n${message_extra}" \
                    0 0
                                    ret="$?"
            fi
        else
            # we are running this command manually so we don't want to ask if we want to do what we want to do :P
            ret="0"
        fi
    fi

    if ! ((is_mode_auto)) ; then
        case "$ret" in
            0|255|123|124) # yes, timeout, cancel
                if ((is_mode_live)) ; then
                    log_progress_msg "Installing proprietary Nvidia drivers"

                    # checks if we can install it {{{
                    if ! echo "${_CMDLINE}" | LC_ALL=C grep -qsE "blacklist=nouveau" && lsmod | grep -qs '^nouveau' ; then
                        local message_reboot_and_select_privative_1
                        local message_reboot_and_select_privative_2
                        message_reboot_and_select_privative_1="$( printf "$( eval_gettext "To install the proprietary drivers, you must reboot and select the proprietary option from the boot menu." )" "" )"
                        message_reboot_and_select_privative_2="$( printf "$( eval_gettext "Or you can boot with any option but you need to press the TAB key (or \"E\" from UEFI boot) to append the next boot parameter:" )\nmodprobe.blacklist=nouveau" "" )"

                        dialog --timeout 80 --clear --colors --backtitle "Elive Systems: Use Ctrl-L to redraw, Enter to confirm" \
                            --title "$( eval_gettext "A reboot is needed using a different option" )" \
                            --msgbox "${message_reboot_and_select_privative_1}\n\n${message_reboot_and_select_privative_2}" \
                            0 0

                        if ((is_mode_live)) ; then
                            dialog --timeout 180 --clear --colors --backtitle "Elive Systems: Use Ctrl-L to redraw, TAB to select, Enter to confirm" \
                                --title "Reboot now?" \
                                --yesno "$( eval_gettext "Do you want to reboot now to select the proprietary drivers? If you select no, we will continue using the open driver." )" \
                                0 0
                            ret="$?"

                            case "$ret" in
                                0|255|124|123) # yes, timeout, cancel
                                    ( reboot & )
                                    sleep 4
                                    exit
                                    ;;
                                1) # no
                                    true
                                    ;;
                            esac
                        fi

                    fi
                    # }}}
                    # remember that this is not stable {{{
                    local message_remember
                    message_remember="$( printf "$( eval_gettext "If the installation of this driver fails, we suggest trying a different version of the driver or a different kernel version, which you can select in the first boot menu. If the installation works but the driver does not function correctly or makes your computer unstable, you can try using the open-source drivers, which sometimes work better. If you continue to experience issues, please use our forums to ask for assistance. Trying a different version of Elive may also be helpful." )" "" )"


                    dialog --timeout 60 --clear --colors --backtitle "Elive Systems: Use Ctrl-L to redraw, Enter to confirm" \
                        --title "If the install fails..." \
                        --msgbox "$message_remember" \
                        0 0

                    # - remember that this is not stable }}}
                fi
                ;;
            1) # no
                if ((is_mode_live)) ; then

                    if echo "${_CMDLINE}" | LC_ALL=C grep -qsE "blacklist=nouveau" ; then
                        # tell the user to reboot with onlyfree option
                        local message_onlyfree
                        if ((is_wheezy)) ; then
                            message_onlyfree="$( printf "$( eval_gettext "Reboot and select the 'only free-drivers' boot option. For compatibility reasons the nouveau module is blacklisted on boot, so either reboot in this mode or remove that parameter from the boot options." )" "" )"
                        else
                            message_onlyfree="$( printf "$( eval_gettext "Reboot and select the normal, non-NVIDIA option, or simply remove the parameter '%s' from the boot options by pressing the Tab key (or \"e\" on UEFI boot and then F10 to boot). Booting without this parameter is necessary to enable the open-source drivers." )" "modprobe.blacklist=nouveau" )"
                        fi

                        dialog --timeout 80 --clear --colors --backtitle "Elive Systems: Use Ctrl-L to redraw, Enter to confirm" \
                            --title "Free-Driver Option" \
                            --msgbox "$message_onlyfree" \
                            0 0
                    else
                        log_progress_msg "Using the free-driver..."
                    fi
                fi

                # not needed to do anything, just exit
                el_debug "We don't need to do anything, continue using nouveau..."
                exit
                ;;
        esac
    fi

    # - ask if want to install the privative one or the free }}}
}
#===  FUNCTION  ================================================================
#          NAME:  interactive_ask_driver_version
#   DESCRIPTION:  ask to the user which driver to install
#    PARAMETERS:  -
#       RETURNS:  -
#===============================================================================
interactive_ask_driver_version(){
    # pre {{{
    local line entry _is_preselection_set _id _desc ret
    el_debug

    # }}}
    # List available versions and ask in a dialog {{{

    local message_select_driver
    message_select_driver="$( printf "$( eval_gettext "Select the version of the driver your graphics card needs." )" "" )"
    local message_select_driver_detected
    message_select_driver_detected="$( printf "$( eval_gettext "For your computer, it is most likely '\Zb%s\ZB'" )" "$_NVIDIA_VERSION" )"


    if ! ((is_mode_auto)) && ! ((is_mode_version_set)) ; then

        if [[ -n "$nvidia_version_live_preselected" ]] ; then
           ret="$nvidia_version_live_preselected"
           unset nvidia_version_live_preselected

        else
            while read -ru 3 line
            do
                if [[ "${line}" = "xserver-xorg-video-nvidia" ]] ; then
                    continue
                fi

                _id="${line#xserver-xorg-video-nvidia}"
                _id="${_id#-}"

                if [[ -z "$_id" ]] ; then
                    _id="unknown"
                fi

                case $_id in
                    *tesla-*)
                        _desc="$( printf "$( eval_gettext "High-Performance Computing drivers" )" )"
                        ;;
                    *nvidia|current)
                        _desc="$( printf "$( eval_gettext "Last drivers for the newest cards" )" )"
                        # show the specific version, its always good to know "what" exactly is considered the last version to know if its really supported on your hardware or not
                        _desc="$_desc ($( LC_ALL=C apt-cache show xserver-xorg-video-nvidia | grep "^Version: " | awk '{print $2}' | sort -V | tail -1 | sed -e 's|-.*$||g' ))"
                        ;;
                    *legacy-470xx)
                        _desc="$( printf "$( eval_gettext "Previous drivers for Kepler cards" )" )"
                        ;;
                    *legacy-390xx)
                        _desc="$( printf "$( eval_gettext "Previous drivers for recent cards" )" )"
                        ;;
                    *legacy-340xx)
                        _desc="$( printf "$( eval_gettext "Previous drivers for recent cards (older)" )" )"
                        ;;
                    *legacy-304xx)
                        _desc="$( printf "$( eval_gettext "Previous drivers for recent cards (more older)" )" )"
                        ;;
                    *legacy-173xx)
                        _desc="$( printf "$( eval_gettext "Drivers for old cards" )" )"
                        ;;
                    *legacy-96xx)
                        _desc="$( printf "$( eval_gettext "Drivers for oldest cards" )" )"
                        ;;
                    *legacy-71xx)
                        _desc="$( printf "$( eval_gettext "Drivers for prehistoric devices" )" )"
                        ;;
                    *legacy*)
                        _desc="$( printf "$( eval_gettext "Old drivers" )" )"
                        ;;
                    *)
                        _desc="$( printf "$( eval_gettext "Unknown version" )" )"
                        ;;
                esac

                if [[ "${_NVIDIA_VERSION}" = "$_id" ]] ; then
                    if ((_is_preselection_set)) ; then
                        echo -e "'$_id' '$_desc'"
                        _is_preselection_set=1
                    else
                        echo -e "'$_id' '$_desc'"
                    fi
                else
                    echo -e "'$_id' '$_desc'"
                fi

            done 3<<< "$( { echo "current" ;  LC_ALL=C apt-cache search xserver-xorg-video-nvidia | grep -v "nouveau" | awk '{print $1}' | sort -V -r | psort -- -p "current" -p "legacy" -p "tesla"  ; } )" \
                | xargs dialog --timeout 240 --clear --colors --backtitle "Elive Systems: Use Ctrl-L to redraw, Enter to confirm" --menu "$message_select_driver\n${message_select_driver_detected}" 0 0 0  2>"/tmp/.$(basename $0)-ret"

            ret="$?"

            # timeout, so select the default one
            if echo "$ret" | grep -qsE "^124$" ; then
                echo "$_NVIDIA_VERSION" > "/tmp/.$(basename $0)-ret"
            fi

            # user canceled? uninstall and exit
            if echo "$ret" | grep -qsE "^(1|123|255|125)$" || grep -qsE "^(1|123|255|125)$" "/tmp/.$(basename $0)-ret" ; then
                uninstall_driver
                try_again
                exit
            fi

            # get result
            ret="$( cat "/tmp/.$(basename $0)-ret" | head -1 )"
            rm -f "/tmp/.$(basename $0)-ret"

            # remove extra leading blank chars
            read -r ret <<< "$ret"

            # if users's cancel, we have no results at all
            if [[ -z "$ret" ]] ; then
                #uninstall_driver
                try_again
                exit
            fi
        fi

        log_progress_msg "Using the '$ret' nvidia drivers version"

        # add a pause in case we selected a different than the expected one
        if [[ "${ret}" != "$_NVIDIA_VERSION" ]] ; then
            sleep 2
        fi

        # update / force the version to use
        if [[ -n "$ret" ]] ; then
            _NVIDIA_VERSION="$ret"
            echo "$_NVIDIA_VERSION" > /tmp/.nvidia-version
        fi
    fi


    # - List available versions and ask in a dialog }}}
    # select packages to install depending on which version we selected {{{
    case $_NVIDIA_VERSION in
        current)
            if apt-cache show "nvidia-driver" 1>/dev/null 2>&1 ; then
                _NVIDIA_PACKAGES="nvidia-driver $_NVIDIA_PACKAGES"
            else
                if apt-cache show "nvidia-driver-libs" 1>/dev/null 2>&1 ; then
                    _NVIDIA_PACKAGES="nvidia-driver-libs $_NVIDIA_PACKAGES"
                fi
            fi
            if apt-cache show "nvidia-settings" 1>/dev/null 2>&1 ; then
                _NVIDIA_PACKAGES="nvidia-settings $_NVIDIA_PACKAGES"
            fi

            # possibly needed firmwares
            if apt-cache show "firmware-nvidia-graphics" 1>/dev/null 2>&1 ; then
                _NVIDIA_PACKAGES="firmware-nvidia-graphics $_NVIDIA_PACKAGES"
            fi
            if apt-cache show "firmware-nvidia-gsp" 1>/dev/null 2>&1 ; then
                _NVIDIA_PACKAGES="firmware-nvidia-gsp $_NVIDIA_PACKAGES"
            fi


            # extra packages
            if ((is_extra_packages_wanted)) ; then
                if apt-cache show "nvidia-cuda-toolkit" 1>/dev/null 2>&1 ; then
                    _NVIDIA_PACKAGES="nvidia-cuda-toolkit $_NVIDIA_PACKAGES"
                fi
                # OpenCL support for things like Blender, Davinci Resolve, etc
                if apt-cache show "nvidia-opencl-icd" 1>/dev/null 2>&1 ; then
                    _NVIDIA_PACKAGES="nvidia-opencl-icd $_NVIDIA_PACKAGES"
                fi
                # pretty small and needed, cuda support but requires opencl-icd too
                if apt-cache show "libnvcuvid1" 1>/dev/null 2>&1 ; then
                    _NVIDIA_PACKAGES="libnvcuvid1 $_NVIDIA_PACKAGES"
                fi
                # OptiX ray tracing
                if apt-cache show "libnvoptix1" 1>/dev/null 2>&1 ; then
                    _NVIDIA_PACKAGES="libnvoptix1 $_NVIDIA_PACKAGES"
                fi
                # video encoding, pretty small
                if apt-cache show "libnvidia-encode1" 1>/dev/null 2>&1 ; then
                    _NVIDIA_PACKAGES="libnvidia-encode1 $_NVIDIA_PACKAGES"
                fi
                # vdpau video driver, pretty required
                if apt-cache show "nvidia-vdpau-driver" 1>/dev/null 2>&1 ; then
                    _NVIDIA_PACKAGES="nvidia-vdpau-driver $_NVIDIA_PACKAGES"
                fi
                # arch based packages:
                if [[ "$( el_architecture host )" = "i386" ]] ; then
                    if apt-cache show "libcuda1-i386" 1>/dev/null 2>&1 ; then
                        _NVIDIA_PACKAGES="libcuda1-i386 $_NVIDIA_PACKAGES"
                    fi
                else
                    if apt-cache show "libcuda1" 1>/dev/null 2>&1 ; then
                        _NVIDIA_PACKAGES="libcuda1 $_NVIDIA_PACKAGES"
                    fi
                fi
            fi

            # needed for things that requires extra features like Davinci Resolve:, requires 25/108 extra MB installed
            if [[ "$RAM_TOTAL_SIZE_mb" -gt 3700 ]] || ((is_persistence)) || ! ((is_live)) ; then
                # opencl support
                if apt-cache show "nvidia-opencl-icd" 1>/dev/null 2>&1 ; then
                    _NVIDIA_PACKAGES="nvidia-opencl-icd $_NVIDIA_PACKAGES"
                fi
                # pretty small and needed, cuda support but requires opencl-icd too
                if apt-cache show "libnvcuvid1" 1>/dev/null 2>&1 ; then
                    _NVIDIA_PACKAGES="libnvcuvid1 $_NVIDIA_PACKAGES"
                fi
                # OptiX ray tracing
                if apt-cache show "libnvoptix1" 1>/dev/null 2>&1 ; then
                    _NVIDIA_PACKAGES="libnvoptix1 $_NVIDIA_PACKAGES"
                fi
                # video encoding, pretty small
                if apt-cache show "libnvidia-encode1" 1>/dev/null 2>&1 ; then
                    _NVIDIA_PACKAGES="libnvidia-encode1 $_NVIDIA_PACKAGES"
                fi
            fi


            # i386 no longer supports this version, it fallsback to the version 390
            if apt-cache show nvidia-driver | grep -qs "^Depends: .*nvidia-legacy-" ; then
                clear ; echo
                NOREPORTS=1 el_error "Version 'current' no longer supported for this architecture"
                sleep 4

                local message_warning_no_longer_supported message_warning_no_longer_supported_fallback
                message_warning_no_longer_supported="$( printf "$( eval_gettext "This version of Nvidia drivers is no longer supported by this architecture; if you need this version of the driver, you should use the 64-bit version of Elive instead." )" )"
                message_warning_no_longer_supported_fallback="$( printf "$( eval_gettext "The installation will proceed using another version instead:" )" "" ) $(apt-cache show nvidia-driver | grep "Depends: " | sed -e 's|^Depends: ||g' | sort -u )"

                dialog --timeout 280 --clear --colors --backtitle "Elive Systems: Use Ctrl-L to redraw, Enter to confirm" \
                    --title "WARNING" \
                    --msgbox "$message_warning_no_longer_supported" \
                    0 0

                dialog --timeout 280 --clear --colors --backtitle "Elive Systems: Use Ctrl-L to redraw, Enter to confirm" \
                    --title "WARNING" \
                    --msgbox "$message_warning_no_longer_supported_fallback" \
                    0 0
            fi
            ;;
        legacy-71xx)

            # NOTE: The 71xx legacy drivers don't support Xorg Xserver newer than 1.4 which was
            # shipped with Debian 5.0 (lenny).

            # the name of the packages are different for this one
            _NVIDIA_PACKAGES="nvidia-glx-legacy-71xx"

            # tell the user to use an older kernel
            #if dpkg --compare-versions "$(uname -r)" ge "3.16" ; then
            #local message_too_much_new_kernel
            ##message_too_much_new_kernel="$( printf "$( eva
            ##l_gettext "Your selected kernel is very new for this version of nvidia, we will try in any of the cases to compile the module for this kernel but if it fails to run your graphical system just use an older version of the kernel, like the one given by default debian. We tested that it compiles with the version 3.2" )" "" )"

            #dialog --timeout 80 --clear --colors --backtitle "Elive Systems: Use Ctrl-L to redraw, Enter to confirm" \
                #--title "Too much new kernel" \
                #--msgbox "$message_too_much_new_kernel" \
                #0 0
            #fi


            ;;
        *)
            # Other driver versions
            if LC_ALL=C apt-cache search "nvidia-settings-$_NVIDIA_VERSION" 2>/dev/null | awk '{print $1}' | grep -qs "nvidia-settings-$_NVIDIA_VERSION" ; then
                _NVIDIA_PACKAGES="nvidia-$_NVIDIA_VERSION-driver nvidia-settings-$_NVIDIA_VERSION"
            else
                _NVIDIA_PACKAGES="nvidia-$_NVIDIA_VERSION-driver"
            fi

            # possibly needed firmwares
            if apt-cache show "firmware-nvidia-${_NVIDIA_VERSION}-graphics" 1>/dev/null 2>&1 ; then
                _NVIDIA_PACKAGES="firmware-nvidia-${_NVIDIA_VERSION}-graphics $_NVIDIA_PACKAGES"
            fi
            if apt-cache show "firmware-nvidia-${_NVIDIA_VERSION}-gsp" 1>/dev/null 2>&1 ; then
                _NVIDIA_PACKAGES="firmware-nvidia-${_NVIDIA_VERSION}-gsp $_NVIDIA_PACKAGES"
            fi

            # extra packages
            if ((is_extra_packages_wanted)) ; then
                if apt-cache show "nvidia-cuda-toolkit" 1>/dev/null 2>&1 ; then
                    _NVIDIA_PACKAGES="nvidia-cuda-toolkit $_NVIDIA_PACKAGES"
                fi
                # OpenCL support for things like Blender, Davinci Resolve, etc
                if apt-cache show "nvidia-$_NVIDIA_VERSION-opencl-icd" 1>/dev/null 2>&1 ; then
                    _NVIDIA_PACKAGES="nvidia-$_NVIDIA_VERSION-opencl-icd $_NVIDIA_PACKAGES"
                fi
                # pretty small and needed, cuda support but requires opencl-icd too
                if apt-cache show "libnvidia-$_NVIDIA_VERSION-nvcuvid1" 1>/dev/null 2>&1 ; then
                    _NVIDIA_PACKAGES="libnvidia-$_NVIDIA_VERSION-nvcuvid1 $_NVIDIA_PACKAGES"
                fi
                # OptiX ray tracing
                if apt-cache show "libnvidia-$_NVIDIA_VERSION-nvoptix1" 1>/dev/null 2>&1 ; then
                    _NVIDIA_PACKAGES="libnvidia-$_NVIDIA_VERSION-nvoptix1 $_NVIDIA_PACKAGES"
                fi
                # video encoding, pretty small
                if apt-cache show "libnvidia-$_NVIDIA_VERSION-encode1" 1>/dev/null 2>&1 ; then
                    _NVIDIA_PACKAGES="libnvidia-$_NVIDIA_VERSION-encode1 $_NVIDIA_PACKAGES"
                fi
                # vdpau video driver, pretty required
                if apt-cache show "nvidia-$_NVIDIA_VERSION-vdpau-driver" 1>/dev/null 2>&1 ; then
                    _NVIDIA_PACKAGES="nvidia-$_NVIDIA_VERSION-vdpau-driver $_NVIDIA_PACKAGES"
                fi
                # arch based packages:
                if [[ "$( el_architecture host )" = "i386" ]] ; then
                    if apt-cache show "libnvidia-$_NVIDIA_VERSION-cuda1-i386" 1>/dev/null 2>&1 ; then
                        _NVIDIA_PACKAGES="libnvidia-$_NVIDIA_VERSION-cuda1-i386 $_NVIDIA_PACKAGES"
                    fi
                else
                    if apt-cache show "libnvidia-$_NVIDIA_VERSION-cuda1" 1>/dev/null 2>&1 ; then
                        _NVIDIA_PACKAGES="libnvidia-$_NVIDIA_VERSION-cuda1 $_NVIDIA_PACKAGES"
                    fi
                fi
            fi

            # needed for things that requires extra features like Davinci Resolve:, requires 25/108 extra MB installed
            if [[ "$RAM_TOTAL_SIZE_mb" -gt 3700 ]] || ((is_persistence)) || ! ((is_live)) ; then
                # opencl support
                if apt-cache show "nvidia-$_NVIDIA_VERSION-opencl-icd" 1>/dev/null 2>&1 ; then
                    _NVIDIA_PACKAGES="nvidia-$_NVIDIA_VERSION-opencl-icd $_NVIDIA_PACKAGES"
                fi
                # pretty small and needed, cuda support but requires opencl-icd too
                if apt-cache show "libnvidia-$_NVIDIA_VERSION-nvcuvid1" 1>/dev/null 2>&1 ; then
                    _NVIDIA_PACKAGES="libnvidia-$_NVIDIA_VERSION-nvcuvid1 $_NVIDIA_PACKAGES"
                fi
                # OptiX ray tracing
                if apt-cache show "libnvidia-$_NVIDIA_VERSION-nvoptix1" 1>/dev/null 2>&1 ; then
                    _NVIDIA_PACKAGES="libnvidia-$_NVIDIA_VERSION-nvoptix1 $_NVIDIA_PACKAGES"
                fi
                # video encoding, pretty small
                if apt-cache show "libnvidia-$_NVIDIA_VERSION-encode1" 1>/dev/null 2>&1 ; then
                    _NVIDIA_PACKAGES="libnvidia-$_NVIDIA_VERSION-encode1 $_NVIDIA_PACKAGES"
                fi
            fi
            ;;
    esac

    # add the modprobe package
    if ! ((is_wheezy)) ; then
        _NVIDIA_PACKAGES="$_NVIDIA_PACKAGES nvidia-modprobe"
    fi

    # ensure dkms package is installed for building kernel modules
    if apt-cache show "dkms" 1>/dev/null 2>&1 ; then
        _NVIDIA_PACKAGES="$_NVIDIA_PACKAGES dkms"
    fi

    # optimus extra packages
    if ((is_optimus)) && ! ((is_optimus_onlynvidia)) ; then
        _NVIDIA_PACKAGES="primus primus-nvidia primus-vk-nvidia $_NVIDIA_PACKAGES"
    fi

    el_debug "Selected list of packages to install:\n$( echo "${_NVIDIA_PACKAGES}" | tr ' ' '\n' )"


    # - select packages to install depending on which version we selected }}}
}

#===  FUNCTION  ================================================================
#          NAME:  fix_virtualbox_dkms_conf
#   DESCRIPTION:  fixes /etc/modprobe.d/virtualbox-dkms.conf if it is a directory
#===============================================================================
fix_virtualbox_dkms_conf(){
    if [ -d "/etc/modprobe.d/virtualbox-dkms.conf" ] ; then
        NOREPORTS=1 el_warning "Fixing /etc/modprobe.d/virtualbox-dkms.conf directory bug..."
        rm -rf /etc/modprobe.d/virtualbox-dkms.conf
        echo "# virtualbox" > /etc/modprobe.d/virtualbox-dkms.conf
    fi
}

#===  FUNCTION  ================================================================
#          NAME:  install_driver
#   DESCRIPTION:  prepare system and install the driver to use nvidia
#    PARAMETERS:  -
#       RETURNS:  -
#===============================================================================
install_driver(){
    # pre {{{
    el_debug

    if ! el_check_variables "_NVIDIA_VERSION" ; then
        el_error "We don't know which version of nvidia to use"
        exit 1
    fi

    if ! el_check_variables "_NVIDIA_PACKAGES" ; then
        el_error "We don't know which packages of nvidia to install"
        exit 1
    fi

    if ((is_xorg_template_wanted)) ; then
        mkdir -p /etc/X11/xorg.conf.d
    fi

    local message_warning_install_failed_try_again

    # }}}

    log_machine_status "NVIDIA_INSTALLATION_STARTED: $_NVIDIA_VERSION"
    log_machine_status "NVIDIA_PACKAGES_TO_INSTALL: $_NVIDIA_PACKAGES"

    # verify and fix virtualbox-dkms.conf before install
    fix_virtualbox_dkms_conf

    # uninstall previous drivers
    uninstall_driver

    # nvidia xorg conf {{{
    # create conf first
    if ((is_xorg_template_wanted)) ; then
        # clean it first
        : > /etc/X11/xorg.conf.d/20-nvidia.conf
        cat > "/etc/X11/xorg.conf.d/20-nvidia.conf" << EOF
Section "Device"
    Identifier     "Default screen"
    Driver         "nvidia"
    Option         "NoLogo"     "true"
    # append options here
EndSection
EOF
    fi
    # - conf }}}
    # Optimus {{{
    # OPTIMUS devices: if we are in laptop, and have more than one graphic card and both are not nvidia ones...
    if ((is_multiple_cards)) ; then

        if ((is_optimus)) ; then
            local message_multiple_cards
            message_multiple_cards="$( printf "$( eval_gettext "An additional graphic card has been detected, your laptop might use the special Nvidia Optimus drivers, where the internal card is used for battery saving and the Nvidia card is used when more performance is needed. You can use Nvidia in Elive if you install the drivers, or it will use Intel if you don't. We are now going to use the Nvidia for more performance. If you have any problem running your graphical system we suggest you enter in the BIOS and disable one of them. Search in Google to know how to configure your BIOS." )" "" )"
        else
            local message_multiple_cards
            message_multiple_cards="$( printf "$( eval_gettext "An additional graphic card has been detected, we will proceed by using Nvidia but if you have any problem running the graphical system we suggest you remove one of the graphic cards. If the other graphic card is included in the motherboard you should be able to disable it from the BIOS. Search in Google to know how to configure your BIOS." )" "" )"
        fi

        if ! ((is_mode_auto)) ; then
            dialog --timeout 80 --clear --colors --backtitle "Elive Systems: Use Ctrl-L to redraw, Enter to confirm" \
                --title "Multiple Graphic Cards found" \
                --msgbox "$message_multiple_cards" \
                0 0
        fi

        # select if wants the full nvidia or on-demand
        local message_optimus_type
        message_optimus_type="$( printf "$( eval_gettext "There are two ways to use your Nvidia card: Enabling it to be used all the time, or using it only when needed to improve battery life. The latter option requires running your wanted 3D applications from a terminal with a command prepended. Like in these examples:" )" "" )"
        local message_optimus_type_question
        message_optimus_type_question="$( printf "$( eval_gettext "Do you want to use only Nvidia? (recommended for novice users). Answering NO will use the less-powered integrated card by default and will use the other one only when you request it." )" "" )"

        if ((is_mode_auto)) ; then
            ret=0
        else
            dialog --timeout 60 --clear --colors --backtitle "Elive Systems: Use Ctrl-L to redraw, TAB to select, Enter to confirm" \
                --title "Select a method to use your both graphic cards" \
                --yesno "*******   IMPORTANT:   ******\n\n${message_optimus_type}\n\n\$ primusrun steam\n\$ primusrun supertuxkart\n\n${message_optimus_type_question}" \
                0 0
                            ret="$?"
        fi

        case "$ret" in
            0|255|124|123) # yes, timeout, cancel
                true
                is_optimus_onlynvidia=1
                ;;
            1) # no
                true
                unset is_optimus_onlynvidia
                unset is_xorg_template_wanted
                rm -f /tmp/.nvidia_optimus
                touch /tmp/.nvidia_optimus_conf_onlynvidia
                ;;
        esac

        if ((is_optimus_onlynvidia)) ; then
            # clean it first
            : > /etc/X11/xorg.conf.d/20-nvidia.conf
            cat > "/etc/X11/xorg.conf.d/20-nvidia.conf" << EOF
Section "OutputClass"
    Identifier "intel"
    MatchDriver "i915"
    Driver "modesetting"
EndSection

Section "OutputClass"
    Identifier "nvidia"
    MatchDriver "nvidia-drm"
    Driver "nvidia"
    Option "AllowEmptyInitialConfiguration"
    Option "PrimaryGPU" "yes"
    ModulePath "/usr/lib/nvidia/xorg"
    ModulePath "/usr/lib/xorg/modules"
    # append options here
EndSection
EOF
            # this entry is needed in order to start the "startx" command with the nvidia card
            if ((is_live)) ; then
                if ! grep -qs "xrandr --setprovideroutputsource modesetting NVIDIA-0" /home/eliveuser/.xinitrc ; then
                    buf="$( cat /home/eliveuser/.xinitrc 2>/dev/null )"
                    echo -e "xrandr --setprovideroutputsource modesetting NVIDIA-0\nxrandr --auto\n\n${buf}" > /home/eliveuser/.xinitrc
                fi
            fi
            # enable it on lightdm when needed
            if [[ -e "/var/lib/dpkg/info/lightdm.list" ]] ; then
                mkdir -p "/etc/lightdm"
                echo -e "#!/bin/sh\nxrandr --setprovideroutputsource modesetting NVIDIA-0\nxrandr --auto" > "/etc/lightdm/display_setup.sh"
                chmod +x "/etc/lightdm/display_setup.sh"
                # set lightdm to run the script when login
                sed -i -e "s|^\(#\)*display-setup-script=.*$|display-setup-script=/etc/lightdm/display_setup.sh|g" "/etc/lightdm/lightdm.conf"
            fi
        fi
    fi
    # - Optimus }}}
    # force brightness entry conf {{{
    if laptop-detect ; then

        local message_brightness_force
        message_brightness_force="$( printf "$( eval_gettext "Is the brightness of your screen working correctly? If you encounter any issues with brightness, select 'NO' next time. Select 'YES' if unsure." )" "" )"

        if ((is_mode_auto)) || ((is_mode_simulate)) ; then
            ret=0
        else
            dialog --timeout 60 --clear --colors --backtitle "Elive Systems: Use Ctrl-L to redraw, TAB to select, Enter to confirm" \
                --title "Brightness of the Screen" \
                --yesno "$message_brightness_force" \
                0 0
            ret="$?"
        fi

        case "$ret" in
            0|255|124|123) # yes, timeout, cancel
                true
                ;;
            1) # no
                true
                if [[ -e "/etc/X11/xorg.conf.d/20-nvidia.conf" ]] ; then
                    sed -i 's|^.*append options here.*$|        Option "RegistryDwords" "EnableBrightnessControl=1"\n&|' /etc/X11/xorg.conf.d/20-nvidia.conf
                fi
                ;;
        esac
    fi

    # - force brightness entry conf }}}
    # force dpi size to 96 {{{

    # local message_dpi_force
    # message_dpi_force="$( printf "$( eval_gettext "Select this option if the fonts and sizes on your screen look wrong. Sometimes the auto-detection fails, resulting in wrong sized elements. This option will set 96 DPI which is a common standard and works well in most cases. But you should try without this option first." )" "" )"
    #
    # if ((is_mode_auto)) || ((is_mode_simulate)) ; then
    #     ret=0
    # else
    #     dialog --timeout 60 --clear --colors --defaultno --backtitle "Elive Systems: Use Ctrl-L to redraw, TAB to select, Enter to confirm" \
    #         --title "Force DPI defaults?" \
    #         --yesno "$message_dpi_force" \
    #         0 0
    #     ret="$?"
    # fi
    #
    # case "$ret" in
    #     0|255|124|123) # yes, timeout, cancel
    #         if [[ -e "/etc/X11/xorg.conf.d/20-nvidia.conf" ]] ; then
    #             sed -i 's|^.*append options here.*$|        Option "UseEdidDpi"  "False"\n        Option "DPI"     "96 x 96"\n&|' /etc/X11/xorg.conf.d/20-nvidia.conf
    #         fi
    #         true
    #         ;;
    #     1) # no
    #         true
    #         ;;
    # esac
    local message_dpi_fix
    message_dpi_fix="$( printf "$( eval_gettext "Some Nvidia drivers have issues detecting the scaling size of the screen. If you find your fonts are too big or too small, Elive has a feature to set your desired desktop scaling. If you want to know the exact DPI value of your screen, run Elive without the Nvidia drivers and, from a terminal, run:" )" "" )"

    if ! ((is_mode_auto)) ; then
        dialog --timeout 30 --clear --colors --backtitle "Elive Systems: Use Ctrl-L to redraw, Enter to confirm" \
            --title "DPI issues with some cards" \
            --msgbox "${message_dpi_fix}\n\nel_dpi_get" \
            0 0
    fi

    # force the fix anyways in order to avoid bad settings
    if [[ -e "/etc/X11/xorg.conf.d/20-nvidia.conf" ]] ; then
        sed -i 's|^.*append options here.*$|        Option "UseEdidDpi"  "False"\n        Option "DPI"     "96 x 96"\n&|' /etc/X11/xorg.conf.d/20-nvidia.conf
    fi

    # optimus - }}}
    # know arch and report {{{
    case "$(uname -m)" in
        i*86)
            local message_unsupported_arch
            message_unsupported_arch="$( printf "$( eval_gettext "You are using the 32-bit version of Elive, and there are no official Nvidia drivers for this architecture. The driver installer will likely fail. You should use the 64-bit version of Elive to ensure your drivers work correctly." )" "" )"

            if ! ((is_mode_auto)) ; then
                dialog --timeout 30 --clear --colors --backtitle "Elive Systems: Use Ctrl-L to redraw, Enter to confirm" \
                    --title "Suggested Version" \
                    --msgbox "$message_unsupported_arch" \
                    0 0
            fi

            is_i386=1
            ;;
        *64)
            is_amd64=1
            ;;
        *)
            el_error "unknown architecture on $SOURCE"
            is_amd64=1
            ;;
    esac

    # }}}

    # unload modules {{{
    # note: we should have already enough memory because we should have already requested to add a swap in case that we don't have enough space
    if lsmod | grep -qsE "^nouveau\s+" ; then
        if ((is_mode_force)) ; then
            if ! ((is_safe_mode)) ; then
                rmmod -f nouveau
            fi
        else
            if ! ((is_safe_mode)) ; then
                rmmod nouveau
            fi
            if lsmod | grep -qsE "^nouveau\s+" ; then
                # report
                if ((is_live)) && grep -qs "blacklist.*nouveau" /proc/cmdline ; then
                    el_error "Nouveau module unable to unload while boot parameters are meant to be blacklisted:\n$(cat /proc/cmdline)"
                else
                    echo -e "\nE: nouveau module is loaded and we cannot unload it"
                fi

                echo -e "You should reboot and add the boot parameter 'modprobe.blacklist=nouveau' to tell the kernel to not load it, or you can use the -f option (but it can make your screen unreadable, which is ok if you are running it from a ssh)"

                if ! ((is_mode_auto)) ; then
                    dialog --timeout 80 --clear --colors --backtitle "Elive Systems: Use Ctrl-L to redraw, Enter to confirm" \
                        --title "Unable to remove module" \
                        --msgbox "Error: nouveau module is loaded and we cannot unload it.\n\nYou should reboot and add the boot parameter 'modprobe.blacklist=nouveau' to tell the kernel to not load it, in Live mode it should be already included in the default boot option, if you are just experimenting you can try to use the -f option (but it can make your screen unreadable, which is ok if you are running it from a ssh, don't expect this to work since its forced)." \
                        0 0

                    if ((is_mode_live)) ; then
                        dialog --timeout 180 --clear --colors --backtitle "Elive Systems: Use Ctrl-L to redraw, TAB to select, Enter to confirm" \
                            --title "Reboot now?" \
                            --yesno "$( eval_gettext "Do you want to reboot now?" )" \
                            0 0
                        ret="$?"

                        case "$ret" in
                            0|255|124|123) # yes, timeout, cancel
                                ( reboot & )
                                sleep 4
                                exit
                                ;;
                            1) # no
                                true
                                ;;
                        esac
                    fi
                fi
            fi
        fi
    fi

    # just in case another one is used
    if ! rmmod_nvidia ; then
        el_info "E: unable to unload the nvidia module, if you are running the graphical system you should exit from it first, and if is not the case you can try to 'rmmod -f' these modules: $( lsmod | grep nvidia )"
    fi

    # - unload modules }}}
    # apt-get install {{{

    echo -e "\n\n\n\n\nInstalling... Please be patient...\n\n"
    sleep 1

    # Install from packages:
    if TERM=screen-256color DEBIAN_FRONTEND=noninteractive DEBIAN_PRIORITY=critical DEBCONF_NONINTERACTIVE_SEEN=true DEBCONF_NOWARNINGS=true \
        apt-get install -y $_NVIDIA_PACKAGES ; then
            is_driver_compiled_fullinstall=1
    else
        # hack the postinst to not fail
        sed -i -e '/^set -e/d' /var/lib/dpkg/info/nvidia-*dkms.postinst
        apt_get -y -f install -q=2

        if TERM=screen-256color DEBIAN_FRONTEND=noninteractive DEBIAN_PRIORITY=critical DEBCONF_NONINTERACTIVE_SEEN=true DEBCONF_NOWARNINGS=true \
            apt-get install -y $_NVIDIA_PACKAGES ; then
                is_driver_compiled_fullinstall=1
        else
            unset is_driver_compiled_fullinstall
        fi
    fi

    # check if at least one (kernel) driver was compiled
    if find "/lib/modules/" -type f -name '*nvidia*ko*' | grep -qs "/updates/dkms/nvidia" ; then
        is_driver_compiled_some=1
    else
        unset is_driver_compiled_some
    fi

    if find "/lib/modules/$(uname -r)/updates" -type f -name '*nvidia*ko*' | grep -qs "update.*/nvidia" ; then
        is_driver_compiled_kernel=1
    else
        unset is_driver_compiled_kernel
    fi

    # if no driver was compiled for any of the kernels, try again by updating the packages list
    if ! ((is_driver_compiled_some)) ; then

        NOREPORTS=1 el_error "error ^^^^^^^^^^^^^^^^^^^^^^^^"
        sleep 12

        # CUDA in live mode? this won't work due to too much RAM needed:
        if ((is_extra_packages_wanted)) && ((is_live)) && ! ((is_persistence)) ; then
            message_warning_install_failed_try_again="$( printf "$( eval_gettext "Failed to install and compile the driver. We'll retry after updating the package list. For installing extra packages like CUDA, we recommend first installing Elive on your hard drive, as this operation requires significant RAM." )" "" )"
        else
            message_warning_install_failed_try_again="$( printf "$( eval_gettext "Failed to install and compile the driver. We'll retry after updating the package list. This issue can arise from using a too new kernel version or insufficient RAM in Live mode installation." )" "" )"
        fi

        if ! ((is_mode_auto)) ; then
            # wait a few seconds before to show this message, so that we can read the pervious errors:
            sleep 3
            dialog --timeout 280 --clear --colors --backtitle "Elive Systems: Use Ctrl-L to redraw, Enter to confirm" \
                --title "Compilation Failed" \
                --msgbox "$message_warning_install_failed_try_again" \
                0 0
        fi

        # first update packages, importan
        el_aptget_update force

        if  TERM=screen-256color DEBIAN_FRONTEND=noninteractive DEBIAN_PRIORITY=critical DEBCONF_NONINTERACTIVE_SEEN=true DEBCONF_NOWARNINGS=true \
            apt-get install -y $_NVIDIA_PACKAGES ; then
                is_driver_compiled_fullinstall=1
        else
            unset is_driver_compiled_fullinstall
        fi

        # check if at least one (kernel) driver was compiled
        if find "/lib/modules/" -type f -name '*nvidia*ko*' | grep -qs "/updates/dkms/nvidia" ; then
            is_driver_compiled_some=1
        else
            unset is_driver_compiled_some
        fi

        if find "/lib/modules/$(uname -r)/updates" -type f -name '*nvidia*ko*' | grep -qs "update.*/nvidia" ; then
            is_driver_compiled_kernel=1
        else
            unset is_driver_compiled_kernel
        fi
    fi

    # because we may have false positive error messages, just clean the screen since everything went fine:
    if ((is_driver_compiled_kernel)) ; then
        clear
    fi


    # if driver compiled on a different kernel, tell the user that needs to reboot in order to use it
    if ((is_driver_compiled_some)) && ! ((is_driver_compiled_kernel)) ; then
        local message_warning_install_other
        message_warning_install_other="$( printf "$( eval_gettext "The driver isn't working with your current kernel but does work with another one, so reboot, choose the other kernel from the boot menu, and then reinstall the Nvidia driver since the one you're using now is the one that failed." )" "" )"

        if ! ((is_mode_auto)) ; then
            dialog --timeout 280 --clear --colors --backtitle "Elive Systems: Use Ctrl-L to redraw, Enter to confirm" \
                --title "Another kernel is required" \
                --msgbox "$message_warning_install_other" \
                0 0

            # suggest to reboot
            try_again
        fi
    fi

    # verify if the installation succeeded
    if ! ((is_driver_compiled_kernel)) ; then

        clear ; echo
        NOREPORTS=1 el_error "Driver compilation seems to have failed:\n$(find /lib/modules/ -type f -iname '*nvidia*ko*' | grep -vE "(typec_nvidia|nvidia-wmi-ec-backlight)" )"
        sleep 4

        local message_warning_install_failed
        message_warning_install_failed="$( printf "$( eval_gettext "Failed to compile the Nvidia driver. Reboot and choose a different kernel version; this is a common issue across different kernel versions. Check our forums for additional assistance." )" "" )"

        if ! ((is_mode_auto)) ; then
            dialog --timeout 280 --clear --colors --backtitle "Elive Systems: Use Ctrl-L to redraw, Enter to confirm" \
                --title "Compilation Failed" \
                --msgbox "$message_warning_install_failed" \
                0 0
        fi


        if ! ((is_mode_auto)) || ((is_mode_live)) ; then
            # if we are not in chroot:
            if [ "$(stat -c %d/%i /)" != "$(stat -Lc %d/%i /proc/1/root 2>/dev/null)" ]; then
                echo -e "\n\n"

                if el_confirm "$( eval_gettext "Installation failed. Open a terminal to check the package status, or manually load the module and then run the graphical system. If you succeed, report the necessary changes in our forums to help others. Open terminal now?" )" ; then
                    find "/lib/modules/$(uname -r)/updates" -type f -iname '*'nvidia'*'
                    el_explain 0 "try to 'modprobe nvidia' or the correct module name, check the status of the packages, run 'dmesg' to check for errors or messages, use 'apse nvidia $_NVIDIA_VERSION' to search for a possible missing package, and finally run the graphical system with 'startx'"
                    el_explain 0 "Type '__exit__' for continue..."
                    $SHELL -l

                fi
            fi
        fi
    fi

    # add the packages to the installed system later too
    # update: not needed in the new installer which should run the command to install it itself
    # if ((is_live)) ; then
        ## first remove any possible previous entry for nvidia
        #sed -i '/nvidia/d' /tmp/.packages-to-install 2>/dev/null
        #sed -i '/nvidia/d' /tmp/.packages-to-hold    2>/dev/null

        #for package in $_NVIDIA_PACKAGES
        #do
            #echo "$package" >> /tmp/.packages-to-install
            ## just like the kernel, keep them holded, we don't want surprises, if a system works it works
            #echo "$package" >> /tmp/.packages-to-hold
        #done
    #fi

    # - apt-get install }}}
    # verify and fix virtualbox-dkms.conf after install
    fix_virtualbox_dkms_conf

    # load module {{{
    # reload devices just in case
    if ((is_mode_simulate)) ; then
        if find "/lib/modules/$(uname -r)/updates" -type f -name '*nvidia*ko*' | grep -qs "update.*/nvidia" ; then
            message_unable_to_load="NVIDIA correctly COMPILED\n\n(in simulation mode)\n\nYou can shutdown the computer since this verification worked\n\n$(find "/lib/modules/$(uname -r)/updates" -type f -iname nvidia'*' | sed -e 's|^.*updates/||g' | tr '\n' ' ' )"
        else
            message_unable_to_load="NVIDIA failed to COMPILE? \n$( find "/lib/modules/$(uname -r)/updates" -type f -name '*'nvidia'*' | grep -vE "(typec_nvidia|nvidia-wmi-ec-backlight)" )"
        fi

        # show the message if we have any
        if [[ -n "$message_unable_to_load" ]] && ! ((is_mode_auto)) ; then
            dialog --timeout 900 --clear --colors --backtitle "Elive Systems: Use Ctrl-L to redraw, Enter to confirm" \
                --title "Simulation mode" \
                --msgbox "$message_unable_to_load" \
                0 0
        fi
    else
        service nvidia-kernel restart 1>/dev/null 2>&1

        load_driver

        if ! lsmod | grep -qs "^nvidia" && ! ((is_mode_simulate)) ; then

            if ! ((is_mode_auto)) ; then
                local message_unable_to_load

                # default message for not working drivers
                if ! lsmod | grep -qs "^nvidia" ; then
                    NOREPORTS=1 el_error "Unable to load NVIDIA module"

                    message_unable_to_load="$( printf "$( eval_gettext "Elive couldn't load the NVIDIA module. Possible reasons include failed compilation, device busyness, or the module not being found. Please reboot and try a different kernel version. For very old video cards, an older version of Elive or the kernel might work better. Check our forums for further assistance." )" "" )"
                fi


                if modprobe $_NVIDIA_MODULE 2>&1 | grep -aqsE "(No supported display adapters|No such device)" || dmesg 2>&1 | colors-remove | grep -aqsi "No NVIDIA graphics adapter found" ; then
                    message_unable_to_load="$( printf "$( eval_gettext "Error: Your graphics card does not seem compatible with this driver version. Try a different version or use the open-source driver instead." )" "" )"

                fi

                # module simply was not compiled
                if ! find "/lib/modules/$(uname -r)/updates" -type f -iname '*'nvidia'*' | grep -qs "nvidia" ; then
                    message_unable_to_load="$( printf "$( eval_gettext "Error: The driver did not compile successfully, usually because of a too recent or too old kernel. Reboot and choose a different version from the boot menu. We recommend trying the open-source driver as it might work." )" "" )"
                fi


                # show the message if we have any
                if [[ -n "$message_unable_to_load" ]] && ! ((is_mode_auto)) ; then
                    dialog --timeout 280 --clear --colors --backtitle "Elive Systems: Use Ctrl-L to redraw, Enter to confirm" \
                        --title "Unable to load module" \
                        --msgbox "$message_unable_to_load" \
                        0 0
                fi
            fi


            # cleanups
            if ! ((is_mode_force)) || ((is_mode_live)) ; then
                uninstall_driver
                try_again
                #NOREPORTS=1 el_warning "Switched to the default drivers option"
                #sleep 4
                #exit 0
            fi
        fi
    fi



    # reload devices just in case
    service nvidia-kernel restart 1>/dev/null 2>&1

    # regenerate initramfs if we are not in live (and persistence)
    if ! ((is_live)) && ! ((is_persistence)) ; then
        LC_ALL="$EL_LC_EN" update-initramfs -k all -u -t 2>&1 | grep -vE '(^mkdir:|mdadm:|Generating /|live-boot)'
        rm -f /boot/*old-dkms 2>/dev/null
    fi

    if ((is_driver_compiled_kernel)) ; then
        log_machine_status "NVIDIA_INSTALLATION_STATUS: SUCCESS"
    else
        log_machine_status "NVIDIA_INSTALLATION_STATUS: FAILURE"
    fi

    el_info "Install complete"
    el_info "Installed nvidia modules:\n$( find /lib/modules/ -type f -iname '*nvidia*ko*' | grep -vE "(typec_nvidia|nvidia-wmi-ec-backlight)" )"

    if ((is_live)) && ! ((is_mode_auto)) && ! ((is_mode_simulate)) ; then
        local message_suggestion
        message_suggestion="$( printf "$( eval_gettext "Suggestion: After installing drivers in live mode, the screen may appear distorted. Try switching to console mode and back to the graphical system. This issue should not occur after installing Elive." )" "" )"
        dialog --timeout 280 --clear --colors --backtitle "Elive Systems: Use Ctrl-L to redraw, Enter to confirm" \
            --title "Suggestion for Live Mode:" \
            --msgbox "${message_suggestion} \n\nExample to switch to Console and then to Graphical system:\nCtrl + Alt + F1, then, Ctrl + Alt + F7 (or F8)" \
            0 0
    fi

    # - load module }}}
}

#===  FUNCTION  ================================================================
#          NAME:  try_again
#   DESCRIPTION:  ask which next step to do if failed
#    PARAMETERS:  -
#       RETURNS:  -
#===============================================================================
try_again(){
    # pre {{{
    if ((is_mode_auto)) ; then
        return 0
    fi

    el_debug

    local message_option_1
    message_option_1="$( printf "$( eval_gettext "Try to install a different version" )" "" )"

    local message_option_2
    message_option_2="$( printf "$( eval_gettext "Use the open-drivers:" )" "" ) nouveau"

    local message_option_3
    message_option_3="$( printf "$( eval_gettext "Exit this tool and continue (unknown state)" )" "" )"

    local message_option_4
    message_option_4="$( printf "$( eval_gettext "Reboot your computer to select another kernel or boot options" )" "" )"

    local message_option_5
    message_option_5="$( printf "$( eval_gettext "Open a console terminal" )" "" )"


    # }}}

    { echo "'free' '$message_option_2'" ; echo "'version' '$message_option_1'" ; echo "'exit' '$message_option_3'" ; echo "'reboot' '$message_option_4'" ; echo "'console' '$message_option_5'" ; } \
        | xargs dialog --timeout 380 --clear --colors --backtitle "Elive Systems: Use Ctrl-L to redraw, Enter to confirm" --menu "Select an option" 0 0 0  2>"/tmp/.$(basename $0)-ret"


    # user canceled? uninstall and exit
    if echo "$?" | grep -qsE "^(1|123|255|125)$" || grep -qsE "^(1|123|255|125)$" "/tmp/.$(basename $0)-ret" ; then
        ret="exit"
    else
        # get result
        ret="$( cat "/tmp/.$(basename $0)-ret" | head -1 )"
    fi
    rm -f "/tmp/.$(basename $0)-ret"

    # remove extra leading blank chars
    read -r ret <<< "$ret"

    case "$ret" in
        "free")
            uninstall_driver
            exit
            ;;
        "version")
            export is_mode_already_run=1
            $0 $args
            exit
            ;;
        "reboot")
            ( reboot & )
            sleep 4
            exit
            ;;
        "console")
            reset
            if [[ -n "$SHELL" ]] ; then
                $SHELL
            else
                if [[ -x "$( which zsh )" ]] ; then
                    zsh -l
                else
                    bash -l
                fi
            fi
            ;;
        "exit")
            exit
            ;;
    esac


}
#===  FUNCTION  ================================================================
#          NAME:  uninstall_driver
#   DESCRIPTION:  uninstalls any possible nvidia drivers and make the system work back on nouveau
#    PARAMETERS:  -
#       RETURNS:  -
#===============================================================================
uninstall_driver(){
    # pre {{{
    local line _NVIDIA_PACKAGES
    el_debug

    # }}}

    # unload module {{{
    # unload module first
    if ! rmmod_nvidia ; then
        el_info "E: unable to unload the nvidia module, if you are running the graphical system you should exit from it first, and if is not the case you can try to 'rmmod -f' these modules: $( lsmod | grep nvidia )"
        exit 1
    fi


    # - unload module }}}
    # confs {{{
    # remove any possible xorg conf (before uninstall packages)
    rm -f /etc/X11/xorg.conf.d/20-nvidia.conf 2>/dev/null || true


    # - confs }}}
    # packages {{{
    # remove all nvidia packages
    while read -ru 3 line
    do
        [[ -z "$line" ]] && continue

        # if matches
        if echo "$line" | grep -qsE "(nvidia|lib.*nvidia|glx.*nvidia|xserver.*nvidia|bumblebee|primus)" ; then
            # which doesn't maches
            if ! echo "$line" | grep -qsE "(nvidia-detect|glx-diversions|nvidia-installer-cleanup)" ; then
                el_debug "Adding $line to the list of uninstall packages"
                _NVIDIA_PACKAGES="$_NVIDIA_PACKAGES $line"
            fi
        fi

    done 3<<< "$( COLUMNS=1000 dpkg -l | grep -E "(nvidia|bumblebee|primus)" | awk '{print $2}' )"

    # remove extra leading blank chars
    read -r _NVIDIA_PACKAGES <<< "$_NVIDIA_PACKAGES"

    if [[ -n "$_NVIDIA_PACKAGES" ]] ; then
        log_progress_msg "Removing Nvidia proprietary drivers, this machine doesn't has it"

        #if ((is_mode_auto)) ; then
            el_debug "apt-get remove --purge -y $_NVIDIA_PACKAGES"
            TERM=screen-256color DEBIAN_FRONTEND=noninteractive DEBIAN_PRIORITY=critical DEBCONF_NONINTERACTIVE_SEEN=true DEBCONF_NOWARNINGS=true \
                apt-get remove --purge -y $_NVIDIA_PACKAGES
            # uninstall also extra packages that we may have installed, otherwise it can fail installing new ones:
            TERM=screen-256color DEBIAN_FRONTEND=noninteractive DEBIAN_PRIORITY=critical DEBCONF_NONINTERACTIVE_SEEN=true DEBCONF_NOWARNINGS=true \
                apt-get autoremove -y --purge
        #else
            #el_debug "apt-get remove --purge $_NVIDIA_PACKAGES"
            #TERM=screen-256color DEBIAN_FRONTEND=noninteractive DEBIAN_PRIORITY=critical DEBCONF_NONINTERACTIVE_SEEN=true DEBCONF_NOWARNINGS=true \
                #apt-get remove --purge $_NVIDIA_PACKAGES
        #fi
    else
        el_info "Nvidia packages already removed"
    fi


    # just in case, reinstall the nouveau driver
    if ! COLUMNS=1000 dpkg -l | awk '{print $2}' | grep -qs "^ii.*xserver-xorg-video-nouveau" ; then
        TERM=screen-256color DEBIAN_FRONTEND=noninteractive DEBIAN_PRIORITY=critical DEBCONF_NONINTERACTIVE_SEEN=true DEBCONF_NOWARNINGS=true \
            apt-get install -y xserver-xorg-video-nouveau
    fi

    # - packages }}}
    # end {{{
    # show final result
    if COLUMNS=1000 dpkg -l | awk '{print $2}' | grep nvidia | grep -vE "(nvidia-detect|glx-diversions|nvidia-installer-cleanup)" | grep -qs nvidia ; then
        echo -e ""
        el_error "We still having some nvidia packages not uninstalled: $( COLUMNS=1000 dpkg -l | grep nvidia | awk '{print $2}' | grep nvidia  1>&2 )"
        log_machine_status "NVIDIA_UNINSTALLATION_STATUS: WARNING_PACKAGES_REMAIN"
    else
        el_debug "Driver NVIDIA uninstalled successfully"
        log_machine_status "NVIDIA_UNINSTALLATION_STATUS: SUCCESS"
    fi


    # deprecated, not needed because next menu asks the same question
    # reboot needed for nouveau
    #if echo "${_CMDLINE}" | LC_ALL=C grep -qsE "blacklist=nouveau" ; then
        #local message_title
        #message_title="$( printf "$( eval_gettext "Nvidia Graphics Card" )" "" )"
        #local message_message_reboot_open
        #message_message_reboot_open="$( printf "$( eval_gettext "To use the open driver you must reboot without the option of the proprietary drivers because nouveau is disabled. Reboot now to select the other option? Or you can continue to select a different version." )" )"

        #dialog --timeout 180 --clear --colors --backtitle "Elive Systems: Use Ctrl-L to redraw, Enter to confirm" \
            #--title "$message_title" \
            #--yesno "$message_message_reboot_open" \
            #0 0
            #ret="$?"

            #case "$ret" in
                #0|255|123) # yes, timeout, cancel
                    #( reboot & )
                    #sleep 4
                    #exit
                    #;;
                #1) # no
                    #true
                    #;;
            #esac
    #fi

    # - end }}}
}

apt_get(){
    local is_waiting i
    i=0

    tput sc
    while fuser /var/lib/apt/lists/lock  >/dev/null 2>&1 ; do
        case $(($i % 4)) in
            0 ) j="-" ;;
            1 ) j="\\" ;;
            2 ) j="|" ;;
            3 ) j="/" ;;
        esac
        tput rc
        echo -en "\r[$j] Waiting for other software managers to finish..."
        is_waiting=1

        sleep 0.5
        ((i=i+1))
    done

    # run what we want
    TERM=linux DEBIAN_FRONTEND=noninteractive DEBIAN_PRIORITY=critical DEBCONF_NONINTERACTIVE_SEEN=true DEBCONF_NOWARNINGS=true  \
        apt-get "$@"
}




main(){
    # pre {{{
    #if [[ -z "${1}" ]] ; then
    #usage
    #exit 1
    #fi

    . /lib/lsb/init-functions

    _CMDLINE="$(cat /proc/cmdline)"
    RAM_TOTAL_SIZE_mb="$( el_ram_usage_show "total" )"
    if echo "${_CMDLINE}" | LC_ALL=C grep -qsE "boot=live" ; then
        is_live=1
    fi
    if echo "${_CMDLINE}" | LC_ALL=C grep -qsE "persistence" ; then
        is_persistence=1
    fi

    el_dependencies_check "dialog|apt-cache"

    if cat /etc/debian_version | grep -qsE "^(7|wheezy)" ; then
        is_wheezy=1
    fi

    # always require the template, important
    is_xorg_template_wanted=1

    args="$@"

    # }}}

    # initialize log file for fresh run
    : > "$NVIDIA_LOGFILE" 2>/dev/null || true
    log_machine_status "NVIDIA_RUN_STARTED: $(date -u +%Y-%m-%dT%H:%M:%SZ)"

    # Usage
    while getopts ":acdfm:lquvhtxs" opt; do
        case $opt in
            a)
                is_mode_auto=1
                ;;
            c)
                is_mode_check=1
                ;;
            d)
                is_mode_detect=1
                ;;
            f)
                is_mode_force=1
                ;;
            v)
                export EL_DEBUG=2

                ;;
            m)
                driver_version="$OPTARG"
                is_mode_version_set=1
                ;;
            l)
                is_mode_live=1
                ;;
            q)
                export EL_DEBUG=0

                ;;
            u)
                is_mode_uninstall=1
                ;;
            t)
                is_mode_test_installed=1
                ;;
            x)
                is_extra_packages_wanted=1
                ;;
            s)
                is_safe_mode=1
                ;;
            h)
                usage
                exit
                ;;
            \?)
                el_error "Invalid option: -$OPTARG"
                usage
                exit 1
                ;;
            :)
                el_error "Option -$OPTARG requires an argument."
                usage
                exit 1
                ;;
        esac
    done

    if LC_ALL=C grep -qs "simulate=nvidia" /proc/cmdline ; then
        is_mode_force=1
        is_mode_simulate=1
    fi


    check_hardware

    if ((is_mode_uninstall)) ; then
        uninstall_driver
        # nothing more to do so exit
        exit
    fi

    if ((is_mode_version_set)) ; then
        # uninstall possible drivers first
        uninstall_driver
    fi

    # just check if installed and working
    if ((is_mode_test_installed)) ; then
        if check_driver ; then
            el_debug "driver is installed and working"
            exit 0
        else
            el_debug "driver is NOT installed / working"
            exit 1
        fi
    fi

    # do not ask to install driver if is already and correctly installed (like in persistence mode)
    if check_driver ; then
        if ! ((is_mode_force)) ; then
            el_debug "driver already installed, use -f to force installation"
            exit
        fi
    fi

    interactive_ask_privative
    detect_driver_version
    interactive_ask_driver_version
    install_driver

    # add version line
    if [[ -n "$_NVIDIA_VERSION" ]] && ((is_driver_compiled_kernel)); then
        if [[ ! -f /etc/elive-version ]]; then
            touch /etc/elive-version
        fi
        sed -i "/^nvidia-privative:/d" /etc/elive-version
        echo "nvidia-privative: $_NVIDIA_VERSION" >> /etc/elive-version
    fi

    report_kernel_nvidia_status
}

#===  FUNCTION  ================================================================
#          NAME:  report_kernel_nvidia_status
#   DESCRIPTION:  outputs machine-readable status of nvidia driver installation per kernel
#===============================================================================
report_kernel_nvidia_status(){
    local kdir kver

    for kdir in /lib/modules/*; do
        [ -d "$kdir" ] || continue
        kver="$(basename "$kdir")"
        if [ -f "/boot/vmlinuz-$kver" ] || [ -d "$kdir/kernel" ]; then
            if find "$kdir" -type f -iname '*nvidia*ko*' 2>/dev/null | grep -vE "(typec_nvidia|nvidia-wmi-ec-backlight)" | grep -qs "nvidia" ; then
                log_machine_status "NVIDIA_KERNEL_INSTALLED: $kver"
            else
                log_machine_status "NVIDIA_KERNEL_NOT_INSTALLED: $kver"
            fi
        fi
    done
}

#
#  MAIN
#
main "$@"

# vim: set foldmethod=marker :
