"""
Signal metadata data structures
"""

from dataclasses import dataclass, field
from typing import Optional, List, Dict
from datetime import datetime


@dataclass
class SignalMetadata:
    """
    Extracted metadata from RF signal capture file
    """
    # File information
    file_type: str  # 'Flipper SubGhz Key File' or 'Flipper SubGhz RAW File'
    version: int
    file_format: str  # 'KEY', 'RAW', 'BinRAW'

    # RF characteristics
    frequency: int  # in Hz
    preset: Optional[str] = None
    modulation: Optional[str] = None  # Extracted from preset

    # Protocol information (for decoded files)
    protocol: Optional[str] = None
    bit_length: Optional[int] = None
    key_data: Optional[bytes] = None
    timing_element: Optional[int] = None  # TE in microseconds

    # RAW signal data
    raw_data: Optional[List[int]] = None  # Timing array

    # BinRAW data
    bin_raw_bit: Optional[int] = None
    bin_raw_te: Optional[int] = None
    bin_raw_data: Optional[bytes] = None

    # Custom preset data
    custom_preset_module: Optional[str] = None
    custom_preset_data: Optional[bytes] = None

    # Computed fields
    duration_ms: Optional[float] = None
    pulse_count: Optional[int] = None
    avg_pulse_width: Optional[float] = None

    # Metadata
    parsed_at: datetime = field(default_factory=datetime.utcnow)
    parse_errors: List[str] = field(default_factory=list)

    def to_dict(self) -> Dict:
        """Convert to dictionary for JSON serialization"""
        return {
            'file_type': self.file_type,
            'version': self.version,
            'file_format': self.file_format,
            'frequency': self.frequency,
            'preset': self.preset,
            'modulation': self.modulation,
            'protocol': self.protocol,
            'bit_length': self.bit_length,
            'key_data': self.key_data.hex() if self.key_data else None,
            'timing_element': self.timing_element,
            'raw_data_length': len(self.raw_data) if self.raw_data else 0,
            'duration_ms': self.duration_ms,
            'pulse_count': self.pulse_count,
            'avg_pulse_width': self.avg_pulse_width,
            'parsed_at': self.parsed_at.isoformat(),
            'parse_errors': self.parse_errors
        }

    @property
    def is_decoded(self) -> bool:
        """Check if signal has been decoded to a protocol"""
        return self.protocol is not None and self.protocol != 'RAW'

    @property
    def has_raw_data(self) -> bool:
        """Check if file contains raw timing data"""
        return self.raw_data is not None and len(self.raw_data) > 0


@dataclass
class PresetInfo:
    """Modulation preset information"""
    name: str
    modulation: str  # 'OOK' or '2FSK'
    bandwidth_khz: float
    deviation_khz: Optional[float] = None  # For FSK

    @staticmethod
    def from_preset_name(name: str) -> 'PresetInfo':
        """Parse preset information from name"""
        presets = {
            'FuriHalSubGhzPresetOok270Async': PresetInfo('OOK270', 'OOK', 270.0),
            'FuriHalSubGhzPresetOok650Async': PresetInfo('OOK650', 'OOK', 650.0),
            'FuriHalSubGhzPreset2FSKDev238Async': PresetInfo('FM238', '2FSK', 270.0, 2.38),
            'FuriHalSubGhzPreset2FSKDev476Async': PresetInfo('FM476', '2FSK', 270.0, 47.6),
            'FuriHalSubGhzPresetCustom': PresetInfo('Custom', 'Custom', 0.0),
        }
        return presets.get(name, PresetInfo('Unknown', 'Unknown', 0.0))
