import tkinter as tk
from tkinter import ttk
import queue

from application_controller import ApplicationController

class GPSApp:
    def __init__(self, root):
        self.root = root
        self.root.title("MBARI CSEM Triggerbox")
        self.root.geometry("1000x450")
        self.root.resizable(False, False)
        self.root.configure(bg='black')

        # GUI state
        self.gui_initialized = False
        
        # Initialize application controller
        self.app_controller = ApplicationController()
        
        # Setup GUI first
        self.setup_gui()
        
        # Register GUI callbacks with application controller
        self._register_callbacks()
        
        # Mark GUI as fully initialized
        self.gui_initialized = True
        
        # Initialize application controller
        self.app_controller.initialize()

        # Bind window events
        self.root.bind('<Map>', self.on_window_map)
        self.root.bind('<Configure>', self.on_window_configure)
        self.root.protocol("WM_DELETE_WINDOW", self.on_close)

        # Start queue processing for any remaining queue-based updates
        self.process_updates()

    def _register_callbacks(self):
        """Register all GUI callback functions with the application controller"""
        callbacks = {
            'status_update': self.update_status,
            'sync_status_update': self.update_sync_status,
            'time_update': self.update_time_displays,
            'frequency_update': self.update_frequency_display,
            'countdown_update': self.update_countdown_display,
            'gps_update': self.update_gps_data,
            'pps_indicator': self.update_pps_indicator,
            'onoff_indicator': self.update_onoff_indicator,
            'duty_indicator': self.update_duty_indicator,
            'polarity_indicator': self.update_polarity_indicator,
            'recording_indicator': self.update_recording_indicator
        }
        
        self.app_controller.register_gui_callbacks(callbacks)

    def setup_gui(self):
        """Setup the main GUI components"""
        # Main container with reduced padding
        main_frame = tk.Frame(self.root, bg='black')
        main_frame.pack(fill=tk.BOTH, expand=True, padx=8, pady=5)
        
        # Status at top with GPS info on same line
        self._setup_status_section(main_frame)
        
        # Time display section with sync button
        self._setup_time_section(main_frame)
        
        # Transmission control section
        self._setup_control_section(main_frame)
        
        # Control buttons and status
        self._setup_button_section(main_frame)
        
        # GPIO Status Indicators
        self._setup_indicator_section(main_frame)

    def _setup_status_section(self, parent):
        """Setup status and GPS info section"""
        self.status_frame = tk.Frame(parent, bg='black')
        self.status_frame.pack(fill=tk.X, pady=(0, 5))
        
        # Create a single line for status and GPS info
        status_info_frame = tk.Frame(self.status_frame, bg='black')
        status_info_frame.pack()
        
        self.status_label = tk.Label(status_info_frame, text="Initializing...", 
                                   font=("Courier", 9), fg="gray", bg="black")
        self.status_label.pack(side=tk.LEFT)
        
        # GPS info on same line
        self.lat_label = tk.Label(status_info_frame, text="Lat: ---", 
                                font=("Courier", 9), fg="lightgreen", bg="black")
        self.lat_label.pack(side=tk.LEFT, padx=(15, 5))

        self.lon_label = tk.Label(status_info_frame, text="Long: ---", 
                                font=("Courier", 9), fg="lightgreen", bg="black")
        self.lon_label.pack(side=tk.LEFT, padx=(0, 5))

        self.sats_label = tk.Label(status_info_frame, text="Sats: --", 
                                 font=("Courier", 9), fg="orange", bg="black")
        self.sats_label.pack(side=tk.LEFT, padx=(0, 5))

    def _setup_time_section(self, parent):
        """Setup time display section"""
        time_section_frame = tk.Frame(parent, bg='black')
        time_section_frame.pack(fill=tk.X, pady=(0, 8))
        
        # Times container
        times_container = tk.Frame(time_section_frame, bg='black')
        times_container.pack()
        
        # Times on the left
        time_frame = tk.Frame(times_container, bg='black')
        time_frame.pack(side=tk.LEFT, fill=tk.BOTH, expand=True)
        
        self.rpi_time_label = tk.Label(time_frame, text="RPI Time (UTC): --", 
                                     font=("Courier", 12, "bold"), fg="white", bg="black", anchor="center")
        self.rpi_time_label.pack(pady=1, fill=tk.X)

        self.gps_time_label = tk.Label(time_frame, text="GPS Time (UTC): --", 
                                     font=("Courier", 12, "bold"), fg="cyan", bg="black", anchor="center")
        self.gps_time_label.pack(pady=1, fill=tk.X)

        self.rtc_time_label = tk.Label(time_frame, text="RTC Time (UTC): --", 
                                     font=("Courier", 12, "bold"), fg="yellow", bg="black", anchor="center")
        self.rtc_time_label.pack(pady=1, fill=tk.X)

        # Sync section moved closer to times
        sync_frame = tk.Frame(times_container, bg='black')
        sync_frame.pack(side=tk.RIGHT, padx=(20, 0))
        
        self.sync_status_label = tk.Label(sync_frame, text="", 
                                        font=("Courier", 8), fg="lightblue", bg="black")
        self.sync_status_label.pack()

        self.sync_button = tk.Button(sync_frame, text="Sync GPS\nto RTC", 
                                   command=self.sync_rtc_time, font=("Arial", 12),
                                   bg="lightblue", fg="black", width=8, height=3)
        self.sync_button.pack(pady=3)

    def _setup_control_section(self, parent):
        """Setup transmission control section"""
        tx_frame = tk.Frame(parent, bg='black')
        tx_frame.pack(fill=tk.X, pady=(0, 8))
        
        # Container for all three control sections
        control_sections_frame = tk.Frame(tx_frame, bg='black')
        control_sections_frame.pack(pady=(0, 5))
        
        # Frequency setting section
        self._setup_frequency_controls(control_sections_frame)
        
        # Transmit Time section
        self._setup_transmit_controls(control_sections_frame)
        
        # Pause Time section
        self._setup_pause_controls(control_sections_frame)

    def _setup_frequency_controls(self, parent):
        """Setup frequency control widgets"""
        freq_section = tk.Frame(parent, bg='black')
        freq_section.pack(side=tk.LEFT, padx=(0, 20))
        
        # Frequency label and info
        freq_info_line = tk.Frame(freq_section, bg='black')
        freq_info_line.pack()
        
        tk.Label(freq_info_line, text="Frequency (Hz):", font=("Arial", 10), 
                fg="white", bg="black").pack()
        
        self.period_display = tk.Label(freq_info_line, text="Period: 1.000s", 
                                     font=("Arial", 9), fg="orange", bg="black")
        self.period_display.pack(pady=(2, 0))
        
        self.decimal_indicator = tk.Label(freq_info_line, text="Editing: Ones place", 
                                        font=("Arial", 8), fg="lightblue", bg="black")
        self.decimal_indicator.pack()
        
        # Frequency control layout
        freq_control_frame = tk.Frame(freq_section, bg='black')
        freq_control_frame.pack(pady=(5, 0))
        
        # Up button
        self.freq_up_btn = tk.Button(freq_control_frame, text="▲", 
                                   font=("Arial", 12, "bold"), bg="lightgray", fg="black",
                                   width=3, height=1, command=self.freq_up)
        self.freq_up_btn.grid(row=0, column=1, padx=2, pady=1)
        
        # Left and Right buttons with frequency display
        freq_middle_frame = tk.Frame(freq_control_frame, bg='black')
        freq_middle_frame.grid(row=1, column=0, columnspan=3, pady=2)
        
        self.freq_left_btn = tk.Button(freq_middle_frame, text="◄", 
                                     font=("Arial", 12, "bold"), bg="lightgray", fg="black",
                                     width=3, height=1, command=self.freq_left)
        self.freq_left_btn.pack(side=tk.LEFT, padx=2)
        
        self.freq_display = tk.Label(freq_middle_frame, text="1.0", 
                                   font=("Courier", 14, "bold"), fg="yellow", bg="black",
                                   width=8, relief="sunken", bd=2)
        self.freq_display.pack(side=tk.LEFT, padx=5)
        
        self.freq_right_btn = tk.Button(freq_middle_frame, text="►", 
                                      font=("Arial", 12, "bold"), bg="lightgray", fg="black",
                                      width=3, height=1, command=self.freq_right)
        self.freq_right_btn.pack(side=tk.LEFT, padx=2)
        
        # Down button
        self.freq_down_btn = tk.Button(freq_control_frame, text="▼", 
                                     font=("Arial", 12, "bold"), bg="lightgray", fg="black",
                                     width=3, height=1, command=self.freq_down)
        self.freq_down_btn.grid(row=2, column=1, padx=2, pady=1)

    def _setup_transmit_controls(self, parent):
        """Setup transmit time controls"""
        transmit_section = tk.Frame(parent, bg='black')
        transmit_section.pack(side=tk.LEFT, padx=(0, 20))
        
        tk.Label(transmit_section, text="Transmit Time", font=("Arial", 10), 
                fg="white", bg="black").pack()
        tk.Label(transmit_section, text="(seconds)", font=("Arial", 8), 
                fg="orange", bg="black").pack()
        
        transmit_control_frame = tk.Frame(transmit_section, bg='black')
        transmit_control_frame.pack(pady=(5, 0))
        
        # Transmit up button
        self.transmit_up_btn = tk.Button(transmit_control_frame, text="▲", 
                                       font=("Arial", 12, "bold"), bg="lightgray", fg="black",
                                       width=3, height=1, command=self.transmit_time_up)
        self.transmit_up_btn.grid(row=0, column=1, padx=2, pady=1)
        
        # Transmit display
        self.transmit_display = tk.Label(transmit_control_frame, text="60", 
                                       font=("Courier", 14, "bold"), fg="lightgreen", bg="black",
                                       width=8, relief="sunken", bd=2)
        self.transmit_display.grid(row=1, column=1, padx=2, pady=2)
        
        # Transmit down button
        self.transmit_down_btn = tk.Button(transmit_control_frame, text="▼", 
                                         font=("Arial", 12, "bold"), bg="lightgray", fg="black",
                                         width=3, height=1, command=self.transmit_time_down)
        self.transmit_down_btn.grid(row=2, column=1, padx=2, pady=1)

    def _setup_pause_controls(self, parent):
        """Setup pause time controls"""
        pause_section = tk.Frame(parent, bg='black')
        pause_section.pack(side=tk.LEFT)
        
        tk.Label(pause_section, text="Pause Time", font=("Arial", 10), 
                fg="white", bg="black").pack()
        tk.Label(pause_section, text="(seconds)", font=("Arial", 8), 
                fg="orange", bg="black").pack()
        
        pause_control_frame = tk.Frame(pause_section, bg='black')
        pause_control_frame.pack(pady=(5, 0))
        
        # Pause up button
        self.pause_up_btn = tk.Button(pause_control_frame, text="▲", 
                                    font=("Arial", 12, "bold"), bg="lightgray", fg="black",
                                    width=3, height=1, command=self.pause_time_up)
        self.pause_up_btn.grid(row=0, column=1, padx=2, pady=1)
        
        # Pause display
        self.pause_display = tk.Label(pause_control_frame, text="30", 
                                    font=("Courier", 14, "bold"), fg="lightcoral", bg="black",
                                    width=8, relief="sunken", bd=2)
        self.pause_display.grid(row=1, column=1, padx=2, pady=2)
        
        # Pause down button
        self.pause_down_btn = tk.Button(pause_control_frame, text="▼", 
                                      font=("Arial", 12, "bold"), bg="lightgray", fg="black",
                                      width=3, height=1, command=self.pause_time_down)
        self.pause_down_btn.grid(row=2, column=1, padx=2, pady=1)

    def _setup_button_section(self, parent):
        """Setup control buttons and status displays"""
        tx_frame = tk.Frame(parent, bg='black')
        tx_frame.pack(fill=tk.X, pady=(0, 8))
        
        # Control buttons
        button_frame = tk.Frame(tx_frame, bg='black')
        button_frame.pack(anchor='center')  # Center the button frame
        
        self.start_button = tk.Button(button_frame, text="START", command=self.start_countdown,
                                    font=("Arial", 12, "bold"), bg="green", fg="white", 
                                    width=6, height=1)
        self.start_button.pack(side=tk.LEFT, padx=(0, 8))
        
        self.stop_button = tk.Button(button_frame, text="STOP", command=self.stop_transmission,
                                   font=("Arial", 12, "bold"), bg="red", fg="white", 
                                   width=6, height=1, state="disabled")
        self.stop_button.pack(side=tk.LEFT)
        
        # Countdown and status display
        status_display_frame = tk.Frame(tx_frame, bg='black')
        status_display_frame.pack(pady=(2, 2))

        # Single line for countdown and status
        self.status_line_frame = tk.Frame(status_display_frame, bg='black')
        self.status_line_frame.pack()

        self.countdown_label = tk.Label(self.status_line_frame, text="", 
                                      font=("Courier", 14, "bold"), fg="yellow", bg="black")
        self.countdown_label.pack(side=tk.LEFT, padx=(0, 10))

        self.tx_status_label = tk.Label(self.status_line_frame, text="NOT TRANSMITTING", 
                                      font=("Courier", 14, "bold"), fg="red", bg="black")
        self.tx_status_label.pack(side=tk.LEFT)

    def _setup_indicator_section(self, parent):
        """Setup GPIO status indicators"""
        status_display_frame = tk.Frame(parent, bg='black')
        status_display_frame.pack()
        
        # GPIO Status Indicators with PPS
        gpio_indicators_frame = tk.Frame(status_display_frame, bg='black')
        gpio_indicators_frame.pack(pady=(5, 2))
        
        # PPS indicator (GPIO 17)
        pps_frame = tk.Frame(gpio_indicators_frame, bg='black')
        pps_frame.pack(side=tk.LEFT, padx=(0, 15))
        
        tk.Label(pps_frame, text="PPS", font=("Arial", 8), 
                fg="white", bg="black").pack()
        self.pps_indicator = tk.Label(pps_frame, text="●", font=("Arial", 32), 
                                     fg="gray", bg="black")
        self.pps_indicator.pack()
        
        # ON/OFF indicator (GPIO 13)
        onoff_frame = tk.Frame(gpio_indicators_frame, bg='black')
        onoff_frame.pack(side=tk.LEFT, padx=(0, 15))
        
        tk.Label(onoff_frame, text="ON/OFF", font=("Arial", 8), 
                fg="white", bg="black").pack()
        self.onoff_indicator = tk.Label(onoff_frame, text="●", font=("Arial", 32), 
                                       fg="gray", bg="black")
        self.onoff_indicator.pack()
        
        # Duty indicator (GPIO 6)
        duty_frame = tk.Frame(gpio_indicators_frame, bg='black')
        duty_frame.pack(side=tk.LEFT, padx=(0, 15))
        
        tk.Label(duty_frame, text="Duty", font=("Arial", 8), 
                fg="white", bg="black").pack()
        self.duty_indicator = tk.Label(duty_frame, text="●", font=("Arial", 32), 
                                      fg="gray", bg="black")
        self.duty_indicator.pack()
        
        # Polarity indicator (GPIO 26)
        polarity_frame = tk.Frame(gpio_indicators_frame, bg='black')
        polarity_frame.pack(side=tk.LEFT, padx=(0, 15))
        
        tk.Label(polarity_frame, text="Polarity", font=("Arial", 8), 
                fg="white", bg="black").pack()
        self.polarity_indicator = tk.Label(polarity_frame, text="●", font=("Arial", 32), 
                                          fg="gray", bg="black")
        self.polarity_indicator.pack()

        # Recording Indicator
        recording_frame = tk.Frame(gpio_indicators_frame, bg='black')
        recording_frame.pack(side=tk.LEFT, padx=(15, 5))

        tk.Label(recording_frame, text="Rec", font=("Arial", 8), 
                fg="white", bg="black").pack()
        self.recording_indicator = tk.Label(recording_frame, text="●", font=("Arial", 32), 
                                          fg="gray", bg="black")
        self.recording_indicator.pack()

        # Log Size Displays
        logsize_frame = tk.Frame(gpio_indicators_frame, bg='black')
        logsize_frame.pack(side=tk.LEFT, padx=(10, 0))

        self.logsize_label = tk.Label(logsize_frame, text="Log: -- KB", font=("Arial", 9), 
                                    fg="lightgray", bg="black")
        self.logsize_label.pack(anchor='w')

        self.gpslogsize_label = tk.Label(logsize_frame, text="GPS Log: -- KB", font=("Arial", 9), 
                                       fg="lightgray", bg="black")
        self.gpslogsize_label.pack(anchor='w')

    # Event handlers for user interactions
    def start_countdown(self):
        """Start countdown to transmission"""
        if not self.gui_initialized:
            return
            
        success = self.app_controller.start_countdown_and_transmission()
        
        if success:
            self.start_button.config(state="disabled")
            self.stop_button.config(state="normal")

    def stop_transmission(self):
        """Stop transmission"""
        if not self.gui_initialized:
            return
            
        self.app_controller.stop_transmission()
        
        # Update GUI
        self.start_button.config(state="normal")
        self.stop_button.config(state="disabled")
        self.countdown_label.config(text="")
        self.tx_status_label.config(text="NOT TRANSMITTING", fg="red")

    def sync_rtc_time(self):
        """Initiate GPS to RTC synchronization"""
        if not self.app_controller or not self.gui_initialized:
            return
            
        success = self.app_controller.sync_rtc_time(
            success_callback=self.sync_success,
            error_callback=self.sync_error
        )
        
        if success:
            self.sync_button.config(state="disabled")
            self.sync_status_label.config(text="Sync in progress...", fg="orange")

    def sync_success(self, sync_time):
        """Called after successful sync"""
        if not self.gui_initialized:
            return
        sync_str = sync_time.strftime("%Y-%m-%d %H:%M:%S")
        self.sync_status_label.config(text=f"Last sync: {sync_str}", fg="lightblue")
        self.sync_button.config(state="normal")

    def sync_error(self, error):
        """Called after sync error"""
        if not self.gui_initialized:
            return
        self.sync_status_label.config(text=f"Sync error: {str(error)}", fg="red")
        self.sync_button.config(state="normal")

    # Frequency control methods
    def freq_up(self):
        """Increase frequency at current decimal place"""
        if not self.gui_initialized:
            return
        self.app_controller.get_frequency_controller().frequency_up()

    def freq_down(self):
        """Decrease frequency at current decimal place"""
        if not self.gui_initialized:
            return
        self.app_controller.get_frequency_controller().frequency_down()

    def freq_left(self):
        """Move decimal place to the left (higher significance)"""
        if not self.gui_initialized:
            return
        self.app_controller.get_frequency_controller().decimal_place_left()

    def freq_right(self):
        """Move decimal place to the right (lower significance)"""
        if not self.gui_initialized:
            return
        self.app_controller.get_frequency_controller().decimal_place_right()

    # Transmit/Pause time control methods
    def transmit_time_up(self):
        """Increase transmit time"""
        if not self.gui_initialized:
            return
        current = int(self.transmit_display.cget("text"))
        new_time = min(3600, current + 1)  # Max 1 hour, increment by 1 second
        self.transmit_display.config(text=str(new_time))
        self.app_controller.update_transmit_time(new_time)

    def transmit_time_down(self):
        """Decrease transmit time"""
        if not self.gui_initialized:
            return
        current = int(self.transmit_display.cget("text"))
        new_time = max(1, current - 1)  # Min 1 second, decrement by 1 second
        self.transmit_display.config(text=str(new_time))
        self.app_controller.update_transmit_time(new_time)

    def pause_time_up(self):
        """Increase pause time"""
        if not self.gui_initialized:
            return
        current = int(self.pause_display.cget("text"))
        new_time = min(3600, current + 1)  # Max 1 hour, increment by 1 second
        self.pause_display.config(text=str(new_time))
        self.app_controller.update_pause_time(new_time)

    def pause_time_down(self):
        """Decrease pause time"""
        if not self.gui_initialized:
            return
        current = int(self.pause_display.cget("text"))
        new_time = max(0, current - 1)  # Min 0 seconds, decrement by 1 second
        self.pause_display.config(text=str(new_time))
        self.app_controller.update_pause_time(new_time)

    # Callback methods for updating GUI from application controller
    def update_status(self, msg, color=None):
        """Update status message"""
        if not self.gui_initialized:
            return
        if color:
            color_map = {"red": "red", "green": "green", "orange": "orange"}
            fg_color = color_map.get(color, "gray")
        else:
            fg_color = "orange"
        self.root.after(0, lambda: self.status_label.config(text=msg, fg=fg_color))

    def update_sync_status(self, msg, color=None):
        """Update sync-related status"""
        if not self.gui_initialized:
            return
        color_map = {"red": "red", "green": "green", "orange": "orange"}
        fg_color = color_map.get(color, "gray")
        self.root.after(0, lambda: self.status_label.config(text=msg, fg=fg_color))

    def update_time_displays(self, cached_times):
        """Update the time display labels with cached synchronized times"""
        if not self.gui_initialized:
            return
        self.root.after(0, lambda: self._update_time_labels(cached_times))

    def _update_time_labels(self, cached_times):
        """Update time labels (called on main thread)"""
        if not self.gui_initialized:
            return
            
        # Update RPI time
        if cached_times['rpi']:
            rpi_time_str = cached_times['rpi'].strftime("%Y-%m-%d %H:%M:%S")
            self.rpi_time_label.config(text=f"RPI Time (UTC): {rpi_time_str}")
        
        # Update GPS time
        if cached_times['gps']:
            gps_time_str = cached_times['gps'].strftime("%Y-%m-%d %H:%M:%S")
            self.gps_time_label.config(text=f"GPS Time (UTC): {gps_time_str}")
        else:
            self.gps_time_label.config(text="GPS Time (UTC): --")
        
        # Update RTC time
        if cached_times['rtc']:
            rtc_time_str = cached_times['rtc'].strftime("%Y-%m-%d %H:%M:%S")
            self.rtc_time_label.config(text=f"RTC Time (UTC): {rtc_time_str}", fg="yellow")
        else:
            self.rtc_time_label.config(text="RTC Time (UTC): Read Error", fg="red")

    def update_frequency_display(self, frequency, period, decimal_place_name):
        """Update frequency display elements"""
        if not self.gui_initialized:
            return
        self.root.after(0, lambda: self._update_freq_labels(frequency, period, decimal_place_name))
    
    def _update_freq_labels(self, frequency, period, decimal_place_name):
        """Update frequency labels (called on main thread)"""
        if not self.gui_initialized:
            return
        self.freq_display.config(text=f"{frequency:.3f}")
        self.period_display.config(text=f"Period: {period:.3f}s")
        self.decimal_indicator.config(text=f"Editing: {decimal_place_name} place")

    def update_countdown_display(self, countdown_text):
        """Update countdown display"""
        if not self.gui_initialized:
            return
        
        def update_labels():
            # Update log sizes
            self.update_log_sizes()
            
            # Clear countdown text when it reaches zero
            if "00:00" in countdown_text:
                self.countdown_label.config(text="")
                self.tx_status_label.config(text="TRANSMITTING", fg="green")
            else:
                self.countdown_label.config(text=countdown_text)
                self.tx_status_label.config(text="COUNTDOWN", fg="yellow")
        
        self.root.after(0, update_labels)

    def update_gps_data(self, data):
        """Update GPS data display"""
        if not self.gui_initialized:
            return
            
        def update_gps_labels():
            # Update compact GPS display
            lat_str = data['lat'] if data['lat'] != 'N/A' else '---'
            lon_str = data['lon'] if data['lon'] != 'N/A' else '---'
            sats_str = data['sats'] if data['sats'] != 'N/A' else '--'
            
            self.lat_label.config(text=f"Lat: {lat_str}")
            self.lon_label.config(text=f"Long: {lon_str}")
            self.sats_label.config(text=f"Sats: {sats_str}")
        
        self.root.after(0, update_gps_labels)

    def update_pps_indicator(self, pps_state):
        """Update PPS indicator based on GPIO 17 state"""
        if not self.gui_initialized:
            return
        self.root.after(0, lambda: self.pps_indicator.config(fg="yellow" if pps_state else "gray"))

    def update_onoff_indicator(self, state):
        """Update ON/OFF indicator"""
        if not self.gui_initialized:
            return
        self.root.after(0, lambda: self.onoff_indicator.config(fg="lightblue" if state else "gray"))

    def update_duty_indicator(self, state):
        """Update Duty indicator"""
        if not self.gui_initialized:
            return
        self.root.after(0, lambda: self.duty_indicator.config(fg="lightblue" if state else "gray"))

    def update_polarity_indicator(self, state):
        """Update Polarity indicator"""
        if not self.gui_initialized:
            return
        self.root.after(0, lambda: self.polarity_indicator.config(fg="lightblue" if state else "gray"))

    def update_recording_indicator(self, recording_state):
        """Update recording indicator"""
        if not self.gui_initialized:
            return
        self.root.after(0, lambda: self.recording_indicator.config(fg="red" if recording_state else "gray"))

    def update_log_sizes(self):
        """Update log size displays"""
        if not self.gui_initialized:
            return
        
        def update_size_labels():
            sizes = self.app_controller.get_log_sizes()
            self.logsize_label.config(text=f"Log: {sizes['main_log_kb']:.1f} KB")
            self.gpslogsize_label.config(text=f"GPS Log: {sizes['gps_log_kb']:.1f} KB")
        
        self.root.after(0, update_size_labels)

    def process_updates(self):
        """Process any remaining queue-based updates"""
        if self.gui_initialized:
            # Update log sizes periodically
            self.update_log_sizes()
            self.root.after(1000, self.process_updates)  # Update every second

    def on_window_map(self, event):
        """Handle window mapping events"""
        if event.widget == self.root and self.gui_initialized:
            self.root.update_idletasks()
    
    def on_window_configure(self, event):
        """Handle window configuration changes"""
        if event.widget == self.root and self.gui_initialized:
            self.root.update_idletasks()

    def on_close(self):
        """Clean up and close application"""
        self.gui_initialized = False
        
        # Clean up application controller
        if hasattr(self, 'app_controller'):
            self.app_controller.cleanup()
        
        self.root.destroy()