"""
VehicleView - Pure State Container
純粹的狀態容器，不主動通訊、不背景下載參數、不搶 RF/MAVLink 流量
只提供狀態存取介面，由外部手動餵資料（push state）
"""

import os
from typing import Dict, Optional, Any
from dataclasses import dataclass, field
from enum import Enum

from .utils import setup_logger

logger = setup_logger(os.path.basename(__file__))


# ====================== Enums =====================

class ConnectionType(Enum):
    """連接類型"""
    SERIAL = "serial"
    UDP = "udp"
    TCP = "tcp"
    OTHER = "other"


class ComponentType(Enum):
    """組件類型"""
    AUTOPILOT = "autopilot"
    GCS = "gcs"
    CAMERA = "camera"
    GIMBAL = "gimbal"
    OTHER = "other"


class RFModuleType(Enum):
    """RF模組類型"""
    XBEE = "xbee"
    UDP = "udp"
    TCP = "tcp"
    OTHER = "other"


# ====================== Data Classes =====================

@dataclass
class Position:
    """位置資訊"""
    latitude: Optional[float] = None  # 緯度 (度)
    longitude: Optional[float] = None  # 經度 (度)
    altitude: Optional[float] = None  # 海拔高度 (公尺)
    relative_altitude: Optional[float] = None  # 相對高度 (公尺)
    timestamp: Optional[float] = None  # 時間戳記


@dataclass
class Attitude:
    """姿態資訊"""
    roll: Optional[float] = None  # 橫滾角 (弧度)
    pitch: Optional[float] = None  # 俯仰角 (弧度)
    yaw: Optional[float] = None  # 偏航角 (弧度)
    rollspeed: Optional[float] = None  # 橫滾速度 (弧度/秒)
    pitchspeed: Optional[float] = None  # 俯仰速度 (弧度/秒)
    yawspeed: Optional[float] = None  # 偏航速度 (弧度/秒)
    timestamp: Optional[float] = None  # 時間戳記


@dataclass
class FlightMode:
    """飛行模式資訊"""
    base_mode: Optional[int] = None  # MAVLink base mode
    custom_mode: Optional[int] = None  # 自定義模式
    mode_name: Optional[str] = None  # 模式名稱 (例如: "GUIDED", "AUTO")
    timestamp: Optional[float] = None  # 時間戳記


@dataclass
class Battery:
    """電池資訊"""
    voltage: Optional[float] = None  # 電壓 (V)
    current: Optional[float] = None  # 電流 (A)
    remaining: Optional[int] = None  # 剩餘電量 (%)
    temperature: Optional[float] = None  # 溫度 (攝氏)
    timestamp: Optional[float] = None  # 時間戳記


@dataclass
class EKF:
    """EKF狀態資訊"""
    flags: Optional[int] = None  # EKF 旗標
    velocity_variance: Optional[float] = None  # 速度變異
    pos_horiz_variance: Optional[float] = None  # 水平位置變異
    pos_vert_variance: Optional[float] = None  # 垂直位置變異
    compass_variance: Optional[float] = None  # 羅盤變異
    terrain_alt_variance: Optional[float] = None  # 地形高度變異
    timestamp: Optional[float] = None  # 時間戳記


@dataclass
class GPS:
    """GPS資訊"""
    fix_type: Optional[int] = None  # GPS fix 類型 (0=無, 1=無fix, 2=2D, 3=3D, 4=DGPS, 5=RTK)
    satellites_visible: Optional[int] = None  # 可見衛星數
    eph: Optional[int] = None  # GPS HDOP 水平精度因子
    epv: Optional[int] = None  # GPS VDOP 垂直精度因子
    timestamp: Optional[float] = None  # 時間戳記


@dataclass
class VFR:
    """VFR HUD資訊"""
    airspeed: Optional[float] = None  # 空速 (m/s)
    groundspeed: Optional[float] = None  # 地速 (m/s)
    heading: Optional[int] = None  # 航向 (度)
    throttle: Optional[int] = None  # 油門 (%)
    climb: Optional[float] = None  # 爬升率 (m/s)
    timestamp: Optional[float] = None  # 時間戳記


@dataclass
class ComponentStatus:
    """組件狀態容器"""
    position: Position = field(default_factory=Position)
    attitude: Attitude = field(default_factory=Attitude)
    mode: FlightMode = field(default_factory=FlightMode)
    battery: Battery = field(default_factory=Battery)
    ekf: EKF = field(default_factory=EKF)
    gps: GPS = field(default_factory=GPS)
    vfr: VFR = field(default_factory=VFR)
    
    # 系統狀態
    system_status: Optional[int] = None  # MAV_STATE
    armed: Optional[bool] = None  # 解鎖狀態
    
    # 其他自定義狀態
    custom_status: Dict[str, Any] = field(default_factory=dict)


@dataclass
class PacketStats:
    """封包統計資訊"""
    received_count: int = 0  # 接收封包數
    lost_count: int = 0  # 遺失封包數
    last_seq: Optional[int] = None  # 最後序號
    last_msg_time: Optional[float] = None  # 最後訊息時間
    msg_type_count: Dict[int, int] = field(default_factory=dict)  # 各類訊息計數 {msg_type: count}


