#!/usr/bin/env python3
import os
import time
import shlex
import subprocess
from evdev import InputDevice, ecodes

# ==========================
# DEFAULT CONFIG
# ==========================

DEFAULTS = {
    "TOUCH_DEVICE": "/dev/input/event5",
    "SWIPE_MIN_DISTANCE": "150",
    "SWIPE_MAX_DURATION": "0.5",
    "SWIPE_DOMINANCE_RATIO": "2.0",
    "SWIPE_UP_CMD": "xdotool key XF86Launch9",
    "SWIPE_LEFT_CMD": "xdotool key 'Ctrl+F10'",
    "SWIPE_RIGHT_CMD": "xdotool key 'Ctrl+F10'",
}

# Apply defaults
for k, v in DEFAULTS.items():
    os.environ.setdefault(k, v)

# ==========================
# RUNTIME CONFIG
# ==========================

DEVICE = os.environ["TOUCH_DEVICE"]
MIN_DISTANCE = int(os.environ["SWIPE_MIN_DISTANCE"])
MAX_DURATION = float(os.environ["SWIPE_MAX_DURATION"])
DOMINANCE_RATIO = float(os.environ["SWIPE_DOMINANCE_RATIO"])

COMMANDS = {
    "up":    os.environ.get("SWIPE_UP_CMD"),
    "down":  os.environ.get("SWIPE_DOWN_CMD"),
    "left":  os.environ.get("SWIPE_LEFT_CMD"),
    "right": os.environ.get("SWIPE_RIGHT_CMD"),
}

# ==========================
# X11 ENV (hard requirement)
# ==========================

os.environ.setdefault("DISPLAY", ":0")
os.environ.setdefault("XAUTHORITY", os.path.expanduser("~/.Xauthority"))

# ==========================
# STATE
# ==========================

dev = InputDevice(DEVICE)

tracking = False
start_x = start_y = None
last_x = last_y = None
start_time = None

# ==========================
# HELPERS
# ==========================

def run_command(cmd):
    if not cmd:
        return
    subprocess.Popen(shlex.split(cmd))

def handle_swipe(dx, dy, duration):
    if duration > MAX_DURATION:
        return

    abs_dx = abs(dx)
    abs_dy = abs(dy)

    if abs_dy > MIN_DISTANCE and abs_dy > abs_dx * DOMINANCE_RATIO:
        if dy < 0:
            run_command(COMMANDS["up"])
        else:
            run_command(COMMANDS["down"])

    elif abs_dx > MIN_DISTANCE and abs_dx > abs_dy * DOMINANCE_RATIO:
        if dx > 0:
            run_command(COMMANDS["right"])
        else:
            run_command(COMMANDS["left"])

# ==========================
# EVENT LOOP
# ==========================

for event in dev.read_loop():
    if event.type != ecodes.EV_ABS:
        continue

    if event.code == ecodes.ABS_MT_TRACKING_ID:
        if event.value != -1:
            tracking = True
            start_time = time.time()
            start_x = start_y = None
        else:
            if tracking and start_x is not None:
                duration = time.time() - start_time
                dx = last_x - start_x
                dy = last_y - start_y
                handle_swipe(dx, dy, duration)

            tracking = False
            start_x = start_y = None

    elif event.code == ecodes.ABS_MT_POSITION_X:
        last_x = event.value
        if start_x is None:
            start_x = last_x

    elif event.code == ecodes.ABS_MT_POSITION_Y:
        last_y = event.value
        if start_y is None:
            start_y = last_y

