"""
Main window — responsive full-screen layout.
Left: compass rose  |  Right: info panel
"""
import math
from pathlib import Path
from PyQt5.QtWidgets import (QMainWindow, QWidget, QHBoxLayout,
                              QDialog, QVBoxLayout, QListWidget,
                              QPushButton, QLabel, QApplication)
from PyQt5.QtCore    import Qt, QTimer
from PyQt5.QtGui     import QColor, QIcon

import config
from core.nmea_parser  import NavData, parse
from core.serial_reader import SerialReader
from ui.compass_widget  import CompassWidget
from ui.info_panel      import InfoPanel
import ui.styles as S


class MainWindow(QMainWindow):

    def __init__(self):
        super().__init__()
        self.setWindowTitle('AR Compass — Marine')
        _logo = Path(__file__).parent.parent / 'assets' / 'images' / 'ar_logo_full.png'
        if _logo.exists():
            self.setWindowIcon(QIcon(str(_logo)))
        self.showFullScreen()

        self._nav      = NavData()
        self._smooth   = 0.0
        self._readers: list[SerialReader] = []
        self._night    = False
        self._hdg_mode = 'M'   # 'M' magnetic, 'T' true

        self._build_ui()
        self._start_serial()
        self._start_timer()

    # ── UI ──────────────────────────────────────────────────────────────────

    def _build_ui(self):
        central = QWidget()
        self.setCentralWidget(central)
        central.setStyleSheet(f'background: {S.BG.name()};')

        hl = QHBoxLayout(central)
        hl.setContentsMargins(0, 0, 0, 0)
        hl.setSpacing(0)

        self.compass = CompassWidget()
        self.panel   = InfoPanel()

        # Divider
        div = QWidget()
        div.setFixedWidth(2)
        div.setStyleSheet(f'background: {S.DIVIDER.name()};')

        # 60 / 40 split
        hl.addWidget(self.compass, stretch=60)
        hl.addWidget(div)
        hl.addWidget(self.panel,   stretch=40)

        self.panel.night_toggled.connect(self._on_night)
        self.panel.port_requested.connect(self._show_port_dialog)
        self.panel.hdg_mode_changed.connect(self._on_hdg_mode)

    # ── Timer — animation & UI refresh ──────────────────────────────────────

    def _start_timer(self):
        self._timer = QTimer(self)
        self._timer.timeout.connect(self._tick)
        self._timer.start(config.UI_REFRESH_MS)

    def _tick(self):
        # Select heading source based on mode
        if self._hdg_mode == 'T':
            hdg = self._nav.hdg_true_calc
        else:
            hdg = self._nav.hdg_mag

        if hdg is not None:
            diff = ((hdg - self._smooth + 180) % 360) - 180
            self._smooth = (self._smooth + diff * config.HEADING_SMOOTHING) % 360
            self.compass.set_heading(self._smooth)

        self.compass.set_attitude(
            self._nav.pitch or 0.0,
            self._nav.roll  or 0.0,
        )
        self.panel.update_data(self._nav)

    # ── Serial ───────────────────────────────────────────────────────────────

    def _start_serial(self):
        for cfg in config.SERIAL_PORTS:
            r = SerialReader(cfg['port'], cfg['baud'], self)
            r.sentence.connect(self._on_sentence)
            r.start()
            self._readers.append(r)

    def _on_sentence(self, line: str):
        parse(line, self._nav)

    # ── Night mode ───────────────────────────────────────────────────────────

    def _on_hdg_mode(self, mode: str):
        self._hdg_mode = mode
        self.compass.set_hdg_mode(mode)

    def _on_night(self, on: bool):
        self._night = on
        self.compass.set_night(on)
        bg = S.N_BG.name() if on else S.BG.name()
        self.centralWidget().setStyleSheet(f'background: {bg};')

    # ── Port dialog ──────────────────────────────────────────────────────────

    def _show_port_dialog(self):
        dlg = PortDialog(self)
        if dlg.exec_() == QDialog.Accepted:
            port, baud = dlg.selected()
            if port:
                self._stop_serial()
                config.SERIAL_PORTS = [{'port': port, 'baud': baud, 'name': 'Selected'}]
                self._start_serial()

    def _stop_serial(self):
        for r in self._readers:
            r.stop()
        self._readers.clear()

    # ── Keyboard shortcuts ───────────────────────────────────────────────────

    def keyPressEvent(self, event):
        if event.key() == Qt.Key_Escape:
            self.close()
        elif event.key() == Qt.Key_F:
            if self.isFullScreen():
                self.showNormal()
            else:
                self.showFullScreen()

    def closeEvent(self, event):
        self._stop_serial()
        super().closeEvent(event)


class PortDialog(QDialog):
    def __init__(self, parent=None):
        super().__init__(parent)
        self.setWindowTitle('Select Serial Port')
        self.setMinimumSize(400, 300)
        self.setStyleSheet(f"""
            QDialog   {{ background: {S.PANEL_BG.name()}; color: {S.WHITE.name()}; }}
            QListWidget {{ background: {S.BEZEL_DARK.name()}; color: {S.WHITE.name()};
                          border: 1px solid {S.GOLD_DIM.name()}; font-size: 14px; }}
            QListWidget::item:selected {{ background: {S.GOLD_DIM.name()}; }}
            QPushButton {{ background: {S.BEZEL_MID.name()}; color: {S.GOLD.name()};
                           border: 1px solid {S.GOLD.name()}; padding: 8px; border-radius: 4px; }}
        """)

        vl = QVBoxLayout(self)
        vl.addWidget(QLabel('Available serial ports:'))

        self._list = QListWidget()
        for p in SerialReader.available_ports():
            self._list.addItem(p)
        vl.addWidget(self._list)

        hl = QHBoxLayout()
        ok  = QPushButton('Connect 4800 baud')
        ok38 = QPushButton('Connect 38400 baud')
        cancel = QPushButton('Cancel')
        ok.clicked.connect(lambda: self._accept(4800))
        ok38.clicked.connect(lambda: self._accept(38400))
        cancel.clicked.connect(self.reject)
        hl.addWidget(ok)
        hl.addWidget(ok38)
        hl.addWidget(cancel)
        vl.addLayout(hl)

        self._port = None
        self._baud = 4800

    def _accept(self, baud):
        items = self._list.selectedItems()
        if items:
            self._port = items[0].text()
            self._baud = baud
            self.accept()

    def selected(self):
        return self._port, self._baud
