# -*- coding: utf-8 -*-
"""
ARTOS Main Docking Window
Modular GUI with dockable panels for different system modules.
"""
import tkinter as tk
from tkinter import ttk, messagebox
import logging
import sys
import os
import threading

# Add external modules to path
sys.path.insert(0, os.path.join(os.path.dirname(__file__), '..', '..', '_external', 'externals', 'python-tkinter-logger'))
sys.path.insert(0, os.path.join(os.path.dirname(__file__), '..', '..', '_external', 'externals', 'python-resource-monitor'))

from tkinter_logger import TkinterLogger
from resource_monitor import ResourceMonitor

from tkinter.scrolledtext import ScrolledText

from pymsc.core.bus_1553_module import Bus1553Module
from pymsc.gui.docking.workspace_manager import WorkspaceManager
from pymsc.gui.docking.mcs_dock import MCSDock
from pymsc.gui.docking.placeholder_dock import PlaceholderDock
from pymsc.gui.docking.logger_dock import LoggerDock
from pymsc.gui.components.command_widgets import (
    CommandFrameCheckBox, CommandFrameComboBox, 
    CommandFrameSpinBox, CommandFrameLabels, 
    CommandFrameControls
)


class MainDockingWindow:
    """
    ARTOS main window with modular docking system.
    
    Architecture:
    - Left panel: MCS (Mission Control System)
    - Right top: Navigation, IRST, Algorithms (placeholders)
    - Right bottom: Logger, Status (placeholders)
    """
    
    def __init__(self, bus_module: Bus1553Module, logger_system=None):
        """
        Args:
            bus_module: Bus1553Module instance for message access
            logger_system: Pre-configured TkinterLogger instance (optional)
        """
        self.bus_module = bus_module
        self._refresh_active = False  # Flag to control GUI refresh loop
        self._closing = False  # Flag to prevent multiple close attempts
        
        # Create main window
        self.root = tk.Tk()
        self.root.title("ARTOS - Advanced Radar Test & Orchestration System")
        self.root.geometry("1600x900")
        
        # Configure light theme
        style = ttk.Style()
        style.theme_use('clam')
        
        # Light theme configuration
        bg_light = '#f0f0f0'
        bg_lighter = '#ffffff'
        fg_dark = '#000000'
        accent = '#0078d7'
        
        self.root.configure(bg=bg_light)
        style.configure('TFrame', background=bg_light)
        style.configure('TLabel', background=bg_light, foreground=fg_dark)
        style.configure('TButton', background=accent, foreground='white')
        style.map('TButton', background=[('active', '#005a9e')])
        style.configure('TLabelframe', background=bg_light, foreground=fg_dark)
        style.configure('TLabelframe.Label', background=bg_light, foreground=fg_dark)
        
        self.root.protocol("WM_DELETE_WINDOW", self._on_close)
        
        # Use existing TkinterLogger or create new one
        if logger_system:
            self.logger_system = logger_system
            # Update root for after() scheduling
            self.logger_system.tk_root = self.root
        else:
            # Fallback: create new logger system
            self.logger_system = TkinterLogger(self.root)
            self.logger_system.setup(
                enable_console=True,
                enable_file=True,
                file_path='logs/artos.log',
                enable_tkinter=False,  # Will add widget after LoggerDock is created
                root_level=logging.INFO
            )
        
        # Create menu bar
        self._create_menu()
        
        # Create status bar at bottom (before workspace)
        self._create_status_bar()
        
        # Create workspace manager FIRST (so containers exist)
        self.workspace = WorkspaceManager(self.root, layouts_dir="layouts")
        
        # Create LoggerDock FIRST so it creates its widget in the correct container
        self.logger_dock = LoggerDock(self.workspace.bottom_container)
        self.workspace.add_dock('logger', self.logger_dock, position='bottom')
        
        # Get the widget from LoggerDock and connect it to TkinterLogger
        log_widget = self.logger_dock.get_log_widget()
        self.logger_system.add_tkinter_handler(
            log_widget,
            level_colors={
                logging.DEBUG: '#666666',
                logging.INFO: '#0066cc',
                logging.WARNING: '#ff8800',
                logging.ERROR: '#cc0000',
                logging.CRITICAL: '#8B0000'
            },
            max_lines=1000
        )
        
        logger = logging.getLogger('ARTOS')
        logger.info("GUI logger initialized - capturing all subsequent logs")
        
        # Create and register other docks
        self._create_docks()
        
        # Load saved layout automatically after widgets are fully rendered
        self.root.after(200, lambda: self.workspace.load_layout("user_layout"))
        
        # Start refresh loops
        self._start_refresh()
    
    def _create_status_bar(self):
        """Create status bar at bottom with resource monitor on the right."""
        self.status_bar = ttk.Frame(self.root, relief=tk.SUNKEN, borderwidth=1)
        self.status_bar.pack(side=tk.BOTTOM, fill=tk.X)
        
        # Left side: general status message
        self.status_label = ttk.Label(
            self.status_bar,
            text="ARTOS Ready",
            anchor=tk.W,
            padding=(5, 2)
        )
        self.status_label.pack(side=tk.LEFT, fill=tk.X, expand=True)
        
        # Right side: resource monitor
        self.resource_label = ttk.Label(
            self.status_bar,
            text="",
            anchor=tk.E,
            padding=(5, 2)
        )
        self.resource_label.pack(side=tk.RIGHT)
        
        # Initialize ResourceMonitor
        def update_resource_stats(stats_str):
            try:
                self.resource_label.config(text=stats_str)
            except Exception:
                pass
        
        self.resource_monitor = ResourceMonitor(
            update_callback=update_resource_stats,
            poll_interval=1.0
        )
        self.resource_monitor.start()
    
    def _create_menu(self):
        """Create the main menu bar."""
        menubar = tk.Menu(self.root)
        self.root.config(menu=menubar)
        
        # File menu
        file_menu = tk.Menu(menubar, tearoff=0)
        menubar.add_cascade(label="File", menu=file_menu)
        file_menu.add_command(label="Save Layout", command=self._save_layout)
        file_menu.add_command(label="Load Layout", command=self._load_layout)
        file_menu.add_separator()
        file_menu.add_command(label="Exit", command=self._on_close)
        
        # View menu - toggle dock visibility
        view_menu = tk.Menu(menubar, tearoff=0)
        menubar.add_cascade(label="View", menu=view_menu)
        view_menu.add_command(label="Toggle MCS", 
                            command=lambda: self.workspace.toggle_dock_visibility('mcs'))
        view_menu.add_command(label="Toggle Navigation", 
                            command=lambda: self.workspace.toggle_dock_visibility('nav'))
        view_menu.add_command(label="Toggle IRST", 
                            command=lambda: self.workspace.toggle_dock_visibility('irst'))
        view_menu.add_separator()
        view_menu.add_command(label="Restore All", command=self._restore_all_docks)
        
        # System menu
        system_menu = tk.Menu(menubar, tearoff=0)
        menubar.add_cascade(label="System", menu=system_menu)
        system_menu.add_command(label="Start System", command=self._start_system)
        system_menu.add_command(label="Stop System", command=self._stop_system)
        system_menu.add_separator()
        system_menu.add_command(label="System Info", command=self._show_system_info)
        system_menu.add_separator()
        system_menu.add_command(label="1553 Debug", command=self._open_1553_debug)
        
        # Help menu
        help_menu = tk.Menu(menubar, tearoff=0)
        menubar.add_cascade(label="Help", menu=help_menu)
        help_menu.add_command(label="About", command=self._show_about)
        help_menu.add_command(label="Documentation", command=self._show_docs)
    
    def _create_docks(self):
        """Create and register remaining dock panels (logger was created first)."""
        # Left panel: MCS
        mcs_dock = MCSDock(
            self.workspace.left_container,
            bus_module=self.bus_module
        )
        self.workspace.add_dock('mcs', mcs_dock, position='left')
        
        # Right top: Navigation placeholder
        nav_dock = PlaceholderDock(
            self.workspace.right_top_container,
            title="Navigation System",
            description="Navigation algorithms and data processing\n\n(Coming in Phase 3)"
        )
        self.workspace.add_dock('nav', nav_dock, position='right_top')
        
        # Right bottom: IRST placeholder
        irst_dock = PlaceholderDock(
            self.workspace.right_bottom_container,
            title="IRST Module",
            description="Infrared Search & Track\n\n(Coming in Phase 4)"
        )
        self.workspace.add_dock('irst', irst_dock, position='right_bottom')
        
        # Logger was already created first in __init__
    
    def _start_refresh(self):
        """Start the GUI refresh loop to update all widgets."""
        self._refresh_active = True
        self.gui_refresh_loop()
    
    def _stop_refresh(self):
        """Stop refresh loops (cleanup on exit)."""
        self._refresh_active = False
    
    def gui_refresh_loop(self):
        """
        Periodically refreshes all custom widgets in all visible docks.
        This updates telemetry displays from received 1553 messages.
        """
        # Check if we should continue refreshing
        if not self._refresh_active:
            return
        
        # First, sync all messages from the 1553 bus (read latest telemetry)
        try:
            if self.bus_module and self.bus_module.is_running:
                self.bus_module.sync_all_messages()
        except Exception:
            pass
        
        # Then refresh widgets in all visible docks
        try:
            for dock_id, dock in self.workspace.docks.items():
                if dock.is_visible and not dock.is_minimized:
                    self._refresh_widgets_recursive(dock.content_frame)
        except Exception:
            pass
        
        # Schedule next refresh only if still active (100ms = 10 Hz update rate)
        if self._refresh_active:
            self.root.after(100, self.gui_refresh_loop)
    
    def _refresh_widgets_recursive(self, container: tk.Widget):
        """
        Traverses the widget tree to find and update PyMsc custom components.
        Calls check_updated_value() on each command widget found.
        """
        for child in container.winfo_children():
            # Check if it's one of our custom command widgets
            is_custom = isinstance(child, (
                CommandFrameCheckBox, CommandFrameComboBox, 
                CommandFrameSpinBox, CommandFrameLabels, 
                CommandFrameControls
            ))
            
            if is_custom and hasattr(child, 'check_updated_value'):
                child.check_updated_value()
            
            # Continue searching if the child has its own children (like sub-frames)
            if child.winfo_children():
                self._refresh_widgets_recursive(child)
    
    def _save_layout(self):
        """Save current workspace layout."""
        self.workspace.save_layout("user_layout")
        messagebox.showinfo("Layout Saved", "Workspace layout saved successfully.")
    
    def _load_layout(self):
        """Load saved workspace layout."""
        self.workspace.load_layout("user_layout")
        messagebox.showinfo("Layout Loaded", "Workspace layout loaded successfully.")
    
    def _restore_all_docks(self):
        """Restore all docks to visible state."""
        for dock_id, dock in self.workspace.docks.items():
            if not dock.is_visible:
                dock.show()
            if dock.is_minimized:
                dock.restore()
    
    def _start_system(self):
        """Start the 1553 bus system."""
        if hasattr(self.bus_module, 'start'):
            self.bus_module.start()
            messagebox.showinfo("System", "Bus system started.")
    
    def _stop_system(self):
        """Stop the 1553 bus system."""
        if hasattr(self.bus_module, 'stop'):
            self.bus_module.stop()

    def _open_1553_debug(self):
        """Open a separate window with the PyBusMonitor1553 DebugView (1553 debug)."""
        try:
            # Import the simplified DebugView (not MonitorApp)
            from pymsc.PyBusMonitor1553.gui.debug_view import DebugView
        except Exception as e:
            messagebox.showerror("1553 Debug", f"Cannot import DebugView: {e}")
            return

        try:
            win = tk.Toplevel(self.root)
            win.title("1553 Debug Monitor")
            win.geometry("1000x700")
            
            # Pass existing BusMonitorCore instance
            bus_monitor_instance = getattr(self.bus_module, 'core', None)
            if not bus_monitor_instance:
                messagebox.showerror("1553 Debug", "BusMonitorCore not initialized")
                win.destroy()
                return
            
            # Create DebugView with existing bus_monitor
            app = DebugView(parent=win, bus_monitor=bus_monitor_instance)
            
            # Keep references
            self._1553_debug_win = win
            self._1553_debug_app = app
            
            # Safe close handler
            def _close_debug():
                try:
                    app.stop()
                except Exception:
                    pass
                try:
                    win.destroy()
                except Exception:
                    pass
            
            win.protocol("WM_DELETE_WINDOW", _close_debug)
            
            logger = logging.getLogger('ARTOS')
            logger.info("1553 Debug window opened")
        
        except Exception as e:
            messagebox.showerror("1553 Debug", f"Failed to create debug window: {e}")
            return
            messagebox.showinfo("System", "Bus system stopped.")
    
    def _show_system_info(self):
        """Display system information."""
        info = f"""
ARTOS System Information

Architecture: Layered Modular Design
- L0: Hardware Abstraction (1553 Bus)
- L1: Test Orchestration (TestContext)
- L2: Algorithm Library
- L3: Test Execution

Active Modules:
- MCS: Mission Control System ✓
- Navigation: Placeholder
- IRST: Placeholder
- Logger: Placeholder

Framework: Tkinter + Custom Docking
Bus Protocol: MIL-STD-1553B over UDP
        """
        messagebox.showinfo("System Information", info.strip())
    
    def _show_about(self):
        """Show about dialog."""
        about_text = """
ARTOS v2.0
Advanced Radar Test & Orchestration System

Modular GUI with docking panels
Built with Tkinter and ttkbootstrap

© 2025
        """
        messagebox.showinfo("About ARTOS", about_text.strip())
    
    def _show_docs(self):
        """Open documentation."""
        messagebox.showinfo(
            "Documentation",
            "Documentation is available in the 'doc/' folder.\n\n"
            "Key files:\n"
            "- ARTOS_Architecture_Decisions.md\n"
            "- ARTOS_design.md\n"
            "- English-manual.md"
        )
    
    def _on_close(self):
        """Handle window close event."""
        # Prevent multiple close attempts
        if self._closing:
            return
        self._closing = True
        
        # Save layout automatically before closing (includes window geometry)
        try:
            self.workspace.save_layout("user_layout")
        except Exception:
            pass
        
        if messagebox.askokcancel("Quit", "Do you want to quit ARTOS?"):
            # Stop GUI refresh loop FIRST to prevent any further after() calls
            self._refresh_active = False
            
            # Stop resource monitor
            try:
                if hasattr(self, 'resource_monitor'):
                    self.resource_monitor.stop()
            except Exception:
                pass

            # Shutdown TkinterLogger system
            try:
                if hasattr(self, 'logger_system'):
                    self.logger_system.shutdown()
            except Exception:
                pass

            # Destroy window immediately
            try:
                self.root.destroy()
            except Exception:
                pass
            
            # Force immediate exit - don't wait for threads to clean up
            # This is necessary because TimeSync and BusMonitor threads may block
            os._exit(0)
        else:
            # User cancelled - allow close again later
            self._closing = False
    
    def run(self):
        """Start the main event loop."""
        self.root.mainloop()


def main():
    """Main entry point for the ARTOS GUI application."""
    # Initialize the bus module
    from pymsc.core.bus_1553_module import Bus1553Module
    
    bus_module = Bus1553Module()
    
    # Initialize with configuration
    config = {
        'udp_send_ip': '127.0.0.1',
        'udp_send_port': 51553,
        'udp_recv_ip': '0.0.0.0',
        'udp_recv_port': 61553
    }
    bus_module.initialize(config)
    
    # Create and run the main window
    app = MainDockingWindow(bus_module)
    app.run()


if __name__ == '__main__':
    main()
