import ctypes
from Grifo_E_1553lib.data_types.dl_target_validity import DlTargetValidity
from Grifo_E_1553lib.data_types.semicircle import Semicircle
from Grifo_E_1553lib.data_types.target_presentation_data import TargetPresentationData
from Grifo_E_1553lib.data_types.target_half_call_sign import TargetHalfCallSign
from Grifo_E_1553lib.data_types.target_position import TargetPosition

class Msg1DataLinkTarget(ctypes.Structure):
    _fields_ = [
        ("dl_target_validity", DlTargetValidity),
        ("tgt_01_pos_x", TargetPosition),
        ("tgt_01_pos_y", TargetPosition),
        ("tgt_01_ground_track_angle", Semicircle),
        ("tgt_01_presentation_data", TargetPresentationData),
        ("tgt_01_call_sign", TargetHalfCallSign * 2),
        ("tgt_02_pos_x", TargetPosition),
        ("tgt_02_pos_y", TargetPosition),
        ("tgt_02_ground_track_angle", Semicircle),
        ("tgt_02_presentation_data", TargetPresentationData),
        ("tgt_02_call_sign", TargetHalfCallSign * 2),
        ("tgt_03_pos_x", TargetPosition),
        ("tgt_03_pos_y", TargetPosition),
        ("tgt_03_ground_track_angle", Semicircle),
        ("tgt_03_presentation_data", TargetPresentationData),
        ("tgt_03_call_sign", TargetHalfCallSign * 2),
        ("tgt_04_pos_x", TargetPosition),
        ("tgt_04_pos_y", TargetPosition),
        ("tgt_04_ground_track_angle", Semicircle),
        ("tgt_04_presentation_data", TargetPresentationData),
        ("tgt_04_call_sign", TargetHalfCallSign * 2),
        ("tgt_05_pos_x", TargetPosition),
        ("tgt_05_pos_y", TargetPosition),
        ("tgt_05_ground_track_angle", Semicircle),
        ("tgt_05_presentation_data", TargetPresentationData),
        ("tgt_05_call_sign", TargetHalfCallSign * 2),
    ]

    def __init__(self):
        super().__init__()
        self.dl_target_validity = DlTargetValidity()
        self.tgt_01_pos_x = TargetPosition()
        self.tgt_01_pos_y = TargetPosition()
        self.tgt_01_ground_track_angle = Semicircle()
        self.tgt_01_presentation_data = TargetPresentationData()
        self.tgt_01_call_sign = (TargetHalfCallSign * 2)()  # Inizializza l'array
        self.tgt_02_pos_x = TargetPosition()
        self.tgt_02_pos_y = TargetPosition()
        self.tgt_02_ground_track_angle = Semicircle()
        self.tgt_02_presentation_data = TargetPresentationData()
        self.tgt_02_call_sign = (TargetHalfCallSign * 2)()  # Inizializza l'array
        self.tgt_03_pos_x = TargetPosition()
        self.tgt_03_pos_y = TargetPosition()
        self.tgt_03_ground_track_angle = Semicircle()
        self.tgt_03_presentation_data = TargetPresentationData()
        self.tgt_03_call_sign = (TargetHalfCallSign * 2)()  # Inizializza l'array
        self.tgt_04_pos_x = TargetPosition()
        self.tgt_04_pos_y = TargetPosition()
        self.tgt_04_ground_track_angle = Semicircle()
        self.tgt_04_presentation_data = TargetPresentationData()
        self.tgt_04_call_sign = (TargetHalfCallSign * 2)()  # Inizializza l'array
        self.tgt_05_pos_x = TargetPosition()
        self.tgt_05_pos_y = TargetPosition()
        self.tgt_05_ground_track_angle = Semicircle()
        self.tgt_05_presentation_data = TargetPresentationData()
        self.tgt_05_call_sign = (TargetHalfCallSign * 2)()  # Inizializza l'array

    def set_target(self, idx, pos_x, pos_y, ground_track_angle, presentation_raw=None, call_sign_chars=None):
        """Populate target by index 1..5 with numeric values.

        - `idx`: 1..5
        - `pos_x`, `pos_y`: floats (meters) accepted by `TargetPosition.set`
                - `ground_track_angle`: float (radians) or integer raw. `Semicircle.set` accepts
                    radians (float) and will convert to raw; passing an `int` stores the raw word.
        - `presentation_raw`: optional 16-bit raw for `TargetPresentationData`
        - `call_sign_chars`: optional tuple/list of two bytes (msb, lsb) for half-call-sign
        """
        if idx < 1 or idx > 5:
            raise ValueError("idx must be 1..5")
        base = (idx - 1)
        setattr(self, f"tgt_{idx:02d}_pos_x", TargetPosition())
        getattr(self, f"tgt_{idx:02d}_pos_x").set(pos_x)
        setattr(self, f"tgt_{idx:02d}_pos_y", TargetPosition())
        getattr(self, f"tgt_{idx:02d}_pos_y").set(pos_y)
        setattr(self, f"tgt_{idx:02d}_ground_track_angle", Semicircle())
        getattr(self, f"tgt_{idx:02d}_ground_track_angle").set(ground_track_angle)
        if presentation_raw is not None:
            setattr(self, f"tgt_{idx:02d}_presentation_data", TargetPresentationData())
            getattr(self, f"tgt_{idx:02d}_presentation_data").raw = presentation_raw
        if call_sign_chars is not None:
            arr = (TargetHalfCallSign * 2)()
            arr[0].raw = (call_sign_chars[0] << 8) | (call_sign_chars[1] & 0xFF)
            arr[1].raw = 0
            setattr(self, f"tgt_{idx:02d}_call_sign", arr)

    def get_target_raw(self, idx):
        """Return tuple of raw words for target idx (pos_x,pos_y,angle,presentation,call1,call2)"""
        if idx < 1 or idx > 5:
            raise ValueError("idx must be 1..5")
        px = getattr(self, f"tgt_{idx:02d}_pos_x").raw
        py = getattr(self, f"tgt_{idx:02d}_pos_y").raw
        ang = getattr(self, f"tgt_{idx:02d}_ground_track_angle").raw
        pres = getattr(self, f"tgt_{idx:02d}_presentation_data").raw
        call0 = getattr(self, f"tgt_{idx:02d}_call_sign")[0].raw
        call1 = getattr(self, f"tgt_{idx:02d}_call_sign")[1].raw
        return (px, py, ang, pres, call0, call1)