#!/bin/sh -efu
# shellcheck disable=SC3043

PROG="${0##*/}"
VERSION='0.1.0'
YEAR=2026

RUNDIR=/run/install2

usage()
{
    [ "$1" = 0 ] || exec >&2
    cat <<EOF
Usage: $PROG [ options ] COMPONENT ACTION

Options:

  -v, --verbose    be verbose;

  -q, --quiet      be quiet;

  -V, --version    print program version and exit;

  -h, --help    show this text and exit.

Components:

  reader -- the screen reader;
  keyboard -- the onscreen keyboard;
  magnifier -- the digital screen magnifier.

Actions:

  available -- cheks if the component available;
  status -- checks if the component is running;
  start -- starts the component if it isn't running;
  stop -- stops the component if it is running;
  toggle -- starts or stops the component based on its current status.

Report bugs to https://bugzilla.altlinux.org/.
EOF
    exit "${1:-0}"
}

TEMP="$(getopt -n "$PROG" -o qvVh -l quiet,verbose,version,help -- "$@")" || usage 1
eval set -- "$TEMP"

verbose=
quiet=
while :; do
    case "$1" in
        -v|--verbose)
	    verbose=y
	    quiet=
            ;;
        -q|--quiet)
	    verbose=
	    quiet=y
            ;;
        -h|--help)
	    usage 0
            ;;
	-V|--version)
	    cat <<EOF
$VERSION $YEAR
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
EOF
	    exit 0
	    ;;
        --)
	    shift
	    break
            ;;
        *)
	    echo "$PROG: unrecognized option: $1" >&2
	    usage 1
            ;;
    esac
    shift
done