@dataclass
class RFStatus:
    """RF模組狀態"""
    rssi: Optional[int] = None  # 信號強度
    noise: Optional[int] = None  # 噪音水平
    at_response: Optional[str] = None  # AT 命令回應
    link_quality: Optional[int] = None  # 連接品質
    timestamp: Optional[float] = None  # 時間戳記
    custom_status: Dict[str, Any] = field(default_factory=dict)  # 其他自定義狀態


@dataclass
class SocketInfo:
    """Socket連接資訊"""
    ip: Optional[str] = None  # IP位址
    port: Optional[int] = None  # 埠號
    local_ip: Optional[str] = None  # 本地IP
    local_port: Optional[int] = None  # 本地埠號
    connected: bool = False  # 連接狀態


# ====================== Component Class =====================

class VehicleComponent:
    """載具組件 - 代表一個 MAVLink component"""
    
    def __init__(self, component_id: int, comp_type: ComponentType = ComponentType.OTHER):
        self.component_id = component_id
        self.type = comp_type
        
        # MAVLink 組件資訊
        self.mav_type: Optional[int] = None  # MAV_TYPE
        self.mav_autopilot: Optional[int] = None  # MAV_AUTOPILOT
        
        # 狀態容器
        self.status = ComponentStatus()
        
        # 參數容器 (只存放，不主動下載)
        self.parameters: Dict[str, Any] = {}
        
        # 封包統計
        self.packet_stats = PacketStats()
    
    def update_packet_stats(self, seq: int, msg_type: int, timestamp: float) -> None:
        """
        更新封包統計
        
        Args:
            seq: 訊息序號
            msg_type: 訊息類型
            timestamp: 時間戳記
        """
        stats = self.packet_stats
        
        # 檢查遺失封包
        if stats.last_seq is not None:
            expected_seq = (stats.last_seq + 1) % 256
            diff = seq - expected_seq
            if diff < 0:
                diff += 256
            stats.lost_count += diff
        
        # 更新統計資訊
        stats.received_count += 1
        stats.last_seq = seq
        stats.last_msg_time = timestamp
        
        # 更新訊息類型計數
        if msg_type in stats.msg_type_count:
            stats.msg_type_count[msg_type] += 1
        else:
            stats.msg_type_count[msg_type] = 1
    
    def reset_packet_stats(self) -> None:
        """重置封包統計"""
        self.packet_stats = PacketStats()

    def set_parameter(self, param_name: str, param_value: Any) -> None:
        """設定參數 (手動餵入)"""
        self.parameters[param_name] = param_value

    def get_parameter(self, param_name: str, default: Any = None) -> Any:
        """取得參數"""
        return self.parameters.get(param_name, default)

    def __str__(self) -> str:
        return (f"Component(id={self.component_id}, type={self.type.value}, "
                f"mav_type={self.mav_type}, received={self.packet_stats.received_count}, "
                f"lost={self.packet_stats.lost_count})")


# ====================== RF Module Class =====================

class RFModule:
    """RF模組資訊容器"""
    
    def __init__(self, rf_type: RFModuleType = RFModuleType.OTHER):
        self.type = rf_type
        self.status = RFStatus()
        self.socket_info = SocketInfo()
    
    def update_rssi(self, rssi: int, timestamp: Optional[float] = None) -> None:
        """更新RSSI"""
        self.status.rssi = rssi
        if timestamp:
            self.status.timestamp = timestamp
    
    def update_at_response(self, response: str, timestamp: Optional[float] = None) -> None:
        """更新AT命令回應"""
        self.status.at_response = response
        if timestamp:
            self.status.timestamp = timestamp
    
    def update_socket_info(self, ip: str = None, port: int = None, 
                          local_ip: str = None, local_port: int = None,
                          connected: bool = None) -> None:
        """更新Socket資訊"""
        if ip is not None:
            self.socket_info.ip = ip
        if port is not None:
            self.socket_info.port = port
        if local_ip is not None:
            self.socket_info.local_ip = local_ip
        if local_port is not None:
            self.socket_info.local_port = local_port
        if connected is not None:
            self.socket_info.connected = connected
    
    def __str__(self) -> str:
        return (f"RFModule(type={self.type.value}, rssi={self.status.rssi}, "
                f"connected={self.socket_info.connected})")


# ====================== Main VehicleView Class =====================

