#!/usr/bin/env python3
"""
Mauseinstellungen für RDP Thin Client
Verwendet xinput direkt für zuverlässige Konfiguration
"""

import tkinter as tk
from tkinter import ttk
import subprocess
import re
import configparser
from pathlib import Path

class MouseSettings:
    CONFIG_DIR = Path.home() / ".config" / "mouse-settings"
    CONFIG_FILE = CONFIG_DIR / "settings.ini"

    def __init__(self, root):
        self.root = root
        self.root.title("Mauseinstellungen")
        self.root.geometry("500x300")

        # Erstelle Config-Verzeichnis
        self.CONFIG_DIR.mkdir(parents=True, exist_ok=True)

        self.mouse_ids = self.get_mouse_ids()

        if not self.mouse_ids:
            tk.Label(root, text="Keine Maus gefunden!", font=('Arial', 14)).pack(pady=50)
            return

        self.create_widgets()
        self.load_saved_settings()

    def get_mouse_ids(self):
        """Finde alle Maus-Device-IDs (alle Pointer mit 'mouse' im Namen)"""
        try:
            result = subprocess.run(['xinput', 'list'], capture_output=True, text=True)
            mouse_ids = []
            # Suche nach allen Devices mit "mouse" im Namen (nicht Virtual core)
            for line in result.stdout.split('\n'):
                if 'pointer' in line.lower() and 'virtual core' not in line.lower() and 'mouse' in line.lower():
                    match = re.search(r'id=(\d+)', line)
                    if match:
                        mouse_ids.append(match.group(1))
            return mouse_ids if mouse_ids else None
        except:
            return None

    def load_saved_settings(self):
        """Lade gespeicherte Mauseinstellungen"""
        if self.CONFIG_FILE.exists():
            try:
                config = configparser.ConfigParser()
                config.read(self.CONFIG_FILE)
                speed_percent = config.getint('Mouse', 'speed', fallback=50)
                self.speed_var.set(speed_percent)
                self.apply_speed()
                return
            except:
                pass

        # Fallback: Lade aktuelle System-Einstellungen
        self.speed_var.set(50)

    def save_settings(self):
        """Speichere Mauseinstellungen persistent"""
        try:
            config = configparser.ConfigParser()
            config['Mouse'] = {
                'speed': str(self.speed_var.get())
            }
            with open(self.CONFIG_FILE, 'w') as f:
                config.write(f)
        except Exception as e:
            print(f"Fehler beim Speichern: {e}")

    def create_widgets(self):
        main_frame = ttk.Frame(self.root, padding="20")
        main_frame.pack(fill=tk.BOTH, expand=True)

        # Geschwindigkeit
        ttk.Label(main_frame, text="Mausgeschwindigkeit:", font=('', 12, 'bold')).pack(anchor=tk.W, pady=(0,10))

        speed_frame = ttk.Frame(main_frame)
        speed_frame.pack(fill=tk.X, pady=10)

        ttk.Label(speed_frame, text="Langsam").pack(side=tk.LEFT)

        self.speed_var = tk.IntVar(value=50)
        self.speed_scale = ttk.Scale(speed_frame, from_=0, to=100,
                                     variable=self.speed_var,
                                     orient=tk.HORIZONTAL,
                                     command=self.apply_speed)
        self.speed_scale.pack(side=tk.LEFT, fill=tk.X, expand=True, padx=10)

        ttk.Label(speed_frame, text="Schnell").pack(side=tk.LEFT)

        # Wert-Anzeige
        self.speed_label = ttk.Label(main_frame, text="50%", font=('', 10))
        self.speed_label.pack()

        # Info
        ttk.Separator(main_frame, orient=tk.HORIZONTAL).pack(fill=tk.X, pady=20)
        info = ttk.Label(main_frame,
                        text="Änderungen werden sofort angewendet und gespeichert.\n"
                             "Die Einstellung wird beim nächsten Start automatisch geladen.",
                        foreground='gray')
        info.pack()

        # Buttons
        button_frame = ttk.Frame(main_frame)
        button_frame.pack(side=tk.BOTTOM, pady=10)

        ttk.Button(button_frame, text="Standard (50%)",
                  command=self.reset_default).pack(side=tk.LEFT, padx=5)
        ttk.Button(button_frame, text="Schließen",
                  command=self.root.destroy).pack(side=tk.LEFT, padx=5)

    def apply_speed(self, value=None):
        """Wende Mausgeschwindigkeit an (für alle gefundenen Mäuse)"""
        speed_percent = self.speed_var.get()

        # Konvertiere 0-100 zu verschiedenen Formaten
        libinput_speed = (speed_percent / 50.0) - 1.0  # -1.0 bis 1.0
        evdev_accel = speed_percent / 10.0  # 0 bis 10
        matrix_scale = speed_percent / 50.0  # 0 bis 2.0

        success_count = 0
        methods_used = set()

        # Wende Einstellungen auf ALLE Mäuse an
        for mouse_id in self.mouse_ids:
            success = False
            method = ""

            try:
                # Methode 1: libinput (modern)
                result = subprocess.run(['xinput', 'set-prop', mouse_id,
                              'libinput Accel Speed', str(libinput_speed)],
                             capture_output=True, text=True)
                if result.returncode == 0:
                    success = True
                    method = "libinput"
            except:
                pass

            if not success:
                try:
                    # Methode 2: evdev (älter)
                    result = subprocess.run(['xinput', 'set-prop', mouse_id,
                                  'Device Accel Constant Deceleration',
                                  str(10.0 / max(evdev_accel, 0.1))],
                                 capture_output=True, text=True)
                    if result.returncode == 0:
                        success = True
                        method = "evdev"
                except:
                    pass

            if not success:
                try:
                    # Methode 3: Coordinate Transformation Matrix (Fallback für Logitech etc.)
                    # Matrix für Skalierung: [scale, 0, 0, 0, scale, 0, 0, 0, 1]
                    # WICHTIG: Muss als einzelne Werte übergeben werden, nicht als String
                    result = subprocess.run(['xinput', 'set-prop', mouse_id,
                                  'Coordinate Transformation Matrix',
                                  str(matrix_scale), '0', '0',
                                  '0', str(matrix_scale), '0',
                                  '0', '0', '1'],
                                 capture_output=True, text=True)
                    if result.returncode == 0:
                        success = True
                        method = "matrix"
                except:
                    pass

            if success:
                success_count += 1
                methods_used.add(method)

        if success_count > 0:
            methods_str = "+".join(sorted(methods_used))
            self.speed_label.config(text=f"{speed_percent}% ({success_count} Maus/Mäuse: {methods_str})")
            self.save_settings()
        else:
            self.speed_label.config(text=f"{speed_percent}% (Fehler!)")

    def reset_default(self):
        """Setze auf Standard zurück"""
        self.speed_var.set(50)
        self.apply_speed()

if __name__ == '__main__':
    root = tk.Tk()
    app = MouseSettings(root)
    root.mainloop()