[ $# -eq 2 ] || usage 1

component="$1"; shift
action="$1"; shift

ORCA_PIDFILE="$RUNDIR"/orca.pid

write_pid() {
    mkdir -p "${2%/*}"
    echo "$1" >"$2"
}

screen_reader_status() {
    local pid=
    pid="$(cat "$ORCA_PIDFILE" 2>/dev/null)" ||:
    if [ -n "$pid" ]; then
        if kill -0 "$pid" 2>/dev/null; then
            [ -n "$quiet" ] || echo 'on'
            return 0
        fi
    fi

    rm -f "$ORCA_PIDFILE"
    [ -n "$quiet" ] || echo 'off'
    return 1
}

screen_reader_available() {
    if which orca 1>/dev/null 2>&1; then
        [ -n "$quiet" ] || echo 'yes'
	return 0
    else
        [ -n "$quiet" ] || echo 'no'
	return 1
    fi
}

# PLEASE NOTE, THAT IT IS ASSUMED THAT THE CODE BELOW
# IS RUN IN THE INSTALLER ENVIRONMENT ONLY! THAT'S WHY
# THE CONFIG FILES ARE SILENTLY OVERWRITTEN.
adjust_alsa() {
    mkdir -p "$HOME"/.config/speech-dispatcher
    cat <<EOF >"$HOME"/.config/speech-dispatcher/speechd.conf
AudioOutputMethod "alsa"
EOF

    cat <<EOF >"$HOME"/.asoundrc
pcm.!default pcm.sysdefault
ctl.!default ctl.sysdefault
EOF
}

run_screen_reader() {
    local orca_bin=
    orca_bin="$(which orca)" ||:

    if [ -z "$orca_bin" ]; then
	echo "ERROR: No screen reader is available" >&2
	return 1
    fi

    local pid=
    pid="$(cat "$ORCA_PIDFILE" 2>/dev/null)" ||:

    if [ -n "$pid" ]; then
        if kill -0 "$pid" 2>/dev/null; then
            # Already running.
            return 0
        else
            rm -f "$ORCA_PIDFILE"
        fi
    fi

    adjust_alsa

    (
	# don't hold the lock!
	exec 9>/dev/null
	"$orca_bin" --replace 1>"$RUNDIR"/orca.log 2>&1 &
	pid=$!
	write_pid "$pid" "$ORCA_PIDFILE"
    )
    pid="$(cat "$ORCA_PIDFILE")"

    local t=50
    while [ "$t" -ne 0 ]; do
        if kill -0 "$pid" 2>/dev/null; then
            t=20
            while [ "$t" -ne 0 ]; do
                sleep 0.1
                if ! kill -0 "$pid" 2>/dev/null; then
                    # Orca died for some reason.
                    err="$(tail -1 "$RUNDIR"/orca.log)"
                    echo "Unable to start the orca screen reader: $err" >&2
                    rm -f "$ORCA_PIDFILE"
                    return 1
                fi
                t=$((t - 1))
            done
            return 0
        else
            sleep 0.1
            t=$((t - 1))
        fi
    done

    rm -f "$ORCA_PIDFILE"
    echo 'Unable to start the orca screen reader.' >&2
    return 1
}

stop_screen_reader() {
    local pid=
    pid="$(cat "$ORCA_PIDFILE" 2>/dev/null)" ||:

    if [ -n "$pid" ]; then
        if kill -0 "$pid" 2>/dev/null; then
            if ! kill "$pid" >&2; then
                echo 'Unable to stop the orca screen reader.' >&2
		return 1
            else
                rm -f "$ORCA_PIDFILE"
            fi
        else
            # Already stopped for some reason.
            rm -f "$ORCA_PIDFILE"
        fi
    fi
}

onscreen_keyboard_status() {
    # To be implemented.
    [ -n "$quiet" ] || echo 'off'
    return 1
}

onscreen_keyboard_available() {
    # To be implemented.
    [ -n "$quiet" ] || echo 'no'
    return 1
}

run_onscreen_keyboard() {
    # To be implemented.
    return 1
}

stop_onscreen_keyboard() {
    # To be implemented.
    return 0
}

magnifier_status() {
    # To be implemented.
    [ -n "$quiet" ] || echo 'off'
    return 1
}

magnifier_available() {
    # To be implemented.
    [ -n "$quiet" ] || echo 'no'
    return 1
}

run_magnifier() {
    # To be implemented.
    return 1
}

stop_magnifier() {
    # To be implemented.
    return 0
}

mkdir -p "$RUNDIR"
(
    [ -z "$verbose" ] || \
	printf 'Trying to acquire %s...' "$RUNDIR/lockfile" >&2
    flock -x 9
    [ -z "$verbose" ] || echo " (success)" >&2

    case "$action" in
	available)
	    case "$component" in
		reader)
		    screen_reader_available
		    ;;
		keyboard)
		    onscreen_keyboard_available
		    ;;
		magnifier)
		    magnifier_available
		    ;;
		*)
		    usage 1
		    ;;
	    esac
	    ;;
	status)
	    case "$component" in
		reader)
		    screen_reader_status
		    ;;
		keyboard)
		    onscreen_keyboard_status
		    ;;
		magnifier)
		    magnifier_status
		    ;;
		*)
		    usage 1
		    ;;
	    esac
	    ;;
	start)
	    case "$component" in
		reader)
		    run_screen_reader
		    ;;
		keyboard)
		    run_onscreen_keyboard
		    ;;
		magnifier)
		    run_magnifier
		    ;;
		*)
		    usage 1
		    ;;
	    esac
	    ;;
	stop)
	    case "$component" in
		reader)
		    stop_screen_reader
		    ;;
		keyboard)
		    stop_onscreen_keyboard
		    ;;
		magnifier)
		    stop_magnifier
		    ;;
		*)
		    usage 1
		    ;;
	    esac
	    ;;
	toggle)
	    case "$component" in
		reader)
		    if screen_reader_status 1>/dev/null; then
			stop_screen_reader
		    else
			run_screen_reader
		    fi
		    ;;
		keyboard)
		    if onscreen_keyboard_status 1>/dev/null; then
			stop_onscreen_keyboard
		    else
			run_onscreen_keyboard
		    fi
		    ;;
		magnifier)
		    if magnifier_status 1>/dev/null; then
			stop_magnifier
		    else
			run_magnifier
		    fi
		    ;;
		*)
		    usage 1
		    ;;
	    esac
	    ;;
	*)
	    usage 1
	    ;;
    esac
) 9>"$RUNDIR"/lockfile
