# radar_data_reader/core/structures/cdpsts_structures.py

"""
Contains all ctypes structure definitions related to the CDPSTS block,
which holds common data processor status and target detection results.
"""

import ctypes
from dataclasses import dataclass
from typing import Optional

from .base_structures import (
    CtypesStructureBase,
    BaseBlock,
    c_boolean,
    c_radians_t,
    c_metres_t,
    c_timetag_t,
)

# ==================================================================================================
# --- CDPSTS Sub-Structures ---
# ==================================================================================================


class SharedMemoryHeader(CtypesStructureBase):
    _fields_ = [
        ("marker_low", ctypes.c_uint32),
        ("marker_high", ctypes.c_uint32),
        ("type", ctypes.c_uint32),
        ("ftm_and_version", ctypes.c_uint32),
        ("counter", ctypes.c_uint32),
        ("size", ctypes.c_uint32),
        ("spare", ctypes.c_uint32 * 2),
    ]


class BaseTimetag(CtypesStructureBase):
    _fields_ = [("batch_id", ctypes.c_uint32), ("time", ctypes.c_uint32)]


class ModeStatus(CtypesStructureBase):
    _fields_ = [
        ("mode", ctypes.c_int),
        ("sub_mode", ctypes.c_int),
        ("range_scale", ctypes.c_int),
        ("stby", c_boolean),
        ("radiate", c_boolean),
        ("freeze", c_boolean),
        ("expand", c_boolean),
        ("waveform", ctypes.c_int),
        ("health_status", ctypes.c_uint),
        ("antenna_state", ctypes.c_uint),
        ("op_state", ctypes.c_uint32),
        ("wow", c_boolean),
        ("ant_radiate", c_boolean),
        ("aesa_quick_status", ctypes.c_uint32),
        ("ms_spare_", ctypes.c_uint32 * 1),
    ]


class AntennaPosition(CtypesStructureBase):
    _fields_ = [("azimuth", c_radians_t), ("elevation", c_radians_t)]


class AntennaFeedback(CtypesStructureBase):
    _fields_ = [
        ("nav_pos", AntennaPosition),
        ("body_pos", AntennaPosition),
        ("bar_in_progress", c_boolean),
        ("frame_in_progress", c_boolean),
        ("direction", ctypes.c_int),
        ("op_mode", ctypes.c_int),
        ("bar_number", ctypes.c_int),
        ("cone_turn_number", ctypes.c_int),
        ("frame_center", ctypes.c_float),
        ("scan_center", ctypes.c_float),
        ("off_limits", c_boolean),
        ("loop_fail", c_boolean),
        ("bar_distance", c_radians_t),
        ("dbs_start_az", c_radians_t),
        ("dbs_end_az", c_radians_t),
        ("dbs_vel", c_radians_t),
        ("db1", ctypes.c_float),
        ("db2", ctypes.c_float),
    ]


class DetectedTarget(CtypesStructureBase):
    MAX_NO_OF_TGT_DETECTIONS = 8
    _fields_ = [
        ("detection_valid", c_boolean),
        ("detected_tgt", ctypes.c_byte * 48),
        ("associated_azimuth", c_radians_t),
        ("associated_elevation", c_radians_t),
        ("associated_altitude", c_metres_t),
        ("associated_bar_number", ctypes.c_uint),
        ("id", ctypes.c_int),
        ("flags", ctypes.c_uint),
        ("track_association", ctypes.c_int),
        ("track_association_value", ctypes.c_float),
    ]


class GenericDetections(CtypesStructureBase):
    _fields_ = [
        ("processed_prt", ctypes.c_uint),
        ("processed_mlc_freq", ctypes.c_float),
        ("processed_tx_freq", ctypes.c_int),
        ("pp_waveform_tellback", ctypes.c_int),
        ("pp_range_scale_tellback", ctypes.c_int),
        ("pp_scan_rate_tellback", ctypes.c_int),
        ("processed_pck_timetag", c_timetag_t),
        ("processed_nfft_total", ctypes.c_uint),
        ("code_length", ctypes.c_uint),
        ("detected_in_lookup", c_boolean),
        ("num_of_detected_tgts", ctypes.c_uint),
        ("target_detections", DetectedTarget * DetectedTarget.MAX_NO_OF_TGT_DETECTIONS),
    ]


class ChunkHeader(CtypesStructureBase):
    _fields_ = [("raw_data", ctypes.c_byte * 16)]


class IdentifierChunk(CtypesStructureBase):
    _fields_ = [("raw_data", ctypes.c_byte * 24)]


def create_chunk_type(data_type):
    """Factory function to create a generic Chunk ctypes.Structure."""

    class Chunk(CtypesStructureBase):
        _fields_ = [("header", ChunkHeader), ("data", data_type)]

    return Chunk


TimetagChunk = create_chunk_type(BaseTimetag)
StatusChunk = create_chunk_type(ModeStatus)
AntennaStatusChunk = create_chunk_type(AntennaFeedback)
DetectionsChunk = create_chunk_type(GenericDetections)


class CdpDataLayout(CtypesStructureBase):
    _fields_ = [
        ("struct_identifier_chunk", IdentifierChunk),
        ("timetag_chunk", TimetagChunk),
        ("timetag_sync_chunk", TimetagChunk),
        ("status_chunk", StatusChunk),
        ("antenna_status_chunk", AntennaStatusChunk),
        ("detections_chunk", DetectionsChunk),
    ]


# ==================================================================================================
# --- Top-Level CDPSTS Structure and Dataclass Wrapper ---
# ==================================================================================================


class CdpStsPayload(CtypesStructureBase):
    """The complete CdpStsPayload ctypes structure."""

    _fields_ = [("mem_header", SharedMemoryHeader), ("data", CdpDataLayout)]


@dataclass
class CdpStsBlock(BaseBlock):
    """Dataclass wrapper for a parsed CDPSTS block."""

    is_valid: bool
    payload: Optional[CdpStsPayload] = None
