# 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_ = [
        ("header_marker", ctypes.c_uint),
        ("rev_id", ctypes.c_uint),
        ("header_dim", ctypes.c_uint),
    ]


class SimInfo(CtypesStructureBase):
    _fields_ = [
        ("validity", ctypes.c_int),
        ("sigremap", ctypes.c_uint),
        ("batch_types", ctypes.c_uint),
        ("signal_destination", ctypes.c_uint),
        ("data", ctypes.c_uint * 6),
    ]


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


class SignalDescriptor(CtypesStructureBase):
    _fields_ = [
        ("bacth_counter", ctypes.c_uint),
        ("ttag", c_timetag_t),
        ("packet_descr", PacketDescriptor),
        ("packet_len", ctypes.c_uint),
        ("num_of_packets", 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_uint),
        ("phase", ctypes.c_int),
        ("sub_phase", ctypes.c_int),
        ("result_id", ctypes.c_int),
        ("tgt_unique_id", ctypes.c_int),
        ("expected_batch_length", c_timetag_t),
        ("spare_", ctypes.c_uint * 3),
    ]


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", c_timetag_t),
        ("attitude", NavAttitude),
        ("attitude_rate", NavAttitudeRate),
        ("geo_pos", NavGeoPos),
        ("speed", NavSpeed),
        ("acceleration", NavAcceleration),
    ]


