# UI components and dialogs for the desktop application

import tkinter as tk
from tkinter import ttk, filedialog, messagebox
from PIL import Image, ImageTk
import os
import uuid
from config import THEME


class MacroDialog:
    """Dialog for adding/editing macros"""
    
    def __init__(self, parent, macro_manager, macro_id=None):
        self.parent = parent
        self.macro_manager = macro_manager
        self.macro_id = macro_id
        self.dialog = None
        self.result = None
    
    def show(self):
        """Show the dialog and return the result"""
        self.dialog = tk.Toplevel(self.parent)
        self.dialog.title("Edit Macro" if self.macro_id else "Add Macro")
        self.dialog.geometry("450x400")
        self.dialog.transient(self.parent)
        self.dialog.configure(bg=THEME['bg_color'])
        self.dialog.grab_set()
        
        # If editing, get existing macro data
        if self.macro_id:
            macro = self.macro_manager.macros.get(self.macro_id, {})
        else:
            macro = {}
        
        self._create_widgets(macro)
        
        # Wait for dialog to close
        self.dialog.wait_window()
        return self.result
    
    def _create_widgets(self, macro):
        """Create the dialog widgets"""
        # Name
        tk.Label(self.dialog, text="Macro Name:", bg=THEME['bg_color'], fg=THEME['fg_color']).grid(row=0, column=0, padx=5, pady=5, sticky="w")
        self.name_entry = tk.Entry(self.dialog, width=30, bg=THEME['highlight_color'], fg=THEME['fg_color'], insertbackground=THEME['fg_color'])
        self.name_entry.grid(row=0, column=1, padx=5, pady=5)
        self.name_entry.insert(0, macro.get("name", ""))

        # Category
        tk.Label(self.dialog, text="Category:", bg=THEME['bg_color'], fg=THEME['fg_color']).grid(row=1, column=0, padx=5, pady=5, sticky="w")
        self.category_entry = tk.Entry(self.dialog, width=30, bg=THEME['highlight_color'], fg=THEME['fg_color'], insertbackground=THEME['fg_color'])
        self.category_entry.grid(row=1, column=1, padx=5, pady=5)
        self.category_entry.insert(0, macro.get("category", ""))

        # Type
        tk.Label(self.dialog, text="Type:", bg=THEME['bg_color'], fg=THEME['fg_color']).grid(row=2, column=0, padx=5, pady=5, sticky="w")
        self.type_var = tk.StringVar(value=macro.get("type", "text"))

        radio_style = {'bg': THEME['bg_color'], 'fg': THEME['fg_color'], 'selectcolor': THEME['accent_color']}
        tk.Radiobutton(self.dialog, text="Text", variable=self.type_var, value="text", **radio_style).grid(row=2, column=1, sticky="w")
        tk.Radiobutton(self.dialog, text="Application", variable=self.type_var, value="app", **radio_style).grid(row=3, column=1, sticky="w")

        # Command/Text
        tk.Label(self.dialog, text="Command/Text:", bg=THEME['bg_color'], fg=THEME['fg_color']).grid(row=4, column=0, padx=5, pady=5, sticky="w")
        self.command_text = tk.Text(self.dialog, width=30, height=5, bg=THEME['highlight_color'], fg=THEME['fg_color'], insertbackground=THEME['fg_color'])
        self.command_text.grid(row=4, column=1, padx=5, pady=5)
        self.command_text.insert("1.0", macro.get("command", ""))

        # Modifiers
        self._create_modifiers(macro)

        # Image
        self.image_path = tk.StringVar()
        tk.Label(self.dialog, text="Image:", bg=THEME['bg_color'], fg=THEME['fg_color']).grid(row=6, column=0, padx=5, pady=5, sticky="w")
        image_entry = tk.Entry(self.dialog, textvariable=self.image_path, width=30, bg=THEME['highlight_color'], fg=THEME['fg_color'], insertbackground=THEME['fg_color'])
        image_entry.grid(row=6, column=1, padx=5, pady=5)

        button_style = {'bg': THEME['button_bg'], 'fg': THEME['button_fg'], 'activebackground': THEME['accent_color'],
                        'activeforeground': THEME['button_fg'], 'bd': 0, 'relief': tk.FLAT}

        tk.Button(self.dialog, text="Browse...", command=self._browse_image, **button_style).grid(row=6, column=2)

        # Buttons
        tk.Button(self.dialog, text="Save", command=self._save, **button_style).grid(row=7, column=0, padx=5, pady=20)
        tk.Button(self.dialog, text="Cancel", command=self._cancel, **button_style).grid(row=7, column=1, padx=5, pady=20)

    def _create_modifiers(self, macro):
        """Create modifier checkboxes"""
        mod_frame = tk.Frame(self.dialog, bg=THEME['bg_color'])
        mod_frame.grid(row=5, column=0, columnspan=2, sticky="w", padx=5, pady=5)

        tk.Label(mod_frame, text="Key Modifiers:", bg=THEME['bg_color'], fg=THEME['fg_color']).pack(side=tk.LEFT, padx=5)

        modifiers = macro.get("modifiers", {})
        self.ctrl_var = tk.BooleanVar(value=modifiers.get("ctrl", False))
        self.alt_var = tk.BooleanVar(value=modifiers.get("alt", False))
        self.shift_var = tk.BooleanVar(value=modifiers.get("shift", False))
        self.enter_var = tk.BooleanVar(value=modifiers.get("enter", False))

        checkbox_style = {'bg': THEME['bg_color'], 'fg': THEME['fg_color'], 'selectcolor': THEME['accent_color'],
                          'activebackground': THEME['bg_color'], 'activeforeground': THEME['fg_color']}

        tk.Checkbutton(mod_frame, text="Ctrl", variable=self.ctrl_var, **checkbox_style).pack(side=tk.LEFT, padx=5)
        tk.Checkbutton(mod_frame, text="Alt", variable=self.alt_var, **checkbox_style).pack(side=tk.LEFT, padx=5)
        tk.Checkbutton(mod_frame, text="Shift", variable=self.shift_var, **checkbox_style).pack(side=tk.LEFT, padx=5)
        tk.Checkbutton(mod_frame, text="Add Enter", variable=self.enter_var, **checkbox_style).pack(side=tk.LEFT, padx=5)

    def _browse_image(self):
        """Browse for image file"""
        filename = filedialog.askopenfilename(
            filetypes=[("Image files", "*.jpg *.jpeg *.png *.gif *.bmp")])
        if filename:
            self.image_path.set(filename)

    def _save(self):
        """Save the macro"""
        name = self.name_entry.get().strip()
        if not name:
            messagebox.showerror("Error", "Macro name is required")
            return

        macro_type = self.type_var.get()
        command = self.command_text.get("1.0", tk.END).strip()
        category = self.category_entry.get().strip()
        
        modifiers = {
            "ctrl": self.ctrl_var.get(),
            "alt": self.alt_var.get(),
            "shift": self.shift_var.get(),
            "enter": self.enter_var.get()
        }

        if self.macro_id:
            # Update existing macro
            success = self.macro_manager.update_macro(
                self.macro_id, name, macro_type, command, category, modifiers, self.image_path.get())
        else:
            # Add new macro
            self.macro_id = self.macro_manager.add_macro(
                name, macro_type, command, category, modifiers, self.image_path.get())
            success = bool(self.macro_id)

        if success:
            self.result = self.macro_id
            self.dialog.destroy()
        else:
            messagebox.showerror("Error", "Failed to save macro")

    def _cancel(self):
        """Cancel dialog"""
        self.result = None
        self.dialog.destroy()


