#!/bin/bash

# This script can be used to trigger a reset of the system and 
# to check if the requested reset was successfully executed.

# Description:
#   - The script will do the following steps:
#       |--> Validate the input parameter
#       |--> Set the default paths for the LEDs
#       |--> In case cel-service-button application is installed 
#       |    get the LEDs from the config.json instead the default ones
#       |--> In case the script was called with the check parameter: 
#           |--> Check if the root-ro script returned an success or error via an magic file
#           |--> Give feedback to the user if the reset was successful or not
#           |--> Exit
#       |--> In case the script was called with the factory parameter: 
#           |--> Check if the script was called directly or by another application
#           |--> Ask interactively if the user is sure to reset the system (in case of direct call)
#           |--> Create magic file to indicate the root-ro script to execute a factory reset
#           |--> Write cache to device
#           |--> Validate that magic file was created properly
#           |--> Signal sucess or error of requesting the reset (in case of direct call)
#           |--> Try reboot and if that is failing force reboot (in case of direct call)
#           |--> Exit

    

# ==========================
#      Functions
# ==========================

usage() {

    echo -e "cel-system-reset:\n"

    echo -e "\tScript which requests a system reset and checks the result after rebooting.\n"

    echo -e "\tUsage: $0 [factory|check]\n"

    echo -e "\tversion: ${SCRIPT_VERSION}\n"
}

# Function to get the name (CMD) of the parent process
get_parent_process() {
    # Get the process name (CMD) of the parent process using the BASH ro variable PPID
    PARENT_PROCESS=$(ps -o comm= -p ${PPID})

    # Check if the parent process is bash or sudo
    if [ "${PARENT_PROCESS}" == "bash" ] || [ "${PARENT_PROCESS}" == "sudo" ]
    then
        # When parent process is bash the script was called directly
        # so set a flag to execute later on the reboot which otherwise 
        # should be handled by the invoking application.
        # When it was called by another application or script PARENT_PROCESS
        # would be <script-name>.sh or <application-name>. 
        echo "cel-system-reset: The script was called directly."
        DIRECT_CALL=true
    fi
}

# Function to activate the failure LED for 3 seconds
signal_failure() {
    if [ -w "$SYSFS_PATH_LED_FAILURE" ]
    then
        echo 1 > "$SYSFS_PATH_LED_FAILURE"
        sleep 3
        echo 0 > "$SYSFS_PATH_LED_FAILURE"
    fi
}

# Function to activate the success LED for 3 seconds
signal_sucess() {
    if [ -w "$SYSFS_PATH_LED_SUCCESS" ]
    then
        echo 1 > "$SYSFS_PATH_LED_SUCCESS"
        sleep 3
        echo 0 > "$SYSFS_PATH_LED_SUCCESS"
    fi
}

# ==========================
#      Initialization
# ==========================

# Check if the script is executed with root permissions
if [ "$(whoami)" != root ]
then
    # Inform the user that he has to run the script as root
    echo "cel-system-reset: To execute this script you need root privileges."
    exit 1
fi

SCRIPT_VERSION="1.1.0"

# Check the amount of input parameters
if [ "$#" -ne 1 ]
then
    echo -e "cel-system-reset: Illegal amount of input parameters.\n"
    usage
    exit 1
fi

# Get the input parameter
COMMAND="${1}"


# Validate the input parameter
if [ -z "${COMMAND}" ]
then
    echo -e "cel-system-reset: No action was provided. Please provide the action as input parameter [factory|check].\n"
    usage
    exit 1
fi

if [ "${COMMAND}" != "factory" ] && [ "${COMMAND}" != "check" ]
then
    echo -e "cel-system-reset: The provided action (${COMMAND}) is not valid. Please provide a valid command [factory|check].\n"
    usage
    exit 1
fi

# Initialize flags for errors and a direct call
FAILURE=false
DIRECT_CALL=false

# Set the default paths for the LEDs
SYSFS_PATH_LED_SUCCESS="/sys/class/leds/yellow/brightness"
SYSFS_PATH_LED_FAILURE="/sys/class/leds/red/brightness"

