#!/bin/bash
# This provides a stripped down 'failsafe' mode for situations
# where X is failing to start up.

# Author: Bryce W. Harrington <bryce@canonical.com>

# Copyright (C) 2010 Canonical, Ltd.
#
# Permission is hereby granted, free of charge, to any person obtaining
# a copy of this software and associated documentation files (the
# "Software"), to deal in the Software without restriction, including
# without limitation the rights to use, copy, modify, merge, publish,
# distribute, sublicense, and/or sell copies of the Software, and to
# permit persons to whom the Software is furnished to do so, subject to
# the following conditions:
#
# The above copyright notice and this permission notice shall be included
# in all copies or substantial portions of the Software.
#
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
# IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
# CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
# TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
# SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.


xorg_conf=$1
dm=$2

display=0
xorg_log="/var/log/Xorg.${display}.log"
gdm_log="/var/log/gdm/:${display}.log"
gdm_log_1="/var/log/gdm/:${display}.log.1"
gdm_log_2="/var/log/gdm/:${display}.log.2"
lightdm_log="/var/log/lightdm/lightdm.log"
lightdm_display_log="/var/log/lightdm/:0.log"
lightdm_greeter_log="/var/log/lightdm/:0-greeter.log"
apport_hook="/usr/share/apport/package-hooks/source_xorg.py"

app_width=600
app_height=300
app_title="$(gettext 'Failsafe-X')"

timestamp=$(date +%y%m%d%H%M%S)

. gettext.sh
TEXTDOMAIN=xdiagnose
export TEXTDOMAIN
TEXTDOMAINDIR=/usr/share/locale-langpack
export TEXTDOMAINDIR

display_main_menu() {
    zenity --list \
        --radiolist \
        --title "$app_title" \
        --width $app_width --height $app_height \
        --text "$(gettext 'What would you like to do?')" \
        --column "" --column "$(gettext 'Choice')" --column "" \
          TRUE   DEFAULT_RES_MODE "$(gettext 'Try running with default graphical mode')" \
          FALSE  RECONFIGURE "$(gettext 'Reconfigure graphics')" \
          FALSE  TROUBLESHOOT "$(gettext 'Troubleshoot the error')" \
          FALSE  EXIT_TO_CONSOLE "$(gettext 'Exit to console login')" \
        --hide-column 2

# TODO:          3 FILE_BUG "Report a bug about this failure" \
}

display_reconfigure_menu() {
    # TODO:  Only display SELECT_BACKUP if backups are available

    zenity --list \
        --radiolist \
        --title "$app_title : $(gettext 'Reconfiguration')" \
        --text "$(gettext 'How would you like to reconfigure your display?')" \
        --width $app_width --height $app_height \
        --column "" --column "$(gettext 'Choice')" --column "" \
          TRUE   DEFAULT_CONFIG "$(gettext 'Use default (generic) configuration')" \
          FALSE  SELECT_BACKUP "$(gettext 'Use your backed-up configuration')" \
        --hide-column 2
}

display_troubleshooting_menu() {
    zenity --list \
        --radiolist \
        --title "$app_title : $(gettext 'Troubleshooting')" \
        --text "$(gettext 'What information would you like to review?')" \
        --width $app_width --height $app_height \
        --column "" --column "$(gettext 'Choice')" --column "" \
          TRUE   VIEW_XORG_LOG "$(gettext 'Review the xserver log file')" \
          FALSE  VIEW_GDM_LOG  "$(gettext 'Review the startup errors')" \
          FALSE  EDIT_CONFIG   "$(gettext 'Edit configuration file')" \
        --hide-column 2
# TODO:          5 VERIFY_XORGCONF "Check configuration file"
}

display_filebug_menu() {
    # Run apport to file a bug
    if [ -e $apport_hook ]; then
        python3 $apport_hook
        if [ $? == 0 ]; then
            zenity --info --text "$(gettext 'A bug report has been written.\nYou can send it next time you log in.')"
        else
            zenity --error --text "$(gettext 'Your bug could not be recorded successfully.\n')"
        fi
    else
        zenity --error --text "$(eval_gettext 'Cannot file bug:  \$apport_hook is not present.')"
    fi
}

