#!/usr/bin/bash

# This file is part of Cockpit.
#
# Copyright (C) 2018 Red Hat, Inc.
#
# Cockpit is free software; you can redistribute it and/or modify it
# under the terms of the GNU Lesser General Public License as published by
# the Free Software Foundation; either version 2.1 of the License, or
# (at your option) any later version.
#
# Cockpit is distributed in the hope that it will be useful, but
# WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
# Lesser General Public License for more details.
#
# You should have received a copy of the GNU Lesser General Public License
# along with Cockpit; If not, see <http://www.gnu.org/licenses/>.

# Run a local bridge, web server, and browser for a particular Cockpit page.
# This is useful for integration into .desktop files, for systems which don't
# have cockpit.socket enabled. The web server and browser run in an unshared
# network namespace, and thus are totally isolated from everything else.
#
# Usage:
#     cockpit-desktop /cockpit/@localhost/system/index.html -t default -r 0
# For testing purposes one can also make cockpit-ws bind to all addresses
# (this is insecure and should not be used in prodcuction):
#     cockpit-desktop /cockpit/@localhost/system/index.html -t default -r 1
#
set -eu

THEME_ID="default"
WEBUI_REMOTE=0
while getopts t:r: option
do
    case "${option}"
        in
        t)THEME_ID=${OPTARG};;
        r)WEBUI_REMOTE=${OPTARG};;
        *) echo "Usage: $0 [-t THEME_ID] [-r WEBUI_REMOTE]" >&2
       exit 1 ;;
    esac
done

URL_PATH="/cockpit/@localhost/anaconda-webui/index.html"

WEBUI_ADDRESS="127.0.0.1"
if [[ "$WEBUI_REMOTE" == "1" ]]
then
    WEBUI_ADDRESS="0.0.0.0"
fi

echo "WEBUI_ADDRESS=$WEBUI_ADDRESS" > /tmp/webui-cockpit-ws.env
systemctl start webui-cockpit-ws

# Function to setup user-related environment
setup_user_environment() {
    # PKEXEC_UID is the uid for "gnome-initial-setup" or "liveuser"
    # depending on how the installer gets started.
    #
    # It's unset on non-live-images, so we just use the current user then (root)
    if [ -n "${PKEXEC_UID:-}" ]; then
      # If PKEXEC_UID is set, use the user associated with it
      INSTALLER_USER=$(id -n -u "${PKEXEC_UID}")
    else
      # Try to find another user who is not root and has /usr/bin/bash as their shell
      INSTALLER_USER=$(grep '/usr/bin/bash' /etc/passwd | grep -v '^root' | cut -d: -f1 | head -n 1)

      # If no such user is found, use the current user running the script
      if [ -z "${INSTALLER_USER:-}" ]; then
        INSTALLER_USER=$(id -un)
      fi
    fi

    # Get the home directory of the selected user
    HOME_DIR=$(grep "^$INSTALLER_USER:" /etc/passwd | cut -d: -f6)

    # Check if the home directory exists, otherwise create it
    if [ ! -d "$HOME_DIR" ]; then
      echo "The home directory $HOME_DIR does not exist. Creating it." >&2
      mkdir -p "$HOME_DIR"
      chown "$INSTALLER_USER" "$HOME_DIR"
    else
      echo "Home directory $HOME_DIR already exists." >&2
    fi

    # Return the user and home directory for further use
    echo "$INSTALLER_USER"
}

get_default_browser() {
    # Read the default browser from the anaconda runtime configuration file but wait till it's available
    # FIXME: Related to: https://issues.redhat.com/browse/INSTALLER-4223
    timeout=60
    elapsed=0

    while [ ! -f /run/anaconda/anaconda.conf ]; do
        if [ "$elapsed" -ge "$timeout" ]; then
            echo "Timed out waiting for anaconda.conf to be available." >&2
            exit 1
        fi
        sleep 1
        elapsed=$((elapsed + 1))
    done

    # FIXME: Should be provided as an argument to this script instead of grepping the config file
    DEFAULT_BROWSER=$(grep '^webui_web_engine =' /run/anaconda/anaconda.conf | cut -d'=' -f2)
    if [ -n "$DEFAULT_BROWSER" ]; then
        echo "Default browser set in anaconda.conf: $DEFAULT_BROWSER" >&2
        DEFAULT_BROWSER=$(echo "$DEFAULT_BROWSER" | sed 's/^[[:space:]]*//;s/[[:space:]]*$//')
        echo "$DEFAULT_BROWSER"
    else
        echo "No default browser set in anaconda.conf, using firefox." >&2
        echo "firefox"
    fi
}

