# radar_data_reader/core/structures/ge_header_structures.py

"""
Contains all ctypes structure definitions related to the GeHeader,
which is the main header found within DSPHDRIN blocks.
"""

import ctypes
from dataclasses import dataclass

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

# ==================================================================================================
# --- GeHeader Sub-Structures ---
# ==================================================================================================


class HeaderInfo(CtypesStructureBase):
    _fields_ = [
        ("marker_dati_1", ctypes.c_uint),
        ("marker_dati_2", ctypes.c_uint),
        ("header_marker", ctypes.c_uint),
        ("rev_id", ctypes.c_uint),
        ("header_dim", ctypes.c_uint),
        ("vuoto", ctypes.c_uint * 10),
    ]


class PacketDescriptor(CtypesStructureBase):
    _fields_ = [
        ("npri", ctypes.c_uint),
        ("nrbin", ctypes.c_uint),
        ("num_of_channels", ctypes.c_uint),
        ("block_dimension", ctypes.c_uint),
        ("signal_ordering", ctypes.c_uint),
    ]


class SignalDescriptor(CtypesStructureBase):
    _fields_ = [
        ("batch_counter", ctypes.c_uint),
        ("ttag", ctypes.c_uint),
        ("packet_descr", PacketDescriptor),
        ("packet_length", ctypes.c_uint),
        ("number_of_packet_signal", ctypes.c_uint),
    ]


class ModeDescriptor(CtypesStructureBase):
    _fields_ = [
        ("master_mode", ctypes.c_int),
        ("operation_mode", ctypes.c_int),
        ("standby", c_boolean),
        ("radiate", c_boolean),
        ("waveform", ctypes.c_int),
        ("range_scale", ctypes.c_int),
        ("scan_rate", ctypes.c_int),
        ("dsp_mode_qualifier", ctypes.c_int),
        ("vuoto", ctypes.c_uint * 8),
    ]


class ExpSettings(CtypesStructureBase):
    _fields_ = [
        ("exp_mof", ctypes.c_uint),
        ("phase_rst_code", ctypes.c_uint),
        ("pulse_id", ctypes.c_uint),
        ("exp_f_base", ctypes.c_uint),
        ("exp_f_delta", ctypes.c_uint),
        ("pulse_len", ctypes.c_uint),
        ("amp_peak", ctypes.c_uint),
        ("pulse_id_2", ctypes.c_uint),
        ("exp_f_base_2", ctypes.c_uint),
        ("exp_f_delta_2", ctypes.c_uint),
        ("pulse_len_2", ctypes.c_uint),
        ("amp_peak_2", ctypes.c_uint),
    ]


class DetSettings(CtypesStructureBase):
    _fields_ = [
        ("det_mof", ctypes.c_uint),
        ("lpf7_filter_id", ctypes.c_uint),
        ("lpf8_filter_id", ctypes.c_uint),
        ("det_f_base", ctypes.c_uint),
        ("det_f_delta", ctypes.c_uint),
        ("ph_vector", ctypes.c_uint),
        ("pc_lsn_start", ctypes.c_uint),
        ("pc_lsn_len", ctypes.c_uint),
    ]


class PcSettings(CtypesStructureBase):
    _fields_ = [
        ("pc_mof", ctypes.c_uint),
        ("filt_id", ctypes.c_uint),
        ("pc_lsn_start", ctypes.c_uint),
        ("pc_lsn_len", ctypes.c_uint),
        ("pc_out_offset", ctypes.c_uint),
    ]


class AgcSettings(CtypesStructureBase):
    _fields_ = [
        ("n_rbin", ctypes.c_uint),
        ("n_rbin_1", ctypes.c_uint),
        ("mgc", ctypes.c_float),
        ("tgt_rgate", ctypes.c_float),
        ("unamb_tgt_range", ctypes.c_uint),
        ("init_rgate", ctypes.c_uint),
        ("app_wind_len", ctypes.c_uint),
        ("inu_valid", ctypes.c_uint),
        ("vmbc_inu", ctypes.c_float),
        ("vmbc_inu_der", ctypes.c_float),
        ("dsp_est_batch", ctypes.c_uint),
        ("dsp_att_k", ctypes.c_float),
        ("att_dt_sec", ctypes.c_float),
        ("stc_attenuation_db", ctypes.c_float),
    ]