backup_xorg_conf() {
    # TODO: backup xorg.conf more elegantly...
    xorg_conf_backup="/etc/X11/xorg.conf-backup-${timestamp}"
    cp /etc/X11/xorg.conf ${xorg_conf_backup}
    if [ $? != 0 ]; then
        return zenity --question --text "$(gettext 'Your config could not be backed up.\nDo you want to continue anyway?\n')"
    fi
}

default_config() {
    backup_xorg_conf || return 1

    rm /etc/X11/xorg.conf
    if [ $? == 0 ]; then
        zenity --info --text "$(gettext 'Your configuration has been restored to default,\nand your old configuration backed up.\nPlease restart.\n')"
    else
        zenity --error --text "$(gettext 'Failure restoring configuration to default.\nYour config has not been changed.')"
    fi
}

restore_default_config() {
    backup_xorg_conf || return 1
    rm /etc/X11/xorg.conf
}

view_xorg_log() {
    zenity --text-info --filename=$xorg_log --width=640 --height=480
}

view_gdm_log() {
    zenity --text-info --filename=${gdm_log_1} --width=640 --height=480
}

verify_xorgconf() {
    # Run Alberto's xorg.conf checker (once it's available in main)
    zenity --error --text "$(gettext 'Sorry, this option is not implemented yet')"
}

edit_config() {
    backup_xorg_conf || return 1

    xorg_conf_tmp=$(mktemp -t xorg.conf.XXXXXXXX)
    zenity --text-info --editable --filename=/etc/X11/xorg.conf --width=640 --height=480 > "${xorg_conf_tmp}" && mv "${xorg_conf_tmp}" /etc/X11/xorg.conf
    chmod 644 /etc/X11/xorg.conf
}

# Scan Xorg.0.log for errors
LOG_ERRORS=$(grep -e "^(EE)" $xorg_log)

if [ -z "$LOG_ERRORS" ]; then
    zenity --warning --text "$(gettext '<big><b>The system is running in low-graphics mode</b></big>\n\nYour screen, graphics card, and input device settings\ncould not be detected correctly.  You will need to configure these yourself.')"
else
    zenity --warning --text "$(gettext '<big><b>The system is running in low-graphics mode</b></big>\n\nThe following error was encountered.  You may need\nto update your configuration to solve this.\n\n')""${LOG_ERRORS}"
fi

# TODO: Add --window-icon "$app_icon" to all zenity windows

choice=""
while : ; do
    case "$choice" in
        ## Main Menu ##
        DEFAULT_RES_MODE ) restore_default_config; break ;;
        RECONFIGURE )     choice=$(display_reconfigure_menu) ;;
        TROUBLESHOOT )    choice=$(display_troubleshooting_menu) ;;
        FILE_BUG )        choice=$(display_filebug_menu) ;;

        ## Reconfigure Menu ##
        DEFAULT_CONFIG )  choice="RECONFIGURE"; default_config ;;
        SELECT_BACKUP )   choice="RECONFIGURE"; ;;

        ## Troubleshooting Menu ##
        VIEW_XORG_LOG )   choice="TROUBLESHOOT"; view_xorg_log ;;
        VIEW_GDM_LOG )    choice="TROUBLESHOOT"; view_gdm_log ;;
        VERIFY_XORGCONF ) choice="TROUBLESHOOT"; verify_xorgconf ;;
        EDIT_CONFIG )     choice="TROUBLESHOOT"; edit_config ;;
        EXIT_TO_CONSOLE ) choice="CONSOLE"; break ;;

        EXIT )          break ;;
        *)              choice=$(display_main_menu) || break ;;
    esac
done

if [ $choice == "CONSOLE" ]; then
    if [ -d /run/systemd ]; then
        chvt 7
        systemctl isolate multi-user.target
    else
        chvt 2
    fi
    exit
fi

if [ -d /run/systemd ]; then
    systemctl default
else
    start $dm | \
        zenity --progress --pulsate --text "$(gettext 'Stand by one minute while the display restarts...')"
fi
