#!/usr/bin/env bash
#-------------------------------------------------#
# bbacklight Copyright (C) 2020 Giuseppe Eletto   #
# This program comes with ABSOLUTELY NO WARRANTY. #
# This is free software, and you are welcome      #
# to redistribute it under certain conditions.    #
#-------------------------------------------------#

# ------------------------
# Constants
# ------------------------

VERSION=1.1.7
PROCESS=$$

FILE_MAX_VAL="max_brightness"
FILE_VAL="brightness"

DEF_SYS_BL="/sys/class/backlight"
DEF_DEVICE="$( ls "$DEF_SYS_BL" | head -n 1 )"


# ------------------------
# Secondary Functions
# ------------------------

show_help() {
  cat <<EOF
Usage: bbacklight <command>
  where <command> are:
  -help
      Show this help text
  -version
      Show version
      And, possibly, if a different version is available on GitHub
  -get [raw]
      Show the current brightness percentage (rounded down)
      If 'raw' is provided, it shows the current brightness value
  -inv <percentage> (w/o % symbol)
      Increase the brightness by a percentage value decided by the user
  -dec <percentage> (w/o % symbol)
      Decrease the brightness by a percentage value decided by the user
  -set <percentage> (w/o % symbol)
      Set the brightness to a percentage value decided by the user
  -d <device>
      Choose which device to change the brightness or request the current value
      The default device is the first entry of dir '/sys/class/backlight'
EOF
  exit 0
}

show_version() {
  if command -v curl > /dev/null 2>&1; then
    GH_VER="curl -s -H"
  elif command -v wget > /dev/null 2>&1; then
    GH_VER="wget -q -O - --header"
  fi

  if [ -n "$GH_VER" ]; then
    GH_VER="$( $GH_VER "Accept: application/vnd.github.v3+json" https://api.github.com/repos/giuseppe998e/bbacklight/tags )"
    GH_VER="$( echo "$GH_VER" | grep -o -E "\"name\": \".+\"" | head -n 1 | cut -d "\"" -f 4 )"

    if [ "$GH_VER" != "v$VERSION" ]; then
      echo "$VERSION (Different version available: $GH_VER)"
      exit 0
    fi
  fi
  
  echo "$VERSION"
  exit 0
}

print_error() {
  printf "%s\n" "Error: $1" >&2
  kill -10 $PROCESS
}

get_opt_arg() {
  if [ -z "$2" ] || [ "$(printf '%s' "$2" | cut -c 1)" = "-" ]; then
    print_error "Argument for '$1' option is missing"
  fi

  echo "$2"
}

pct_to_val() {
  if [ "$1" -gt 100 ] || [ "$1" -lt 0 ]; then
    print_error "Possible values are 0 ... 100"
  fi

  # FIXME $MAX_BRIGHT values less than 100 returns float
  echo "$(( "$1" * "$MAX_BRIGHT" / 100 ))"
}


# ------------------------
# Primary Functions
# ------------------------

get_bright() {
  if [ "$1" != "raw" ]; then
    # FIXME Shows the current percentage of brightness (rounded down) with fake decimals
    echo "$(( "$ACT_BRIGHT" * 100 / "$MAX_BRIGHT" )).00000"
  else
    echo "$ACT_BRIGHT"
  fi
}

inc_bright() {
  CALC_VAL="$( pct_to_val "$1" )"
  MAX_VAL="$(( "$MAX_BRIGHT" - "$ACT_BRIGHT" ))"

  if [ "$MAX_VAL" -le 0 ]; then
    print_error "Max value reached"
  elif [ "$CALC_VAL" -gt "$MAX_VAL" ]; then
    CALC_VAL="$MAX_VAL"
  fi

  echo "$(( "$ACT_BRIGHT" + "$CALC_VAL" ))" > "$DBP/$FILE_VAL"
}

dec_bright() {
  CALC_VAL="$( pct_to_val "$1" )"

  if [ "$ACT_BRIGHT" -le 0 ]; then
    print_error "Min value reached"
  elif [ "$CALC_VAL" -lt "$ACT_BRIGHT" ]; then
    echo "$(( "$ACT_BRIGHT" - "$CALC_VAL" ))" > "$DBP/$FILE_VAL"
  else
    echo "0" > "$DBP/$FILE_VAL"
  fi
}

set_bright() {
  pct_to_val "$1" > "$DBP/$FILE_VAL"
}


# ------------------------
# Main "Function"
# ------------------------

# Execute "exit 1" when SIGUSR1
trap "exit 1" USR1 

# Set global var DBP (default)
DBP="$DEF_SYS_BL/$DEF_DEVICE"

# Custom "getopts" for options management
while [ "$#" -gt 0 ]; do
  case "$1" in
    -get)
      WTD=1
      if [ -n "$2" ] && [ "$(printf '%s' "$2" | cut -c 1)" != "-" ]; then
        ARG="$2"
        shift
      fi
    ;;
    -inc)
      WTD=2
      ARG=$( get_opt_arg "$1" "$2" )
      shift
    ;;
    -dec)
      WTD=3
      ARG=$( get_opt_arg "$1" "$2" )
      shift
    ;;
    -set)
      WTD=4
      ARG=$( get_opt_arg "$1" "$2" )
      shift
    ;;
    -d)
      DBP="$DEF_SYS_BL/$( get_opt_arg "$1" "$2" )" # Set global var DBP (custom)
      shift
    ;;
    -help);;
    -version) show_version;;
    -?*) print_error "Unknown flag '$1'";;
    *) break;;
  esac
  shift
done

# Show help text if no action was chosen (or -help)
if [ -z "$WTD" ]; then
  show_help
fi

# Check SYS permissions
if [ ! -d "$DBP" ]; then
  print_error "Path '$DBP' not found"
fi

if [ ! -r "$DBP/$FILE_MAX_VAL" ]; then
  print_error "File '$DBP/$FILE_MAX_VAL' does not have read permissions"
fi

if [ ! -r "$DBP/$FILE_VAL" ]; then
  print_error "File '$DBP/$FILE_VAL' does not have read permissions"
fi

if [ ! -w "$DBP/$FILE_VAL" ]; then
  print_error "File '$DBP/$FILE_VAL' does not have write permissions"
fi

# Set global var MAX_BRIGHT
read -r MAX_BRIGHT < "$DBP/$FILE_MAX_VAL"

# Set global var ACT_BRIGHT
read -r ACT_BRIGHT < "$DBP/$FILE_VAL"

# Perform the desired action
case "$WTD" in
  1) get_bright "$ARG";;
  2) inc_bright "$ARG";;
  3) dec_bright "$ARG";;
  4) set_bright "$ARG";;
esac
