import tkinter as tk
from tkinter import colorchooser, messagebox
from typing import Optional, Dict


class TextEntryHandler:
    """Handler for text input dialog functionality in the GUI.
    
    This class encapsulates the text input dialog that allows users
    to enter text and configure its parameters (position, font size, color).
    """
    
    def __init__(self, root_window: tk.Tk):
        """Initialize the text entry handler.
        
        Args:
            root_window: The root tkinter window for creating dialogs
        """
        self._root = root_window
    
    def show_text_input_dialog(self) -> Optional[Dict[str, any]]:
        """Show a dialog window for text input and parameters.
        
        Returns:
            A dictionary with text parameters if user confirmed, None if cancelled.
            Dictionary contains: text, x, y, font_size, color
        """
        dialog = tk.Toplevel(self._root)
        dialog.title("Add Text to Image")
        dialog.geometry("400x350")
        dialog.resizable(False, False)
        dialog.transient(self._root)
        dialog.grab_set()  # Make dialog modal
        
        # Center the dialog
        dialog.update_idletasks()
        x = (dialog.winfo_screenwidth() // 2) - (dialog.winfo_width() // 2)
        y = (dialog.winfo_screenheight() // 2) - (dialog.winfo_height() // 2)
        dialog.geometry(f"+{x}+{y}")
        
        result = {"text": "", "x": 10, "y": 10, "font_size": 40, "color": (0, 0, 0)}
        dialog_closed = [False]  # Use list to allow modification in nested functions
        
        # Text input field
        tk.Label(dialog, text="Text:", font=("Arial", 10)).pack(pady=(20, 5), padx=20, anchor="w")
        text_entry = tk.Text(dialog, height=3, width=40, wrap=tk.WORD, font=("Arial", 10))
        text_entry.pack(padx=20, pady=(0, 10), fill="x")
        text_entry.focus()
        
        # Position and size frame
        options_frame = tk.Frame(dialog)
        options_frame.pack(padx=20, pady=10, fill="x")
        
        # X position
        x_frame = tk.Frame(options_frame)
        x_frame.pack(fill="x", pady=5)
        tk.Label(x_frame, text="X Position:", width=12, anchor="w").pack(side="left")
        x_entry = tk.Entry(x_frame, width=10)
        x_entry.pack(side="left", padx=5)
        x_entry.insert(0, "10")
        
        # Y position
        y_frame = tk.Frame(options_frame)
        y_frame.pack(fill="x", pady=5)
        tk.Label(y_frame, text="Y Position:", width=12, anchor="w").pack(side="left")
        y_entry = tk.Entry(y_frame, width=10)
        y_entry.pack(side="left", padx=5)
        y_entry.insert(0, "10")
        
        # Font size
        size_frame = tk.Frame(options_frame)
        size_frame.pack(fill="x", pady=5)
        tk.Label(size_frame, text="Font Size:", width=12, anchor="w").pack(side="left")
        size_entry = tk.Entry(size_frame, width=10)
        size_entry.pack(side="left", padx=5)
        size_entry.insert(0, "40")
        
        # Color selection
        color_frame = tk.Frame(options_frame)
        color_frame.pack(fill="x", pady=5)
        tk.Label(color_frame, text="Color:", width=12, anchor="w").pack(side="left")
        color_preview = tk.Label(color_frame, bg="#000000", width=8, height=1, relief="sunken", bd=2)
        color_preview.pack(side="left", padx=5)
        selected_color = [(0, 0, 0)]  # Use list to allow modification
        
        def choose_color():
            color = colorchooser.askcolor(title="Choose Text Color", color="#000000")
            if color[1]:  # color[1] is the hex string
                selected_color[0] = tuple(int(color[1][i:i+2], 16) for i in (1, 3, 5))
                color_preview.config(bg=color[1])
        
        tk.Button(color_frame, text="Choose Color", command=choose_color, width=12).pack(side="left", padx=5)
        
        # Buttons
        button_frame = tk.Frame(dialog)
        button_frame.pack(pady=20)
        
        def on_ok():
            text = text_entry.get("1.0", tk.END).strip()
            if not text:
                messagebox.showwarning("No Text", "Please enter some text.")
                return
            
            try:
                result["text"] = text
                result["x"] = int(x_entry.get() or "10")
                result["y"] = int(y_entry.get() or "10")
                result["font_size"] = int(size_entry.get() or "40")
                result["color"] = selected_color[0]
                dialog_closed[0] = True
                dialog.destroy()
            except ValueError:
                messagebox.showerror("Invalid Input", "Please enter valid numbers for position and font size.")
        
        def on_cancel():
            dialog_closed[0] = True
            dialog.destroy()
        
        tk.Button(button_frame, text="OK", command=on_ok, width=10).pack(side="left", padx=5)
        tk.Button(button_frame, text="Cancel", command=on_cancel, width=10).pack(side="left", padx=5)
        
        # Handle Enter key (Ctrl+Enter for Text widget, Enter for dialog)
        text_entry.bind("<Control-Return>", lambda e: on_ok())
        dialog.bind("<Return>", lambda e: on_ok())
        dialog.bind("<Escape>", lambda e: on_cancel())
        
        # Wait for dialog to close
        dialog.wait_window()
        
        # Return None if cancelled, otherwise return result
        if not dialog_closed[0] or not result["text"]:
            return None
        return result