prepare_firefox_cmd() {
    INSTALLER_USER=$1

    # prepare empty firefox profile dir with theme based on the passed profile id
    FIREFOX_THEME_DIR="/usr/share/anaconda/firefox-theme"
    FIREFOX_PROFILE_PATH="${XDG_RUNTIME_DIR}/anaconda/firefox-profile"

    # make sure the profile directory exists and is empty
    if [ -d ${FIREFOX_PROFILE_PATH} ]
    then
        echo "Cleaning up existing Anaconda Firefox profile directory." >&2
        rm -rf ${FIREFOX_PROFILE_PATH}
    fi
    pkexec --user "${INSTALLER_USER}" mkdir -p ${FIREFOX_PROFILE_PATH}

    # populate the profile directory with our custom Firefox theme
    # - theme id is passed as the second argument of this script
    THEME_PATH="${FIREFOX_THEME_DIR}/${THEME_ID}"

    pkexec --user "${INSTALLER_USER}" cp -a "${THEME_PATH}/." ${FIREFOX_PROFILE_PATH}

    # set environment for Firefox
    BROWSER_ENV=(MOZ_APP_TITLE="" MOZ_APP_REMOTINGNAME="liveinst" MOZ_GTK_TITLEBAR_DECORATION=client)

    BROWSER=(/usr/bin/env "${BROWSER_ENV[@]}" /usr/bin/firefox --new-instance --profile "${FIREFOX_PROFILE_PATH}")

    declare -p BROWSER
}


if [[ "$WEBUI_REMOTE" == "1" ]]
then
    /bin/sleep infinity &
    BLOCK_ON_PID=$!
else
    USER_INFO=$(setup_user_environment)
    INSTALLER_USER=$(echo "$USER_INFO" | cut -d' ' -f1)
    HOME_DIR=$(echo "$USER_INFO" | cut -d' ' -f2)

    # if we have netcat, use it for waiting until ws is up
    if type nc >/dev/null 2>&1; then
        for _ in `seq 10`; do
            nc -z "$WEBUI_ADDRESS" 80 && break
            sleep 0.5;
        done
    else
        # otherwise, just wait a bit
        sleep 3
    fi

    readarray -t user_environment < <(pkexec --user "${INSTALLER_USER}" env XDG_RUNTIME_DIR="${XDG_RUNTIME_DIR}" systemctl --user show-environment)

    DEFAULT_BROWSER_CMD=$(get_default_browser)
    echo "Using default browser: ${DEFAULT_BROWSER_CMD}" >&2
    if [[ "${DEFAULT_BROWSER_CMD}" == "firefox" ]]; then
        eval "$(prepare_firefox_cmd "$INSTALLER_USER")"
        echo "Using Firefox browser command: ${BROWSER[@]}" >&2
    else
        BROWSER=(${DEFAULT_BROWSER_CMD})
        echo "Using default browser command: ${BROWSER[@]}" >&2
    fi

    # start browser in a temporary home dir, so that it does not interfere with your real one
    BROWSER_HOME=$(mktemp --directory --tmpdir cockpit.desktop.XXXXXX)
    HOME="$BROWSER_HOME" XDG_CURRENT_DESKTOP=GNOME \
    pkexec --user $INSTALLER_USER env DISPLAY=$DISPLAY "${user_environment[@]}" "${BROWSER[@]}" http://"$WEBUI_ADDRESS""$URL_PATH" &
    BLOCK_ON_PID=$!
fi

# Cleanup function
cleanup() {
    set +e
    kill $BLOCK_ON_PID
    [[ -n $BROWSER_HOME ]] && rm -rf $BROWSER_HOME
}
trap 'cleanup' EXIT INT QUIT PIPE

wait $BLOCK_ON_PID