class MacroSelector:
    """Dialog for selecting a macro from a list"""
    
    def __init__(self, parent, macro_manager, title="Select Macro"):
        self.parent = parent
        self.macro_manager = macro_manager
        self.title = title
        self.result = None
    
    def show(self):
        """Show the selection dialog"""
        if not self.macro_manager.macros:
            messagebox.showinfo("No Macros", "There are no macros available.")
            return None

        dialog = tk.Toplevel(self.parent)
        dialog.title(self.title)
        dialog.geometry("200x340")
        dialog.transient(self.parent)
        dialog.configure(bg=THEME['bg_color'])
        dialog.grab_set()

        # Instructions
        tk.Label(dialog, text=f"{self.title}:", bg=THEME['bg_color'], fg=THEME['fg_color']).pack(pady=5)

        # Listbox
        listbox = tk.Listbox(dialog, bg=THEME['highlight_color'], fg=THEME['fg_color'], selectbackground=THEME['accent_color'])
        listbox.pack(fill=tk.BOTH, expand=True, padx=10, pady=5)

        # Populate listbox
        macro_ids = []
        for macro_id, macro in self.macro_manager.macros.items():
            listbox.insert(tk.END, macro["name"])
            macro_ids.append(macro_id)

        def on_select():
            if not listbox.curselection():
                messagebox.showwarning("No Selection", f"Please select a macro.")
                return
            idx = listbox.curselection()[0]
            self.result = macro_ids[idx]
            dialog.destroy()

        button_style = {'bg': THEME['button_bg'], 'fg': THEME['button_fg'], 'activebackground': THEME['accent_color'],
                        'activeforeground': THEME['button_fg'], 'bd': 0, 'relief': tk.FLAT}

        tk.Button(dialog, text="Select", command=on_select, **button_style).pack(pady=10)
        tk.Button(dialog, text="Cancel", command=lambda: dialog.destroy(), **button_style).pack(pady=5)

        dialog.wait_window()
        return self.result


