import ctypes
import math

ICD1553_SEMICIRCLE_LSB = 3.05176E-05
GC_K_PI = math.pi
ICD1553_SEMICIRCLE_RAD_LSB = ICD1553_SEMICIRCLE_LSB * GC_K_PI

class Semicircle(ctypes.Union):
    _fields_ = [("raw", ctypes.c_int16),
                ("az_scan_centre", ctypes.c_int16),
                ("el_scan_centre", ctypes.c_int16),
                ("cursor_world_pos_azimuth", ctypes.c_int16),
                ("platform_azimuth", ctypes.c_int16),
                ("roll", ctypes.c_int16),
                ("pitch", ctypes.c_int16),
                ("az_antenna_demand", ctypes.c_int16),
                ("el_antenna_demand", ctypes.c_int16),
                ("wind_direction", ctypes.c_int16),
                ("true_heading", ctypes.c_int16),
                ("magnetic_heading", ctypes.c_int16),
                ]

    def get(self):
        """Return the raw 16-bit stored value (preserves backward compatibility).

        Use `to_radians()` to get the value converted to radians.
        """
        return self.raw

    def to_radians(self):
        """Return the stored value converted to radians using ICD LSB."""
        return float(self.raw) * ICD1553_SEMICIRCLE_RAD_LSB

    def set(self, value):
        """Set the stored raw value.

        - If `value` is an `int`, it's treated as the raw 16-bit word and stored as-is.
        - Otherwise it's treated as radians (float) and converted using the ICD LSB.

        Values are clamped to signed 16-bit range to avoid overflow.
        """
        # determine raw representation
        if isinstance(value, int):
            raw = int(value)
        else:
            # treat as radians
            raw = int(round(float(value) / ICD1553_SEMICIRCLE_RAD_LSB))

        # clamp to int16
        if raw < -32768:
            raw = -32768
        if raw > 32767:
            raw = 32767

        self.raw = ctypes.c_int16(raw).value