#!/usr/bin/env bash
set -euo pipefail

usage() {
    cat <<'EOF'
Usage:
  ./generate-egtouch-ini.sh [--output FILE] [--detect-rotation 0|1] [MONITOR...]

Examples:
  ./generate-egtouch-ini.sh HDMI-1 HDMI-2 > eGTouchL.ini
  ./generate-egtouch-ini.sh --output /tmp/eGTouchL.ini HDMI-1 DP-1
  sudo ./generate-egtouch-ini.sh --output /etc/eGTouchL.ini HDMI-1 DP-1

Detects eGalax/EETI input devices with USB VID 0eef and writes one
[Device_No.X] block per detected controller.

Physical_Address is generated from /proc/bus/input/devices "P: Phys=":
  usb-0000:00:14.0-1/input0
EOF
}

output=""
detect_rotation="1"
monitors=()

while [ "$#" -gt 0 ]; do
    case "$1" in
        --output|-o)
            output="${2:-}"
            [ -n "$output" ] || { echo "Missing value for --output" >&2; exit 2; }
            shift 2
            ;;
        --detect-rotation)
            detect_rotation="${2:-}"
            [ "$detect_rotation" = "0" ] || [ "$detect_rotation" = "1" ] || {
                echo "--detect-rotation must be 0 or 1" >&2
                exit 2
            }
            shift 2
            ;;
        --help|-h)
            usage
            exit 0
            ;;
        *)
            monitors+=("$1")
            shift
            ;;
    esac
done

require_cmd() {
    command -v "$1" >/dev/null 2>&1 || {
        echo "Required command not found: $1" >&2
        exit 1
    }
}

read_first_line() {
    local path="$1"
    [ -r "$path" ] || return 1
    sed -n '1p' "$path"
}

auto_monitors() {
    command -v xrandr >/dev/null 2>&1 || return 0
    xrandr --query 2>/dev/null | awk '$2 == "connected" { print $1 }'
}

physical_addresses=()

if [ -r /proc/bus/input/devices ]; then
    while IFS= read -r phys; do
        [ -n "$phys" ] && physical_addresses+=("$phys")
    done < <(
        awk '
            BEGIN { RS=""; FS="\n"; IGNORECASE=1 }
            /Vendor=0eef/ {
                phys = ""
                handlers = ""
                for (i = 1; i <= NF; i++) {
                    if ($i ~ /^P: Phys=/) {
                        phys = $i
                        sub(/^P: Phys=/, "", phys)
                    }
                    if ($i ~ /^H: Handlers=/) {
                        handlers = $i
                    }
                }
                if (phys ~ /^usb-/ && phys ~ /\/input[0-9]+$/ && handlers ~ /event[0-9]+/) {
                    if (!seen[phys]++) {
                        print phys
                    }
                }
            }
        ' /proc/bus/input/devices
    )
else
    echo "/proc/bus/input/devices is not readable." >&2
fi

if [ "${#physical_addresses[@]}" -eq 0 ]; then
    echo "No eGalax/EETI input devices found. Expected USB VID 0eef." >&2
    exit 1
fi

if [ "${#monitors[@]}" -eq 0 ]; then
    while IFS= read -r monitor; do
        [ -n "$monitor" ] && monitors+=("$monitor")
    done < <(auto_monitors)
fi

make_device_block() {
    local index="$1"
    local physical_address="$2"
    local monitor="${3:-null}"

    cat <<EOF
[Device_No.${index}]
Physical_Address		${physical_address}
SupportPoints			10
VirtualDevName			null
SendRawPoints			0
Direction			0
Orientation			0
EdgeCompensate			0
	EdgeLeft			100
	EdgeRight			100
	EdgeTop				100
	EdgeBottom			100
HoldFilterEnable		0
	HoldRange			20
SplitRectMode			0
	CustomRectLeft			0
	CustomRectRight			2047
	CustomRectTop			0
	CustomRectBottom		2047
MonitorName			${monitor}
DetectRotation			${detect_rotation}
ReportMode			1
EventType			0
BtnType				0
RightClickEnable		1
	RightClickDuration		1500
	RightClickRange			20
BeepState			0
	BeepDevice			0
	BeepFreq			1000
	BeepLen				200
VKEYEnable			0
	VKEYReportMod			1
	VKEY_0				0
[EndOfDevice]

EOF
}

generate_ini() {
    local count="${#physical_addresses[@]}"

    cat <<EOF
[eGTouchL.ini]
DebugEnableBits			1
ShowDebugPosition		0
RemoveDriverLog			1
DeviceNums			${count}
BaudRate			0
ScanInterface			1
UseDriverCalib			0
SkipFirstByte			0
ShiftByteBothEnd		1
ScanDevStartDelayTime		0
ScanDevInterval			50
RS232HWFlowCtl			1
MouseDevDisable			0

[String]
SerialPath0			default
SerialPath1			default
DevPID0				null
DevPID1				null
eGalaxTool			/tmp

EOF

    local i
    for i in "${!physical_addresses[@]}"; do
        make_device_block "$i" "${physical_addresses[$i]}" "${monitors[$i]:-null}"
    done

    cat <<'EOF'
[EndOfFile]
EOF
}

tmp_file="$(mktemp)"
generate_ini > "$tmp_file"

if [ -n "$output" ]; then
    if [ -e "$output" ]; then
        cp -a "$output" "${output}.bak.$(date +%Y%m%d-%H%M%S)"
    fi
    cat "$tmp_file" > "$output"
    echo "Wrote $output with ${#physical_addresses[@]} device block(s)." >&2
else
    cat "$tmp_file"
fi

rm -f "$tmp_file"