class VehicleView:
    """
    載具視圖 - 純狀態容器
    
    特點:
    1. 只有狀態容器，沒有任何主動通訊功能
    2. 不主動通訊、不背景下載參數、不搶 RF/MAVLink 流量
    3. 可以手動餵資料 (push state)
    4. 可擴充 (支援 RF 模組狀態)
    """
    
    # TODO: connected_via 這個值可能用不到 之後可能要移除 不要用它再加功能了

    def __init__(self, sysid: int):
        # Meta 資訊
        self.sysid = sysid
        self.kind: Optional[str] = None  # 載具種類描述 (例如: "Copter", "Plane")
        self.vehicle_type: Optional[int] = None  # MAV_TYPE
        self.connected_via: ConnectionType = ConnectionType.OTHER
        
        # 組件容器 {component_id: VehicleComponent}
        self.components: Dict[int, VehicleComponent] = {}
        
        # RF模組
        self.rf_module: Optional[RFModule] = None
        
        # 其他自定義meta資訊
        self.custom_meta: Dict[str, Any] = {}
    
    def add_component(self, component_id: int, comp_type: ComponentType = ComponentType.OTHER) -> VehicleComponent:
        """
        新增組件
        
        Args:
            component_id: 組件ID
            comp_type: 組件類型
            
        Returns:
            VehicleComponent: 新增的組件
        """
        if component_id not in self.components:
            self.components[component_id] = VehicleComponent(component_id, comp_type)
            # logger.debug(f"Added component {component_id} to system {self.sysid}")
        return self.components[component_id]
    
    def get_component(self, component_id: int) -> Optional[VehicleComponent]:
        """取得組件"""
        return self.components.get(component_id)
    
    def remove_component(self, component_id: int) -> bool:
        """移除組件"""
        if component_id in self.components:
            del self.components[component_id]
            # logger.debug(f"Removed component {component_id} from system {self.sysid}")
            return True
        return False

    def reset_component_stats(self, component_id: int) -> None:
        """重置指定組件的封包統計"""
        component = self.get_component(component_id)
        if component:
            component.reset_packet_stats()
            # logger.info(f"Reset packet stats for component {component_id} in system {self.sysid}")

    def set_rf_module(self, rf_type: RFModuleType) -> RFModule:
        """設定RF模組"""
        self.rf_module = RFModule(rf_type)
        return self.rf_module
    
    def get_rf_module(self) -> Optional[RFModule]:
        """取得RF模組"""
        return self.rf_module
    
    def __str__(self) -> str:
        comp_list = ", ".join([str(cid) for cid in self.components.keys()])
        return (f"VehicleView(sysid={self.sysid}, kind={self.kind}, "
                f"connected_via={self.connected_via.value}, "
                f"components=[{comp_list}], "
                f"rf_module={self.rf_module is not None})")
    
    def to_dict(self) -> Dict[str, Any]:
        """轉換為字典格式 (方便序列化/除錯)"""
        return {
            'meta': {
                'sysid': self.sysid,
                'kind': self.kind,
                'vehicle_type': self.vehicle_type,
                'connected_via': self.connected_via.value,
                'custom_meta': self.custom_meta
            },
            'components': {
                cid: {
                    'component_id': comp.component_id,
                    'type': comp.type.value,
                    'mav_type': comp.mav_type,
                    'mav_autopilot': comp.mav_autopilot,
                    'packet_stats': {
                        'received': comp.packet_stats.received_count,
                        'lost': comp.packet_stats.lost_count,
                        'last_seq': comp.packet_stats.last_seq,
                        'last_msg_time': comp.packet_stats.last_msg_time
                    },
                    'parameters_count': len(comp.parameters)
                }
                for cid, comp in self.components.items()
            },
            'rf_module': {
                'type': self.rf_module.type.value,
                'rssi': self.rf_module.status.rssi,
                'socket_connected': self.rf_module.socket_info.connected
            } if self.rf_module else None
        }


# ====================== Registry =====================

class VehicleViewRegistry:
    """載具視圖註冊表 - 管理所有的 VehicleView"""
    
    def __init__(self):
        self._vehicles: Dict[int, VehicleView] = {}
    
    def register(self, sysid: int) -> VehicleView:
        """註冊新的載具視圖"""
        if sysid not in self._vehicles:
            self._vehicles[sysid] = VehicleView(sysid)
            logger.info(f"Registered new VehicleView for system {sysid}")
        return self._vehicles[sysid]
    
    def get(self, sysid: int) -> Optional[VehicleView]:
        """取得載具視圖"""
        return self._vehicles.get(sysid)
    
    def unregister(self, sysid: int) -> bool:
        """註銷載具視圖"""
        if sysid in self._vehicles:
            del self._vehicles[sysid]
            logger.info(f"Unregistered VehicleView for system {sysid}")
            return True
        return False
    
    def get_all(self) -> Dict[int, VehicleView]:
        """取得所有載具視圖"""
        return self._vehicles.copy()
    
    def clear(self) -> None:
        """清空所有載具視圖"""
        self._vehicles.clear()
        logger.info("Cleared all VehicleViews")
    
    def __len__(self) -> int:
        return len(self._vehicles)
    
    def __contains__(self, sysid: int) -> bool:
        return sysid in self._vehicles


# ====================== Global Instance =====================

# 全域註冊表實例
vehicle_registry = VehicleViewRegistry()

'''
================= 改版記錄 ============================

2026.01.16
1. 新增 重置指定組件的封包統計 功能

'''

