import sys
from PyQt5.QtWidgets import (
    QApplication, QMainWindow, QWidget, QVBoxLayout, QHBoxLayout,
    QPushButton, QLabel, QFrame, QSizePolicy, QStyle, QTextEdit, QSplitter,
    QMenu, QAction, QInputDialog, QShortcut
)
from PyQt5.QtCore import Qt, QSize, QTimer, pyqtSignal
from PyQt5.QtGui import QFont, QTextCursor, QKeySequence
import time
import threading
from phone_manager import PhoneManager
from waveform_widget import WaveformWidget
from phone_state import PhoneState

class PhoneUI(QMainWindow):
    debug_signal = pyqtSignal(str)
    
    def __init__(self):
        super().__init__()
        self.setWindowTitle("DryBox - Noise XK + Codec2 + 4FSK")
        self.setGeometry(100, 100, 1200, 900)
        
        # Set minimum size to ensure window is resizable
        self.setMinimumSize(800, 600)
        
        # Auto test state
        self.auto_test_running = False
        self.auto_test_timer = None
        self.test_step = 0
        self.setStyleSheet("""
            QMainWindow { background-color: #333333; }
            QLabel { color: #E0E0E0; font-size: 14px; }
            QPushButton {
                background-color: #0078D4; color: white; border: none;
                padding: 10px 15px; border-radius: 5px; font-size: 14px;
                min-height: 30px;
            }
            QPushButton:hover { background-color: #005A9E; }
            QPushButton:pressed { background-color: #003C6B; }
            QPushButton#settingsButton { background-color: #555555; }
            QPushButton#settingsButton:hover { background-color: #777777; }
            QFrame#phoneDisplay {
                background-color: #1E1E1E; border: 2px solid #0078D4;
                border-radius: 10px;
            }
            QLabel#phoneTitleLabel {
                font-size: 18px; font-weight: bold; padding-bottom: 5px;
                color: #FFFFFF;
            }
            QLabel#mainTitleLabel {
                font-size: 24px; font-weight: bold; color: #00A2E8;
                padding: 15px;
            }
            QWidget#phoneWidget {
                border: 2px solid #4A4A4A; border-radius: 10px;
                background-color: #3A3A3A;
                min-width: 250px;
            }
            QTextEdit#debugConsole {
                background-color: #1E1E1E; color: #00FF00; 
                font-family: monospace; font-size: 12px;
                border: 2px solid #0078D4; border-radius: 5px;
            }
            QPushButton#autoTestButton {
                background-color: #FF8C00; min-height: 35px;
            }
            QPushButton#autoTestButton:hover { background-color: #FF7F00; }
        """)

        # Setup debug signal early
        self.debug_signal.connect(self.append_debug)
        
        self.manager = PhoneManager()
        self.manager.ui = self  # Set UI reference for debug logging
        self.manager.initialize_phones()

        # Main widget with splitter
        main_widget = QWidget()
        self.setCentralWidget(main_widget)
        main_layout = QVBoxLayout()
        main_widget.setLayout(main_layout)
        
        # Create splitter for phones and debug console
        self.splitter = QSplitter(Qt.Vertical)
        main_layout.addWidget(self.splitter)
        
        # Top widget for phones
        phones_widget = QWidget()
        phones_layout = QVBoxLayout()
        phones_layout.setSpacing(20)
        phones_layout.setContentsMargins(20, 20, 20, 20)
        phones_layout.setAlignment(Qt.AlignCenter)
        phones_widget.setLayout(phones_layout)

        # App Title
        app_title_label = QLabel("Integrated Protocol Control Panel")
        app_title_label.setObjectName("mainTitleLabel")
        app_title_label.setAlignment(Qt.AlignCenter)
        phones_layout.addWidget(app_title_label)
        
        # Protocol info
        protocol_info = QLabel("Noise XK + Codec2 (1200bps) + 4FSK")
        protocol_info.setAlignment(Qt.AlignCenter)
        protocol_info.setStyleSheet("font-size: 12px; color: #00A2E8;")
        phones_layout.addWidget(protocol_info)

        # Phone displays layout
        phone_controls_layout = QHBoxLayout()
        phone_controls_layout.setSpacing(20)
        phone_controls_layout.setContentsMargins(10, 0, 10, 0)
        phones_layout.addLayout(phone_controls_layout)

        # Setup UI for phones
        for phone in self.manager.phones:
            phone_container_widget, phone_display_frame, phone_button, waveform_widget, sent_waveform_widget, phone_status_label, playback_button, record_button = self._create_phone_ui(
                f"Phone {phone['id']+1}", lambda checked, pid=phone['id']: self.manager.phone_action(pid, self)
            )
            phone['button'] = phone_button
            phone['waveform'] = waveform_widget
            phone['sent_waveform'] = sent_waveform_widget
            phone['status_label'] = phone_status_label
            phone['playback_button'] = playback_button
            phone['record_button'] = record_button
            
            # Connect audio control buttons with proper closure
            playback_button.clicked.connect(lambda checked, pid=phone['id']: self.toggle_playback(pid))
            record_button.clicked.connect(lambda checked, pid=phone['id']: self.toggle_recording(pid))
            phone_controls_layout.addWidget(phone_container_widget)
            # Connect data_received signal - it emits (data, client_id)
            phone['client'].data_received.connect(lambda data, cid: self.manager.update_waveform(cid, data))
            phone['client'].state_changed.connect(lambda state, num, cid=phone['id']: self.set_phone_state(cid, state, num))
            phone['client'].start()

        # Control buttons layout
        control_layout = QHBoxLayout()
        control_layout.setSpacing(15)
        control_layout.setContentsMargins(20, 10, 20, 10)
        
        # Auto Test Button
        self.auto_test_button = QPushButton("🧪 Run Automatic Test")
        self.auto_test_button.setObjectName("autoTestButton")
        self.auto_test_button.setMinimumWidth(180)
        self.auto_test_button.setMaximumWidth(250)
        self.auto_test_button.clicked.connect(self.toggle_auto_test)
        control_layout.addWidget(self.auto_test_button)
        
        # Clear Debug Button
        self.clear_debug_button = QPushButton("Clear Debug")
        self.clear_debug_button.setMinimumWidth(100)
        self.clear_debug_button.setMaximumWidth(150)
        self.clear_debug_button.clicked.connect(self.clear_debug)
        control_layout.addWidget(self.clear_debug_button)
        
        # Audio Processing Button
        self.audio_menu_button = QPushButton("Audio Options")
        self.audio_menu_button.setMinimumWidth(100)
        self.audio_menu_button.setMaximumWidth(150)
        self.audio_menu_button.clicked.connect(self.show_audio_menu)
        control_layout.addWidget(self.audio_menu_button)
        
        # Settings Button
        self.settings_button = QPushButton("Settings")
        self.settings_button.setObjectName("settingsButton")
        self.settings_button.setMinimumWidth(100)
        self.settings_button.setMaximumWidth(150)
        self.settings_button.setIcon(self.style().standardIcon(QStyle.SP_FileDialogDetailedView))
        self.settings_button.setIconSize(QSize(20, 20))
        self.settings_button.clicked.connect(self.settings_action)
        control_layout.addWidget(self.settings_button)
        
        phones_layout.addLayout(control_layout)
        
        # Add phones widget to splitter
        self.splitter.addWidget(phones_widget)
        
        # Debug console
        self.debug_console = QTextEdit()
        self.debug_console.setObjectName("debugConsole")
        self.debug_console.setReadOnly(True)
        self.debug_console.setMinimumHeight(200)
        self.debug_console.setMaximumHeight(400)
        self.splitter.addWidget(self.debug_console)
        
        # Flush any queued debug messages
        if hasattr(self, '_debug_queue'):
            for msg in self._debug_queue:
                self.debug_console.append(msg)
            del self._debug_queue
        
        # Set splitter sizes (70% phones, 30% debug)
        self.splitter.setSizes([600, 300])

        # Initialize UI
        for phone in self.manager.phones:
            self.update_phone_ui(phone['id'])
            
        # Initial debug message
        QTimer.singleShot(100, lambda: self.debug("DryBox UI initialized with integrated protocol"))
        
        # Setup keyboard shortcuts
        self.setup_shortcuts()

    def _create_phone_ui(self, title, action_slot):
        phone_container_widget = QWidget()
        phone_container_widget.setObjectName("phoneWidget")
        phone_container_widget.setSizePolicy(QSizePolicy.Preferred, QSizePolicy.Preferred)
        phone_layout = QVBoxLayout()
        phone_layout.setAlignment(Qt.AlignCenter)
        phone_layout.setSpacing(10)
        phone_layout.setContentsMargins(15, 15, 15, 15)
        phone_container_widget.setLayout(phone_layout)

        phone_title_label = QLabel(title)
        phone_title_label.setObjectName("phoneTitleLabel")
        phone_title_label.setAlignment(Qt.AlignCenter)
        phone_layout.addWidget(phone_title_label)

        phone_display_frame = QFrame()
        phone_display_frame.setObjectName("phoneDisplay")
        phone_display_frame.setMinimumSize(200, 250)
        phone_display_frame.setMaximumSize(300, 400)
        phone_display_frame.setSizePolicy(QSizePolicy.Preferred, QSizePolicy.Preferred)

        display_content_layout = QVBoxLayout(phone_display_frame)
        display_content_layout.setAlignment(Qt.AlignCenter)
        phone_status_label = QLabel("Idle")
        phone_status_label.setAlignment(Qt.AlignCenter)
        phone_status_label.setFont(QFont("Arial", 16))
        display_content_layout.addWidget(phone_status_label)
        phone_layout.addWidget(phone_display_frame, alignment=Qt.AlignCenter)

        phone_button = QPushButton()
        phone_button.setMinimumWidth(100)
        phone_button.setMaximumWidth(150)
        phone_button.setIconSize(QSize(20, 20))
        phone_button.clicked.connect(action_slot)
        phone_layout.addWidget(phone_button, alignment=Qt.AlignCenter)

        # Received waveform
        waveform_label = QLabel(f"{title} Received")
        waveform_label.setAlignment(Qt.AlignCenter)
        waveform_label.setStyleSheet("font-size: 12px; color: #E0E0E0;")
        phone_layout.addWidget(waveform_label)
        waveform_widget = WaveformWidget(dynamic=False)
        waveform_widget.setMinimumSize(200, 50)
        waveform_widget.setMaximumSize(300, 80)
        waveform_widget.setSizePolicy(QSizePolicy.Preferred, QSizePolicy.Fixed)
        phone_layout.addWidget(waveform_widget, alignment=Qt.AlignCenter)

        # Sent waveform
        sent_waveform_label = QLabel(f"{title} Sent")
        sent_waveform_label.setAlignment(Qt.AlignCenter)
        sent_waveform_label.setStyleSheet("font-size: 12px; color: #E0E0E0;")
        phone_layout.addWidget(sent_waveform_label)
        sent_waveform_widget = WaveformWidget(dynamic=False)
        sent_waveform_widget.setMinimumSize(200, 50)
        sent_waveform_widget.setMaximumSize(300, 80)
        sent_waveform_widget.setSizePolicy(QSizePolicy.Preferred, QSizePolicy.Fixed)
        phone_layout.addWidget(sent_waveform_widget, alignment=Qt.AlignCenter)
        
        # Audio control buttons
        audio_controls_layout = QHBoxLayout()
        audio_controls_layout.setAlignment(Qt.AlignCenter)
        
        playback_button = QPushButton("🔊 Playback")
        playback_button.setCheckable(True)
        playback_button.setMinimumWidth(90)
        playback_button.setMaximumWidth(120)
        playback_button.setStyleSheet("""
            QPushButton {
                background-color: #404040;
                color: white;
                border: 1px solid #606060;
                padding: 5px;
                border-radius: 3px;
            }
            QPushButton:checked {
                background-color: #4CAF50;
            }
            QPushButton:hover {
                background-color: #505050;
            }
        """)
        
        record_button = QPushButton("⏺ Record")
        record_button.setCheckable(True)
        record_button.setMinimumWidth(90)
        record_button.setMaximumWidth(120)
        record_button.setStyleSheet("""
            QPushButton {
                background-color: #404040;
                color: white;
                border: 1px solid #606060;
                padding: 5px;
                border-radius: 3px;
            }
            QPushButton:checked {
                background-color: #F44336;
            }
            QPushButton:hover {
                background-color: #505050;
            }
        """)
        
        audio_controls_layout.addWidget(playback_button)
        audio_controls_layout.addWidget(record_button)
        phone_layout.addLayout(audio_controls_layout)

        return phone_container_widget, phone_display_frame, phone_button, waveform_widget, sent_waveform_widget, phone_status_label, playback_button, record_button

    def update_phone_ui(self, phone_id):
        phone = self.manager.phones[phone_id]
        other_phone = self.manager.phones[1 - phone_id]
        state = phone['state']
        phone_number = other_phone['number'] if state != PhoneState.IDLE else ""
        button = phone['button']
        status_label = phone['status_label']

        if state == PhoneState.IDLE:
            button.setText("Call")
            button.setIcon(self.style().standardIcon(QStyle.SP_MediaPlay))
            status_label.setText("Idle")
            button.setStyleSheet("background-color: #0078D4;")
        elif state == PhoneState.CALLING:
            button.setText("Cancel")
            button.setIcon(self.style().standardIcon(QStyle.SP_MediaStop))
            status_label.setText(f"Calling {phone_number}...")
            button.setStyleSheet("background-color: #E81123;")
        elif state == PhoneState.IN_CALL:
            button.setText("Hang Up")
            button.setIcon(self.style().standardIcon(QStyle.SP_DialogCancelButton))
            status_label.setText(f"In Call with {phone_number}")
            button.setStyleSheet("background-color: #E81123;")
        elif state == PhoneState.RINGING:
            button.setText("Answer")
            button.setIcon(self.style().standardIcon(QStyle.SP_DialogApplyButton))
            status_label.setText(f"Incoming Call from {phone_number}")
            button.setStyleSheet("background-color: #107C10;")

    def set_phone_state(self, client_id, state_str, number):
        self.debug(f"Phone {client_id + 1} state change: {state_str}")
        
        # Handle protocol-specific states
        if state_str == "HANDSHAKE_COMPLETE":
            phone = self.manager.phones[client_id]
            phone['status_label'].setText("🔒 Secure Channel Established")
            self.debug(f"Phone {client_id + 1} secure channel established")
            self.manager.start_audio(client_id, parent=self)
            return
        elif state_str == "VOICE_START":
            phone = self.manager.phones[client_id]
            phone['status_label'].setText("🎤 Voice Active (Encrypted)")
            self.debug(f"Phone {client_id + 1} voice session started")
            return
        elif state_str == "VOICE_END":
            phone = self.manager.phones[client_id]
            phone['status_label'].setText("🔒 Secure Channel")
            self.debug(f"Phone {client_id + 1} voice session ended")
            return
            
        # Handle regular states
        state = self.manager.map_state(state_str)
        phone = self.manager.phones[client_id]
        other_phone = self.manager.phones[1 - client_id]
        self.debug(f"Setting state for Phone {client_id + 1}: {state.name if hasattr(state, 'name') else state}, number: {number}, is_initiator: {phone['is_initiator']}")
        phone['state'] = state
        if state == PhoneState.IN_CALL:
            self.debug(f"Phone {client_id + 1} confirmed in IN_CALL state")
            self.debug(f"  state_str={state_str}, number={number}")
            self.debug(f"  is_initiator={phone['is_initiator']}")
            
            # Only start handshake when the initiator RECEIVES the IN_CALL message
            if state_str == "IN_CALL" and phone['is_initiator']:
                self.debug(f"Phone {client_id + 1} (initiator) received IN_CALL, starting handshake")
                phone['client'].start_handshake(initiator=True, keypair=phone['keypair'], peer_pubkey=other_phone['public_key'])
            elif number == "HANDSHAKE":
                # Old text-based handshake trigger - no longer used
                self.debug(f"Phone {client_id + 1} received legacy HANDSHAKE message")
            elif number == "HANDSHAKE_DONE":
                self.debug(f"Phone {client_id + 1} received HANDSHAKE_DONE")
                # Handled by HANDSHAKE_COMPLETE now
                pass
        self.update_phone_ui(client_id)

    def settings_action(self):
        print("Settings clicked")
        self.debug("Settings clicked")

    def debug(self, message):
        """Thread-safe debug logging to both console and UI"""
        timestamp = time.strftime("%H:%M:%S.%f")[:-3]
        debug_msg = f"[{timestamp}] {message}"
        print(debug_msg)  # Console output
        self.debug_signal.emit(debug_msg)  # UI output
    
    def append_debug(self, message):
        """Append debug message to console (called from main thread)"""
        if hasattr(self, 'debug_console'):
            self.debug_console.append(message)
            # Auto-scroll to bottom
            cursor = self.debug_console.textCursor()
            cursor.movePosition(QTextCursor.End)
            self.debug_console.setTextCursor(cursor)
        else:
            # Queue messages until console is ready
            if not hasattr(self, '_debug_queue'):
                self._debug_queue = []
            self._debug_queue.append(message)
    
    def clear_debug(self):
        """Clear debug console"""
        self.debug_console.clear()
        self.debug("Debug console cleared")
    
    def toggle_auto_test(self):
        """Toggle automatic test sequence"""
        if not self.auto_test_running:
            self.start_auto_test()
        else:
            self.stop_auto_test()
    
    def start_auto_test(self):
        """Start automatic test sequence"""
        self.auto_test_running = True
        self.auto_test_button.setText("⏹ Stop Test")
        self.test_step = 0
        
        self.debug("=== STARTING AUTOMATIC TEST SEQUENCE ===")
        self.debug("Test will go through complete protocol flow")
        
        # Start test timer
        self.auto_test_timer = QTimer()
        self.auto_test_timer.timeout.connect(self.execute_test_step)
        self.auto_test_timer.start(2000)  # 2 second intervals
        
        # Execute first step immediately
        self.execute_test_step()
    
    def stop_auto_test(self):
        """Stop automatic test sequence"""
        self.auto_test_running = False
        self.auto_test_button.setText("🧪 Run Automatic Test")
        
        if self.auto_test_timer:
            self.auto_test_timer.stop()
            self.auto_test_timer = None
        
        self.debug("=== TEST SEQUENCE STOPPED ===")
    
    def execute_test_step(self):
        """Execute next step in test sequence"""
        phone1 = self.manager.phones[0]
        phone2 = self.manager.phones[1]
        
        self.debug(f"\n--- Test Step {self.test_step + 1} ---")
        
        if self.test_step == 0:
            # Step 1: Check initial state
            self.debug("Checking initial state...")
            state1 = phone1['state']
            state2 = phone2['state']
            # Handle both enum and int states
            state1_name = state1.name if hasattr(state1, 'name') else str(state1)
            state2_name = state2.name if hasattr(state2, 'name') else str(state2)
            self.debug(f"Phone 1 state: {state1_name}")
            self.debug(f"Phone 2 state: {state2_name}")
            self.debug(f"Phone 1 connected: {phone1['client'].sock is not None}")
            self.debug(f"Phone 2 connected: {phone2['client'].sock is not None}")
            
        elif self.test_step == 1:
            # Step 2: Make call
            self.debug("Phone 1 calling Phone 2...")
            self.manager.phone_action(0, self)
            state1_name = phone1['state'].name if hasattr(phone1['state'], 'name') else str(phone1['state'])
            state2_name = phone2['state'].name if hasattr(phone2['state'], 'name') else str(phone2['state'])
            self.debug(f"Phone 1 state after call: {state1_name}")
            self.debug(f"Phone 2 state after call: {state2_name}")
            
        elif self.test_step == 2:
            # Step 3: Answer call
            self.debug("Phone 2 answering call...")
            self.manager.phone_action(1, self)
            state1_name = phone1['state'].name if hasattr(phone1['state'], 'name') else str(phone1['state'])
            state2_name = phone2['state'].name if hasattr(phone2['state'], 'name') else str(phone2['state'])
            self.debug(f"Phone 1 state after answer: {state1_name}")
            self.debug(f"Phone 2 state after answer: {state2_name}")
            self.debug(f"Phone 1 is_initiator: {phone1['is_initiator']}")
            self.debug(f"Phone 2 is_initiator: {phone2['is_initiator']}")
            
        elif self.test_step == 3:
            # Step 4: Check handshake progress
            self.debug("Checking handshake progress...")
            self.debug(f"Phone 1 handshake in progress: {phone1['client'].state.handshake_in_progress}")
            self.debug(f"Phone 2 handshake in progress: {phone2['client'].state.handshake_in_progress}")
            self.debug(f"Phone 1 command queue: {phone1['client'].state.command_queue.qsize()}")
            self.debug(f"Phone 2 command queue: {phone2['client'].state.command_queue.qsize()}")
            # Increase timer interval for handshake
            self.auto_test_timer.setInterval(3000)  # 3 seconds
            
        elif self.test_step == 4:
            # Step 5: Check handshake status
            self.debug("Checking Noise XK handshake status...")
            self.debug(f"Phone 1 handshake complete: {phone1['client'].handshake_complete}")
            self.debug(f"Phone 2 handshake complete: {phone2['client'].handshake_complete}")
            self.debug(f"Phone 1 has session: {phone1['client'].noise_session is not None}")
            self.debug(f"Phone 2 has session: {phone2['client'].noise_session is not None}")
            # Reset timer interval
            self.auto_test_timer.setInterval(2000)
            
        elif self.test_step == 5:
            # Step 6: Check voice status
            self.debug("Checking voice session status...")
            self.debug(f"Phone 1 voice active: {phone1['client'].voice_active}")
            self.debug(f"Phone 2 voice active: {phone2['client'].voice_active}")
            self.debug(f"Phone 1 codec initialized: {phone1['client'].codec is not None}")
            self.debug(f"Phone 2 codec initialized: {phone2['client'].codec is not None}")
            self.debug(f"Phone 1 modem initialized: {phone1['client'].modem is not None}")
            self.debug(f"Phone 2 modem initialized: {phone2['client'].modem is not None}")
            
        elif self.test_step == 6:
            # Step 7: Check audio transmission
            self.debug("Checking audio transmission...")
            self.debug(f"Phone 1 audio file loaded: {phone1['audio_file'] is not None}")
            self.debug(f"Phone 2 audio file loaded: {phone2['audio_file'] is not None}")
            self.debug(f"Phone 1 frame counter: {phone1.get('frame_counter', 0)}")
            self.debug(f"Phone 2 frame counter: {phone2.get('frame_counter', 0)}")
            self.debug(f"Phone 1 audio timer active: {phone1['audio_timer'] is not None and phone1['audio_timer'].isActive()}")
            self.debug(f"Phone 2 audio timer active: {phone2['audio_timer'] is not None and phone2['audio_timer'].isActive()}")
            
        elif self.test_step == 7:
            # Step 8: Protocol details
            self.debug("Protocol stack details:")
            if phone1['client'].codec:
                self.debug(f"Codec mode: {phone1['client'].codec.mode.name}")
                self.debug(f"Frame size: {phone1['client'].codec.frame_bits} bits")
                self.debug(f"Frame duration: {phone1['client'].codec.frame_ms} ms")
            if phone1['client'].modem:
                self.debug(f"FSK frequencies: {phone1['client'].modem.frequencies}")
                self.debug(f"Symbol rate: {phone1['client'].modem.baud_rate} baud")
            
        elif self.test_step == 8:
            # Step 9: Wait for more frames
            self.debug("Letting voice transmission run...")
            self.auto_test_timer.setInterval(5000)  # Wait 5 seconds
            
        elif self.test_step == 9:
            # Step 10: Final statistics
            self.debug("Final transmission statistics:")
            self.debug(f"Phone 1 frames sent: {phone1.get('frame_counter', 0)}")
            self.debug(f"Phone 2 frames sent: {phone2.get('frame_counter', 0)}")
            self.auto_test_timer.setInterval(2000)  # Back to 2 seconds
            
        elif self.test_step == 10:
            # Step 11: Hang up
            self.debug("Hanging up call...")
            self.manager.phone_action(0, self)
            state1_name = phone1['state'].name if hasattr(phone1['state'], 'name') else str(phone1['state'])
            state2_name = phone2['state'].name if hasattr(phone2['state'], 'name') else str(phone2['state'])
            self.debug(f"Phone 1 state after hangup: {state1_name}")
            self.debug(f"Phone 2 state after hangup: {state2_name}")
            
        elif self.test_step == 11:
            # Complete
            self.debug("\n=== TEST SEQUENCE COMPLETE ===")
            self.debug("All protocol components tested successfully!")
            self.stop_auto_test()
            return
        
        self.test_step += 1
    
    def toggle_playback(self, phone_id):
        """Toggle audio playback for a phone"""
        is_enabled = self.manager.toggle_playback(phone_id)
        phone = self.manager.phones[phone_id]
        phone['playback_button'].setChecked(is_enabled)
        
        if is_enabled:
            self.debug(f"Phone {phone_id + 1}: Audio playback enabled")
        else:
            self.debug(f"Phone {phone_id + 1}: Audio playback disabled")
    
    def toggle_recording(self, phone_id):
        """Toggle audio recording for a phone"""
        is_recording, save_path = self.manager.toggle_recording(phone_id)
        phone = self.manager.phones[phone_id]
        phone['record_button'].setChecked(is_recording)
        
        if is_recording:
            self.debug(f"Phone {phone_id + 1}: Recording started")
        else:
            if save_path:
                self.debug(f"Phone {phone_id + 1}: Recording saved to {save_path}")
            else:
                self.debug(f"Phone {phone_id + 1}: Recording stopped (no data)")
    
    def show_audio_menu(self):
        """Show audio processing options menu"""
        menu = QMenu(self)
        
        # Create phone selection submenu
        for phone_id in range(2):
            phone_menu = menu.addMenu(f"Phone {phone_id + 1}")
            
            # Export buffer
            export_action = QAction("Export Audio Buffer", self)
            export_action.triggered.connect(lambda checked, pid=phone_id: self.export_audio_buffer(pid))
            phone_menu.addAction(export_action)
            
            # Clear buffer
            clear_action = QAction("Clear Audio Buffer", self)
            clear_action.triggered.connect(lambda checked, pid=phone_id: self.clear_audio_buffer(pid))
            phone_menu.addAction(clear_action)
            
            phone_menu.addSeparator()
            
            # Processing options
            normalize_action = QAction("Normalize Audio", self)
            normalize_action.triggered.connect(lambda checked, pid=phone_id: self.process_audio(pid, "normalize"))
            phone_menu.addAction(normalize_action)
            
            gain_action = QAction("Apply Gain...", self)
            gain_action.triggered.connect(lambda checked, pid=phone_id: self.apply_gain_dialog(pid))
            phone_menu.addAction(gain_action)
            
            noise_gate_action = QAction("Apply Noise Gate", self)
            noise_gate_action.triggered.connect(lambda checked, pid=phone_id: self.process_audio(pid, "noise_gate"))
            phone_menu.addAction(noise_gate_action)
            
            low_pass_action = QAction("Apply Low Pass Filter", self)
            low_pass_action.triggered.connect(lambda checked, pid=phone_id: self.process_audio(pid, "low_pass"))
            phone_menu.addAction(low_pass_action)
            
            high_pass_action = QAction("Apply High Pass Filter", self)
            high_pass_action.triggered.connect(lambda checked, pid=phone_id: self.process_audio(pid, "high_pass"))
            phone_menu.addAction(high_pass_action)
            
            remove_silence_action = QAction("Remove Silence", self)
            remove_silence_action.triggered.connect(lambda checked, pid=phone_id: self.process_audio(pid, "remove_silence"))
            phone_menu.addAction(remove_silence_action)
        
        # Show menu at button position
        menu.exec_(self.audio_menu_button.mapToGlobal(self.audio_menu_button.rect().bottomLeft()))
    
    def export_audio_buffer(self, phone_id):
        """Export audio buffer for a phone"""
        save_path = self.manager.export_buffered_audio(phone_id)
        if save_path:
            self.debug(f"Phone {phone_id + 1}: Audio buffer exported to {save_path}")
        else:
            self.debug(f"Phone {phone_id + 1}: No audio data to export")
    
    def clear_audio_buffer(self, phone_id):
        """Clear audio buffer for a phone"""
        self.manager.clear_audio_buffer(phone_id)
    
    def process_audio(self, phone_id, processing_type):
        """Process audio with specified type"""
        save_path = self.manager.process_audio(phone_id, processing_type)
        if save_path:
            self.debug(f"Phone {phone_id + 1}: Processed audio saved to {save_path}")
        else:
            self.debug(f"Phone {phone_id + 1}: Audio processing failed")
    
    def apply_gain_dialog(self, phone_id):
        """Show dialog to get gain value"""
        gain, ok = QInputDialog.getDouble(
            self, "Apply Gain", "Enter gain in dB:", 
            0.0, -20.0, 20.0, 1
        )
        if ok:
            save_path = self.manager.process_audio(phone_id, "gain", gain_db=gain)
            if save_path:
                self.debug(f"Phone {phone_id + 1}: Applied {gain}dB gain, saved to {save_path}")
    
    def setup_shortcuts(self):
        """Setup keyboard shortcuts"""
        # Phone 1 shortcuts
        QShortcut(QKeySequence("1"), self, lambda: self.manager.phone_action(0, self))
        QShortcut(QKeySequence("Ctrl+1"), self, lambda: self.toggle_playback(0))
        QShortcut(QKeySequence("Alt+1"), self, lambda: self.toggle_recording(0))
        
        # Phone 2 shortcuts
        QShortcut(QKeySequence("2"), self, lambda: self.manager.phone_action(1, self))
        QShortcut(QKeySequence("Ctrl+2"), self, lambda: self.toggle_playback(1))
        QShortcut(QKeySequence("Alt+2"), self, lambda: self.toggle_recording(1))
        
        # General shortcuts
        QShortcut(QKeySequence("Space"), self, self.toggle_auto_test)
        QShortcut(QKeySequence("Ctrl+L"), self, self.clear_debug)
        QShortcut(QKeySequence("Ctrl+A"), self, self.show_audio_menu)
        
        self.debug("Keyboard shortcuts enabled:")
        self.debug("  1/2: Phone action (call/answer/hangup)")
        self.debug("  Ctrl+1/2: Toggle playback")
        self.debug("  Alt+1/2: Toggle recording")
        self.debug("  Space: Toggle auto test")
        self.debug("  Ctrl+L: Clear debug")
        self.debug("  Ctrl+A: Audio options menu")

    def closeEvent(self, event):
        if self.auto_test_running:
            self.stop_auto_test()
        # Clean up audio player
        if hasattr(self.manager, 'audio_player'):
            self.manager.audio_player.cleanup()
        for phone in self.manager.phones:
            phone['client'].stop()
        event.accept()

if __name__ == "__main__":
    app = QApplication(sys.argv)
    window = PhoneUI()
    window.show()
    sys.exit(app.exec_())