#!/usr/bin/python3
# -*- coding: utf-8 -*-

import time
import os
import configparser
import subprocess
import threading

# 1. FORÇA a biblioteca a usar o novo padrão do Trixie (libgpiod)
os.environ["GPIOZERO_PIN_FACTORY"] = "lgpio"
from gpiozero import Button, LED, OutputDevice

CONFIG_PATH = os.getenv(
    "RPI_POWERBUTTON_CONFIG",
    "/etc/rpi-powerbutton/rpi-powerbutton.conf"
)

config_defaults = {
    "pin": 16,
    "pull_up": False,
    "led_enabled": True,
    "led_pin": 20,
    "led_mode": 0,
    "led_modes": [(100,1900),(100,100),(30,30),(100,0)],
    "reboot_time": 3000,
    "shutdown_time": 5000
}

def parse_modes(modes_str):
    modes = []
    for pair in modes_str.split(';'):
        on, off = pair.split(',')
        modes.append((int(on), int(off)))
    return modes

def load_config():
    cfg = configparser.ConfigParser()
    if not os.path.exists(CONFIG_PATH):
        return config_defaults
    
    cfg.read(CONFIG_PATH)
    conf = config_defaults.copy()

    # Lendo a seção [btn-config]
    if cfg.has_section("btn-config"):
        conf["pin"]     = cfg.getint("btn-config", "pin", fallback=conf["pin"])
        conf["pull_up"] = cfg.getboolean("btn-config", "pull_up", fallback=conf["pull_up"])
        
    # Lendo a seção [led-config]
    if cfg.has_section("led-config"):
        conf["led_enabled"] = cfg.getboolean("led-config", "enabled", fallback=conf["led_enabled"])
        conf["led_pin"]     = cfg.getint("led-config", "pin",  fallback=conf["led_pin"])
        conf["led_mode"]    = cfg.getint("led-config", "mode", fallback=conf["led_mode"])
        
        modes_str = cfg.get("led-config", "modes", fallback=None)
        if modes_str:
            conf["led_modes"] = parse_modes(modes_str)
            
    # Lendo a seção [action]
    if cfg.has_section("action"):
        conf["reboot_time"]   = cfg.getint("action", "reboot_time",   fallback=conf["reboot_time"])
        conf["shutdown_time"] = cfg.getint("action", "shutdown_time", fallback=conf["shutdown_time"])
        
    return conf

# ================================
#        Controle do LED
# ================================
def led_worker(led, conf):
    while True:
        if not conf["led_enabled"]:
            time.sleep(1)
            continue

        current_mode = conf["led_mode"]
        mode = conf["led_modes"][current_mode]
        
        on_time  = mode[0] / 1000.0
        off_time = mode[1] / 1000.0

        led.on()
        
        # Sleep inteligente com resposta ultra-rápida (20ms)
        end_time = time.time() + on_time
        while time.time() < end_time:
            if conf["led_mode"] != current_mode:
                break
            time.sleep(0.02)

        if conf["led_mode"] != current_mode:
            continue

        if off_time > 0:
            led.off()
            
            end_time = time.time() + off_time
            while time.time() < end_time:
                if conf["led_mode"] != current_mode:
                    break
                time.sleep(0.02)


def main():
    conf = load_config()
    print(f"[INFO] Starting Power Button Service on BCM pin {conf['pin']}")

    # ==================================================================
    #    Configura o GPIO 21 para manter sempre Nível Lógico 1 (3.3V)
    # ==================================================================
    # initial_value=True garante que ele já liga no estado HIGH
    gpio21_high = OutputDevice(21, active_high=True, initial_value=True)
    print("[INFO] GPIO 21 locked to HIGH (Logic 1)")

    # 2. Configura LED como Active-Low (Nível LOW liga o LED)
    led = None
    if conf["led_enabled"]:
        led = LED(conf["led_pin"], active_high=False)
        threading.Thread(target=led_worker, args=(led, conf), daemon=True).start()

    # 3. Configura o botão usando o lgpio 
    button = Button(conf["pin"], pull_up=conf["pull_up"])

    while True:
        # Fica aguardando o clique do botão
        button.wait_for_press()
        press_time = time.time() * 1000
        
        print("[INFO] Button Pressed!")

        # MUDANÇA APLICADA: Muda o LED para o modo 1 imediatamente ao clicar!
        conf["led_mode"] = 1

        # Loop enquanto o botão é segurado
        while button.is_pressed:
            duration = (time.time() * 1000) - press_time
            
            if duration >= conf["shutdown_time"]:
                conf["led_mode"] = 3
            elif duration >= conf["reboot_time"]:
                conf["led_mode"] = 2
                
            time.sleep(0.02) # MUDANÇA APLICADA: Reduzido de 0.05 para 0.02 para remover o lag

        # O botão foi solto
        duration = (time.time() * 1000) - press_time
        print(f"[INFO] Button released after {duration:.0f} ms")
        
        # Volta o LED ao normal
        conf["led_mode"] = 0

        if duration >= conf["shutdown_time"]:
            print("[ACTION] Shutdown triggered!")
            subprocess.call(["poweroff"])
        elif duration >= conf["reboot_time"]:
            print("[ACTION] Reboot triggered!")
            subprocess.call(["reboot"])


if __name__ == "__main__":
    try:
        main()
    except KeyboardInterrupt:
        pass
    except Exception as e:
        print(f"[ERROR] {e}")