class AntPos(CtypesStructureBase):
    _fields_ = [
        ("ant_ttag", c_timetag_t),
        ("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", c_radians_t),
        ("antenna_el_rad", c_radians_t),
        ("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),
        ("spare", ctypes.c_uint * 4),
    ]


class AntEvent(CtypesStructureBase):
    _fields_ = [
        ("frame_in_progress", c_boolean),
        ("bar_in_progress", c_boolean),
        ("number_of_bars", ctypes.c_uint),
        ("current_bar_number", ctypes.c_uint),
        ("bar_direction", ctypes.c_int),
        ("mode", ctypes.c_uint),
        ("spare_", ctypes.c_uint * 2),
    ]


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


class WaveformDescriptor(CtypesStructureBase):
    _fields_ = [
        ("validity", ctypes.c_int),
        ("wfcode", ctypes.c_uint),
        ("spare_", ctypes.c_int * 7),
    ]


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


class NciSettings(CtypesStructureBase):
    _fields_ = [
        ("n_rbin", ctypes.c_uint),
        ("n_pulses", ctypes.c_uint),
        ("time_tag", c_timetag_t),
        ("conv_fact", ctypes.c_float),
    ]

class MtifftSettings(CtypesStructureBase):
    _fields_ = [
        ("timetag", c_timetag_t),
        ("nrbin", ctypes.c_uint),
        ("npulses", ctypes.c_uint),
        ("nint", ctypes.c_uint),
        ("nclutter_reg", ctypes.c_uint),
        ("prt", ctypes.c_uint),
        ("mti_filt_id", ctypes.c_uint),
        ("fft_window_id", ctypes.c_uint),
        ("conv_scale_factor", ctypes.c_float),
    ]

class CfarSampleSupport(CtypesStructureBase):
    _fields_ = [
        ("cfar_geometry_id", ctypes.c_uint),
        ("cfar_rng_dim", ctypes.c_uint),
        ("cfar_rng_guard", ctypes.c_uint),
        ("cfar_dop_dim", ctypes.c_uint),
        ("cfar_dop_guard", ctypes.c_uint),
        ("gradient", ctypes.c_uint),
        ("cfar_ring", ctypes.c_uint),
    ]

class CfarSensing(CtypesStructureBase):
    _fields_ = [
        ("min_rbin", ctypes.c_uint),
        ("max_rbin", ctypes.c_uint),
        ("min_filt", ctypes.c_uint),
        ("max_filt", ctypes.c_uint),
    ]

class Collapsing(CtypesStructureBase):
    _fields_ = [
        ("max_coll_det", ctypes.c_float),
        ("coll_max_rng", ctypes.c_uint),
        ("coll_max_dop", ctypes.c_uint),
    ]

class CfarSettings(CtypesStructureBase):
    _fields_ = [
        ("n_rbin", ctypes.c_uint),
        ("n_fft", ctypes.c_uint),
        ("start_filt", ctypes.c_uint),
        ("stop_filt", ctypes.c_uint),
        ("doppler_notch", ctypes.c_float),
        ("cfar_scheme", ctypes.c_uint),
        ("rbin_block_dim", ctypes.c_uint),
        ("sample_support", CfarSampleSupport),
        ("pfa", ctypes.c_uint),
        ("rs_index", ctypes.c_uint),
        ("cfar_sensing", CfarSensing),
        ("num_sat", ctypes.c_uint),
        ("sat_vector", ctypes.c_uint),
        ("batch_id", ctypes.c_uint),
        ("antenna_az_ned", ctypes.c_float),
        ("collapsing", Collapsing),
        ("noise_level", ctypes.c_float),
        ("guard_switch_flag", ctypes.c_float),
        ("cfar_2d_thr_ovr", ctypes.c_float),
        ("grifo_gain", ctypes.c_float),
        ("grifo_gain_delta", ctypes.c_float),
    ]

class ArfOverflown(CtypesStructureBase):
    _fields_ = [
        ("ovf_start_rbin", ctypes.c_uint),
        ("ovf_stop_rbin", ctypes.c_uint),
        ("ovf_start_filt", ctypes.c_uint),
        ("ovf_stop_filt", ctypes.c_uint),
    ]

class ArfTxLeakage(CtypesStructureBase):
    _fields_ = [
        ("txl_start_rbin", ctypes.c_uint),
        ("txl_stop_rbin", ctypes.c_uint),
        ("txl_window_filt", ctypes.c_uint),
        ("txl_freq_filt", ctypes.c_uint),
        ("txl_th_amp", ctypes.c_float),
    ]

class ArfFftSl(CtypesStructureBase):
    _fields_ = [
        ("fft_sl_window_rbin", ctypes.c_uint),
        ("mult_alm_num", ctypes.c_uint),
        ("mult_alm_db_margin", ctypes.c_float),
    ]

class ArfDpcSl(CtypesStructureBase):
    _fields_ = [
        ("ext_pulse_length", ctypes.c_uint),
        ("dpc_sl_window_filt", ctypes.c_uint),
        ("dpc_sl_margin_db", ctypes.c_float),
    ]

class ArfAle(CtypesStructureBase):
    _fields_ = [
        ("ale_start_rbin", ctypes.c_uint),
        ("ale_stop_rbin", ctypes.c_uint),
        ("ale_freq_filt", ctypes.c_uint),
        ("ale_window_filt", ctypes.c_uint),
    ]

class ArfJem(CtypesStructureBase):
    _fields_ = [
        ("jem_window_rbin", ctypes.c_uint),
    ]

class ArfDemZone(CtypesStructureBase):
    _fields_ = [
        ("n_range_zone", ctypes.c_uint),
    ]

class ArfSlb(CtypesStructureBase):
    _fields_ = [
        ("current_cagc_att", ctypes.c_float),
        ("slb_m", ctypes.c_float),
    ]

class ArfSettings(CtypesStructureBase):
    _fields_ = [
        ("n_rbin", ctypes.c_uint),
        ("n_fft", ctypes.c_uint),
        ("ovf", ArfOverflown),
        ("tx_leak", ArfTxLeakage),
        ("fft_sl", ArfFftSl),
        ("dpc_sl", ArfDpcSl),
        ("ale", ArfAle),
        ("jem", ArfJem),
        ("demz", ArfDemZone),
        ("slb", ArfSlb),
    ]

class AufSettings(CtypesStructureBase):
    _fields_ = [
        ("n_rbin", ctypes.c_uint),
        ("n_fft", ctypes.c_uint),
        ("filter_flag", ctypes.c_uint),
        ("prf_set_idx", ctypes.c_uint),
        ("prf_elem_idx", ctypes.c_uint),
        ("skip_proc_flag", ctypes.c_uint),
        ("cll_filter_shift", ctypes.c_uint),
        ("theta_point", ctypes.c_float),
    ]

class DbsPeSettings(CtypesStructureBase):
    _fields_ = [
        ("dbs_flush_flag", c_boolean),
        ("int_rbin_offset", ctypes.c_uint),
        ("skip_processing", c_boolean),
        ("spare", ctypes.c_uint * 8),
    ]

class GadsSettings(CtypesStructureBase):
    _fields_ = [
        ("n_rbin", ctypes.c_uint),
        ("n_fft", ctypes.c_uint),
        ("cfar_start_filt", ctypes.c_uint),
        ("cfar_stop_filt", ctypes.c_uint),
        ("doppler_notch", ctypes.c_uint),
        ("skip_proc_flag", ctypes.c_uint),
    ]

class ScSettings(CtypesStructureBase):
    _fields_ = [
        ("ant_nav_direction", ctypes.c_int),
        ("ant_current_bar_number", ctypes.c_uint),
        ("ant_nav_scan_center", ctypes.c_float),
        ("ant_nav_left_scan_limit", ctypes.c_float),
        ("ant_nav_right_scan_limit", ctypes.c_float),
        ("rbm_white_level", ctypes.c_float),
        ("map_comp_vx", ctypes.c_float),
        ("map_comp_vy", ctypes.c_float),
        ("spare", ctypes.c_uint * 8),
    ]

class SlbSettings(CtypesStructureBase):
    _fields_ = [
        ("timetag", c_timetag_t),
        ("slobe_blanking", ctypes.c_float),
        ("slbc", ctypes.c_float),
        ("nrbin", ctypes.c_uint),
        ("nfft", ctypes.c_uint),
        ("grifo_gain", ctypes.c_float),
        ("max_coll_det", ctypes.c_uint),
        ("coll_max_rng", ctypes.c_uint),
        ("coll_max_dop", ctypes.c_uint),
        ("cfar_start_filt", ctypes.c_uint),
        ("doppler_notch", ctypes.c_float),
        ("prt", ctypes.c_float),
    ]

class SpsSettings(CtypesStructureBase):
    _fields_ = [
        ("n_rbin", ctypes.c_uint),
        ("n_fft", ctypes.c_uint),
        ("skip_proc_flag", ctypes.c_uint),
    ]

class PeSettings(CtypesStructureBase):
    _fields_ = [
        ("time_tag", c_timetag_t),
        ("n_rbin", ctypes.c_uint),
        ("lrb", ctypes.c_float),
        ("prt", ctypes.c_float),
        ("mlc_freq", ctypes.c_float),
        ("close_plot_flag", c_boolean),
        ("tx_chan", ctypes.c_uint),
        ("ant_az", ctypes.c_float),
        ("ant_el", ctypes.c_float),
        ("nav_az", ctypes.c_float),
        ("nav_el", ctypes.c_float),
        ("yaw", ctypes.c_float),
        ("pitch", ctypes.c_float),
        ("roll", ctypes.c_float),
        ("plat_az", ctypes.c_float),
        ("pp_coast_flag", c_boolean),
        ("pp_mprf_lookup", c_boolean),
        ("stt_rb_start", ctypes.c_uint),
        ("stt_rb_stop", ctypes.c_uint),
        ("stt_fil_start", ctypes.c_uint),
        ("stt_fil_stop", ctypes.c_uint),
        ("unamb_tgt_range", ctypes.c_float),
        ("unamb_tgt_doppler", ctypes.c_float),
        ("fm_slope", ctypes.c_float),
        ("rb_start", ctypes.c_uint),
        ("rb_stop", ctypes.c_uint),
        ("fil_start", ctypes.c_uint),
        ("fil_stop", ctypes.c_uint),
        ("sdr_before_coast", ctypes.c_float),
        ("prf_set", ctypes.c_int),
        ("prf_number", ctypes.c_int),
        ("mtg", ctypes.c_float),
        ("spur_num", ctypes.c_int),
        ("delsign", ctypes.c_int),
        ("jam_thresh", ctypes.c_float),
        ("cut_off_vel", ctypes.c_float),
        ("batch_end", ctypes.c_int),
        ("spur_freq", ctypes.c_float),
        ("filtered_err_vel_clutt", ctypes.c_float),
        ("flw_range_start", ctypes.c_uint),
        ("flw_range_stop", ctypes.c_uint),
        ("flw_doppler_start", ctypes.c_uint),
        ("flw_doppler_stop", ctypes.c_uint),
        ("desensitisation", ctypes.c_int),
        ("batch_azim_angle", ctypes.c_float),
        ("batch_count", ctypes.c_uint),
        ("batch_dur", c_timetag_t),
        ("agr_window_center", ctypes.c_float),
        ("agr_window_length", ctypes.c_float),
        ("ngt_enable", c_boolean),
        ("mti_code", ctypes.c_int),
        ("mbc_dop_index", ctypes.c_int),
        ("stt_transition_status", ctypes.c_int),
        ("tracked_tgt_amplitude", ctypes.c_float),
        ("ale_blanking_enable", c_boolean),
        ("ale_range_estimate", ctypes.c_float),
        ("ale_blk_start", ctypes.c_uint),
        ("ale_blk_stop", ctypes.c_uint),
        ("ale_trk_start", ctypes.c_uint),
        ("ale_trk_stop", ctypes.c_uint),
        ("baro_alt", ctypes.c_float),
        ("baro_alt_validity", c_boolean),
        ("z_velocity", ctypes.c_float),
        ("agc_gain", ctypes.c_float),
        ("mgc", ctypes.c_int),
        ("expand", c_boolean),
        ("tx_chan_mhz", ctypes.c_float),
        ("lrb_meters", ctypes.c_float),
        ("v_los", ctypes.c_float),
        ("unamb_range_start", ctypes.c_float),
        ("unamb_range_stop", ctypes.c_float),
        ("nearest_range", ctypes.c_float),
        ("deramp_dly_us", ctypes.c_float),
        ("lsn_dly_us", ctypes.c_float),
        ("lsn_len_us", ctypes.c_float),
        ("tgt_band", ctypes.c_float),
        ("clutter_band", ctypes.c_float),
        ("tgt_altitude", ctypes.c_float),
        ("tgt_longitude", ctypes.c_float),
        ("tgt_latitude", ctypes.c_float),
        ("spare_", ctypes.c_uint * 4),
    ]

class FunctionSettings(CtypesStructureBase):
    _fields_ = [
        ("nci_settings", NciSettings),
        ("mtifft_settings", MtifftSettings),
        ("cfar_settings", CfarSettings),
        ("arf_settings", ArfSettings),
        ("slb_settings", SlbSettings),
        ("pe_settings", PeSettings),
        ("sc_settings", ScSettings),
        ("dbs_pe_settings", DbsPeSettings),
        ("auf_settings", AufSettings),
        ("sps_settings", SpsSettings),
        ("gads_settings", GadsSettings),
    ]


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


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

    _fields_ = [
        ("header_info", HeaderInfo),
        ("sim_info", SimInfo),
        ("signal", 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