class TabManager:
    """Dialog for managing macro categories/tabs"""
    
    def __init__(self, parent, macro_manager):
        self.parent = parent
        self.macro_manager = macro_manager
    
    def show(self):
        """Show tab management dialog"""
        dialog = tk.Toplevel(self.parent)
        dialog.title("Manage Tabs")
        dialog.geometry("450x400")  # Increased width and height
        dialog.transient(self.parent)
        dialog.configure(bg=THEME['bg_color'])
        dialog.grab_set()

        # Instructions
        tk.Label(dialog, text="Assign categories to macros for better organization:", 
                bg=THEME['bg_color'], fg=THEME['fg_color']).pack(pady=10)

        # Create scrollable frame
        list_frame = tk.Frame(dialog, bg=THEME['bg_color'])
        list_frame.pack(fill=tk.BOTH, expand=True, padx=10, pady=5)

        canvas = tk.Canvas(list_frame, bg=THEME['bg_color'], highlightthickness=0)
        scrollbar = ttk.Scrollbar(list_frame, orient="vertical", command=canvas.yview)
        scrollable_frame = tk.Frame(canvas, bg=THEME['bg_color'])

        scrollable_frame.bind(
            "<Configure>",
            lambda e: canvas.configure(scrollregion=canvas.bbox("all"))
        )
        canvas.create_window((0, 0), window=scrollable_frame, anchor="nw")
        canvas.configure(yscrollcommand=scrollbar.set)

        canvas.pack(side="left", fill="both", expand=True)
        scrollbar.pack(side="right", fill="y")

        # Category entries for each macro
        category_vars = {}
        for macro_id, macro in self.macro_manager.macros.items():
            frame = tk.Frame(scrollable_frame, bg=THEME['bg_color'])
            frame.pack(fill="x", pady=2, padx=5)
            
            tk.Label(frame, text=macro["name"], bg=THEME['bg_color'], fg=THEME['fg_color'], 
                    width=20, anchor="w").pack(side=tk.LEFT)
            
            category_var = tk.StringVar(value=macro.get("category", ""))
            category_vars[macro_id] = category_var
            entry = tk.Entry(frame, textvariable=category_var, width=15,
                           bg=THEME['highlight_color'], fg=THEME['fg_color'], insertbackground=THEME['fg_color'])
            entry.pack(side=tk.RIGHT, padx=(5, 0))

        # Buttons - use a fixed frame at bottom
        button_frame = tk.Frame(dialog, bg=THEME['bg_color'])
        button_frame.pack(side=tk.BOTTOM, fill=tk.X, pady=10)

        def save_categories():
            for macro_id, category_var in category_vars.items():
                category = category_var.get().strip()
                if category:
                    self.macro_manager.macros[macro_id]["category"] = category
                else:
                    self.macro_manager.macros[macro_id].pop("category", None)
            
            self.macro_manager.save_macros()
            dialog.destroy()

        button_style = {'bg': THEME['button_bg'], 'fg': THEME['button_fg'], 'activebackground': THEME['accent_color'],
                        'activeforeground': THEME['button_fg'], 'bd': 0, 'relief': tk.FLAT}

        tk.Button(button_frame, text="Save", command=save_categories, **button_style).pack(side=tk.LEFT, padx=5)
        tk.Button(button_frame, text="Cancel", command=lambda: dialog.destroy(), **button_style).pack(side=tk.LEFT, padx=5)

        dialog.wait_window()