# In case cel-service-button application is installed 
# get the LEDs from the config.json instead the default ones
if [ -f /etc/cel-service-button/config.json ]
then
    SYSFS_PATH_LED_SUCCESS=$(jq -r '.led.success' < /etc/cel-service-button/config.json)
    SYSFS_PATH_LED_FAILURE=$(jq -r '.led.failure' < /etc/cel-service-button/config.json)
fi

# Check if LEDs are available and accessible
if ! [ -w "$SYSFS_PATH_LED_SUCCESS" ] || ! [ -w "$SYSFS_PATH_LED_FAILURE" ]
then
    echo "cel-system-reset: No LEDs available for signaling the state."
fi

# ==========================
#      Main part
# ==========================

# In case the script was called with the check option just validate if the root-ro script returned an error
if [ "${COMMAND}" == "check" ]
then
    echo "cel-system-reset: This script will check if the system reset was successful." 

    # Check if a reset was requested but not executed yet (in that case the the file was 
    # created manually or the script was executed by another application which doesn't reboot the system)
    if [ -f /data/.root-rw/reset-factory ]
    then
        echo "cel-system-reset: A factory reset was requested but not executed yet."
        echo "cel-system-reset: Please reboot the system manually to execute the factory reset."
        exit 0
    fi

    # Check if reset was already executed before (in case the check mode was executed manually) 
    if [ ! -f /data/.root-rw/reset-done ]
    then
        echo "cel-system-reset: There was no factory reset done. You can use this script to reset the system."
        exit 0
    fi

    # Check if magic file signaling result is present
    if [ -f /data/.root-rw/reset-success ]
    then
        echo "cel-system-reset: System reset was successful"
        signal_sucess
    elif [ -f /data/.root-rw/reset-error ]
    then
        echo "cel-system-reset: System reset has failed"
        signal_failure
    else
        echo "cel-system-reset: There was a reset done but no result available, which signals in all cases an error."
        signal_failure
    fi

    # Remove magic files (independent of the result)
    rm -f /data/.root-rw/reset-*

    # Exit here because the rest of the script is not needed when the check option was used
    exit 0
fi

# Get the name of the parent process
get_parent_process

# Check if there are already magic file(s) created for different reset target(s), which can be when the file was created manually
#   redirect stderr to /dev/null to suppress the error message when no file is found
rm -f /data/.root-rw/reset-* 2> /dev/null

# Check here in case of direct call
if $DIRECT_CALL
then
    # Ask interactively if the user is sure to reset the system
    read -p "Are you sure you want to reset the system? [y/n]: " -r

    # Stop here and exit in case it was not y|Y
    if ! [ "$REPLY" == "y" ] && ! [ "$REPLY" == "Y" ]
    then
        echo "cel-system-reset: The system reset was canceled."
        exit 0
    fi
fi

if [ "$COMMAND" == "factory" ]
then
    echo "cel-system-reset: This script will take care that the system will be reset completely (factory reset)."

    # Create magic file to indicate the root-ro script to empty the upper layer of the overlay
    touch /data/.root-rw/reset-factory

    # Write cache to device
    sync

    # Validate if file was created properly
    if [ ! -f /data/.root-rw/reset-factory ]
    then
        echo "cel-system-reset: An error occurred while creating the magic file for the factory reset."
        FAILURE=true
    fi
fi

# When the script was called directly do the signaling and rebooting here
if $DIRECT_CALL
then
    # Check if there where any errors
    if $FAILURE
    then
        echo "cel-system-reset: The ${COMMAND} reset couldn't be successfully requested. The system will now reboot."
        signal_failure
    else
        echo "cel-system-reset: The ${COMMAND} reset has been successfully requested. The system will now reboot."
        signal_sucess
    fi

    # Check if the reboot was successful and if not try to forced reboot
    if ! /usr/sbin/reboot
    then
        echo "cel-system-reset: The requested reboot failed so reboot will be forced now."
        /usr/sbin/reboot --force
    fi
fi