class SpSettings(CtypesStructureBase):
    _fields_ = [
        ("exp_settings", ExpSettings),
        ("det_settings", DetSettings),
        ("pc_settings", PcSettings),
        ("agc_settings", AgcSettings),
    ]


class MissionTime(CtypesStructureBase):
    _fields_ = [
        ("utc_time_1", ctypes.c_uint),
        ("utc_time_2", ctypes.c_uint),
        ("utc_time_3", ctypes.c_uint),
        ("utc_time_4", ctypes.c_uint),
        ("timetag", c_timetag_t),
    ]


class NavAttitude(CtypesStructureBase):
    _fields_ = [
        ("true_heading_rad", c_radians_t),
        ("pitch_rad", c_radians_t),
        ("roll_rad", c_radians_t),
        ("platform_azimuth_rad", c_radians_t),
        ("magnetic_heading_rad", c_radians_t),
    ]


class NavAttitudeRate(CtypesStructureBase):
    _fields_ = [
        ("heading_rad_sec", c_radians_t),
        ("pitch_rad_sec", c_radians_t),
        ("roll_rad_sec", c_radians_t),
    ]


class NavGeoPos(CtypesStructureBase):
    _fields_ = [
        ("lat_rad", c_radians_t),
        ("lon_rad", c_radians_t),
        ("altitude_m", c_metres_t),
    ]


class NavSpeed(CtypesStructureBase):
    _fields_ = [
        ("north_m_s", c_metres_per_sec_t),
        ("east_m_s", c_metres_per_sec_t),
        ("down_m_s", c_metres_per_sec_t),
        ("vx_ground", ctypes.c_float),
    ]


class NavAcceleration(CtypesStructureBase):
    _fields_ = [
        ("north_m_s2", ctypes.c_float),
        ("east_m_s2", ctypes.c_float),
        ("down_m_s2", ctypes.c_float),
    ]


class Navigation(CtypesStructureBase):
    _fields_ = [
        ("time_tag", ctypes.c_uint),
        ("attitude", NavAttitude),
        ("attitude_rate", NavAttitudeRate),
        ("geo_pos", NavGeoPos),
        ("speed", NavSpeed),
        ("acceleration", NavAcceleration),
    ]


class AntPos(CtypesStructureBase):
    _fields_ = [
        ("ant_ttag", ctypes.c_uint),
        ("nav_az_rad", c_radians_t),
        ("nav_el_rad", c_radians_t),
        ("body_az_rad", c_radians_t),
        ("body_el_rad", c_radians_t),
        ("antenna_az_rad", ctypes.c_uint),
        ("antenna_el_rad", ctypes.c_uint),
        ("utx_rad", c_radians_t),
        ("vtx_rad", c_radians_t),
        ("urx_rad", c_radians_t),
        ("vrx_rad", c_radians_t),
        ("uguard_rx_rad", c_radians_t),
        ("vguard_rx_rad", c_radians_t),
        ("vuoto", ctypes.c_uint * 4),
    ]


class AntEvent(CtypesStructureBase):
    _fields_ = [
        ("frame_in_progress", ctypes.c_int),
        ("bar_in_progress", ctypes.c_int),
        ("number_of_bars", ctypes.c_int),
        ("current_bar_number", ctypes.c_int),
        ("vuoto", ctypes.c_uint * 4),
    ]


class Antenna(CtypesStructureBase):
    _fields_ = [("position", AntPos), ("event", AntEvent)]


class WaveformDescriptor(CtypesStructureBase):
    _fields_ = [("validity", ctypes.c_int), ("vuoto", ctypes.c_uint * 8)]


class GeneralSettings(CtypesStructureBase):
    _fields_ = [
        ("mission_time", MissionTime),
        ("navigation", Navigation),
        ("antenna", Antenna),
        ("waveform_descriptor", WaveformDescriptor),
    ]


class FunctionSettings(CtypesStructureBase):
    _fields_ = []


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


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

    _fields_ = [
        ("header_info", HeaderInfo),
        ("signal_descr", SignalDescriptor),
        ("mode", ModeDescriptor),
        ("sp_settings", SpSettings),
        ("general_settings", GeneralSettings),
        ("function_settings", FunctionSettings),
    ]


@dataclass
class DspHeaderIn(BaseBlock):
    """Dataclass wrapper for a parsed DSPHDRIN block."""

    ge_header: GeHeader
