#!/bin/bash

## Copyright (C) 2025 - 2025 ENCRYPTED SUPPORT LLC <adrelanos@whonix.org>
## See the file COPYING for copying conditions.

#set -x

set -o errexit
set -o nounset
set -o errtrace
set -o pipefail

true "$0: START"

source /usr/libexec/helper-scripts/lockfile.sh
source /usr/libexec/helper-scripts/strings.bsh

manual_debugging=false
#manual_debugging=true

bl_pct_file='/run/backlight-tool-dist/bl_pct'

if [ "$manual_debugging" = "true" ]; then
  ## Hardcoded. 'backlight-tool-dist-agent' uses 'leaprun'.
  ## Therefore '$HOME' cannot be used.
  cd "/home/user/derivative-maker/packages/kicksecure/desktop-config-dist"
  kernel_backlight_folder=./backlight-tool-test
else
  kernel_backlight_folder=/sys/class/backlight
fi

get_backlight_driver() {
  local bl_driver bl_driver_prio bl_dir cur_bl_driver_type cur_bl_driver_prio;

  bl_driver=""
  bl_driver_prio=""

  ## Manual debugging.
  #for bl_dir in ./backlight-tool-test/* ; do

  for bl_dir in "${kernel_backlight_folder}/"* ; do
    if [ ! -d "$bl_dir" ] ; then
      true "INFO: bl_dir '$bl_dir' is not a folder."
      continue
    fi
    if ! test -f "${bl_dir}/type" ; then
      true "INFO: file '${bl_dir}/type' does not exist."
      continue
    fi
    if ! cur_bl_driver_type="$(stcat "${bl_dir}/type")" ; then
      true "INFO: stcat file '${bl_dir}/type' failed."
      continue
    fi
    case "$cur_bl_driver_type" in
      ## LXQt's backlight helper prioritizes backlight drivers with `firmware`
      ## being most preferable, `platform` below `firmware`, `raw` below
      ## `platform`, and everything else below `raw`. Replicate that behavior
      ## here.
      'firmware') cur_bl_driver_prio='4';;
      'platform') cur_bl_driver_prio='3';;
      'raw')      cur_bl_driver_prio='2';;
      *)          cur_bl_driver_prio='1';;
    esac
    if (( cur_bl_driver_prio >= bl_driver_prio )); then
      bl_driver="$bl_dir"
      bl_driver_prio="$cur_bl_driver_prio"
    fi
  done

  if [ -z "$bl_driver" ]; then
    printf '%s\n' "$0: ERROR: No backlight driver found!" >&2
    return 1
  fi
  true "INFO: bl_driver is '$bl_driver'."
  printf '%s\n' "$bl_driver"
}

backlight_get_val() {
  local bl_pct bl_brightness bl_max_brightness

  if ! bl_brightness="$(read_integer_file "${bl_driver}/actual_brightness")" ; then
    printf '%s\n' "$0: ERROR: Missing or invalid 'actual_brightness' file for backlight driver '$bl_driver'!" >&2
    return 1
  fi
  if ! bl_max_brightness="$(read_integer_file "${bl_driver}/max_brightness")" ; then
    printf '%s\n' "$0: ERROR: Missing or invalid 'max_brightness' file for backlight driver '$bl_driver'!" >&2
    return 1
  fi

  bl_pct=$(( bl_brightness * 100 )) || true
  bl_pct=$(( bl_pct / bl_max_brightness )) || true

  if (( bl_pct < 1 )); then
    bl_pct='1'
  elif (( bl_pct > 100 )); then
    bl_pct='100'
  fi
  true "INFO: bl_pct is '$bl_pct'."
  printf '%s\n' "$bl_pct"
}

backlight_set_val() {
  local bl_pct bl_max_brightness calc_bl_brightness;

  bl_pct="${1:-}"
  if [ -z "$bl_pct" ]; then
    printf '%s\n' "$0: ERROR: No backlight percentage specified!" >&2
    return 1
  fi
  if ! is_whole_number "${bl_pct}"; then
    printf '%s\n' "$0: ERROR: Backlight percentage is not a whole number!" >&2
    return 1
  fi

  if ! bl_max_brightness="$(read_integer_file "${bl_driver}/max_brightness")" ; then
    printf '%s\n' "$0: ERROR: Missing or invalid 'max_brightness' file for backlight driver '$bl_driver'!" >&2
    return 1
  fi

  calc_bl_brightness=$(( bl_max_brightness * bl_pct )) || true
  calc_bl_brightness=$(( calc_bl_brightness / 100 )) || true

  if [ "$calc_bl_brightness" = '0' ]; then
    calc_bl_brightness='1'
  fi

  ## TODO: use 'overwrite' (does not support yet writing to kernel files)
  true "INFO: over writing file '${bl_driver}/brightness' with value '$calc_bl_brightness'"
  if ! printf '%s\n' "$calc_bl_brightness" > "${bl_driver}/brightness" ; then
    printf '%s\n' "$0: ERROR: Could not write brightness value to '${bl_driver}/brightness'!" >&2
    return 1
  fi

  if [ "$manual_debugging" = "true" ] ; then
    if ! printf '%s\n' "$calc_bl_brightness" > "${bl_driver}/actual_brightness" ; then
      true "INFO: Unable to update '${bl_driver}/actual_brightness' during manual debugging."
      return 1
    fi
  fi
}

backlight_set_val_from_file() {
  local bl_pct

  if ! bl_pct="$(read_integer_file "$bl_pct_file" '1' '100')" ; then
    printf '%s\n' "$0: ERROR: Missing or invalid backlight percentage data!" >&2
    return 1
  fi

  backlight_set_val "$bl_pct" || return 1
}

backlight_mod_val() {
  local mode bl_pct

  mode="${1:-}"
  if [ "$mode" != 'inc' ] && [ "$mode" != 'dec' ]; then
    printf '%s\n' "$0: ERROR: Invalid mode specified for 'backlight_mod_val'!"
    return 1
  fi

  ## backlight_get_val is guaranteed to return an integer if it succeeds.
  if ! bl_pct="$(backlight_get_val)" ; then
    printf '%s\n' "$0: ERROR: Could not get backlight brightness percentage!"
    return 1
  fi

  if [ "$mode" = 'inc' ]; then
    if (( bl_pct == 1 )); then
      bl_pct='5'
    else
      (( bl_pct += 5 )) || true
    fi
  else
    (( bl_pct -= 5 )) || true
  fi

  if (( bl_pct < 1 )); then
    bl_pct=1
  elif (( bl_pct > 100 )); then
    bl_pct=100
  fi

  backlight_set_val "$bl_pct" || return 1
}

bl_driver="$(get_backlight_driver)" || exit 1

case "${1:-}" in
  'get') backlight_get_val || exit 1;;
  'set') backlight_set_val_from_file || exit 1;;
  'inc') backlight_mod_val 'inc' || exit 1;;
  'dec') backlight_mod_val 'dec' || exit 1;;
  '')
    printf '%s\n' "$0: ERROR: No mode specified!" >&2
    exit 1
    ;;
  *)
    printf '%s\n' "$0: ERROR: Unrecognized mode '$1' specified!" >&2
    exit 1
    ;;
esac

true "$0: END"
