from ..message_base import MessageBase
from ..constants import (
    Subaddress, BullsEyeSelect, WaypointType, WaypointQualifier,
    InterceptMode, LineStyle, SymbolState, Identity
)
from ..fields import BitField, EnumField, ScaledField, ASCIIField

class MsgA3(MessageBase):
    """
    Message A3: Graphic Settings
    
    ID: A3
    Direction: BC -> RT (Receive)
    Subaddress: 03
    Rate: 6.25 Hz
    Document Ref: 7.1.3
    """
    SUBADDRESS = Subaddress.RX_GRAPHIC
    IS_TRANSMIT = False
    RATE_HZ = 6.25

    # --- Word 01: Graphic Order (Ref 7.1.3.1) ---
    # Graphic Symbols Enable Flags (1=Display)
    show_waypoint_1 = BitField(word_index=0, start_bit=0, width=1)
    show_waypoint_2 = BitField(word_index=0, start_bit=1, width=1)
    show_waypoint_3 = BitField(word_index=0, start_bit=2, width=1)
    show_intercept_fd = BitField(word_index=0, start_bit=3, width=1)
    show_break_away_cue = BitField(word_index=0, start_bit=4, width=1)
    show_intercept_zones = BitField(word_index=0, start_bit=5, width=1)
    show_ttg_cursor = BitField(word_index=0, start_bit=6, width=1)
    show_asec_circle = BitField(word_index=0, start_bit=7, width=1)
    show_attack_steering = BitField(word_index=0, start_bit=8, width=1)
    
    # Bull's Eye Selection
    bullseye_select = EnumField(word_index=0, start_bit=9, width=2, enum_cls=BullsEyeSelect)
    
    # Bits 11-15 Spare

    # --- Word 02: Time-to-Go to Cursor (Ref 7.1.3.2) ---
    # LSB = 1 sec
    ttg_cursor = ScaledField(word_index=1, start_bit=0, width=16, lsb_value=1.0)

    # --- Helper function for 25-bit Semicircles (Lat/Lon) ---
    def _get_25bit_semicircle(self, word_idx_msw, word_idx_lsw):
        """
        Combines MSW (16 bit) and LSW (9 bit) to form a 25-bit 2's complement
        Semicircle value. LSB = 5.96046e-8.
        """
        msw = self._data[word_idx_msw]
        # LSW uses only bits 0-8 (9 bits)
        lsw = (self._data[word_idx_lsw] >> 7) & 0x1FF 
        
        # Combine: MSW is top 16 bits, LSW is bottom 9 bits
        raw_25 = (msw << 9) | lsw
        
        # Handle 2's complement for 25 bits
        if raw_25 & (1 << 24): # Sign bit check
            raw_25 -= (1 << 25)
            
        # Scale (1.0 full scale / 2^24) approx 5.96046e-8
        return float(raw_25 * 5.9604644775e-8)

    # --- Waypoint 1 Data (Ref 7.1.3.3 - 7.1.3.4) ---
    # Raw accessors for internal use if needed, but properties are preferred
    _wp1_lat_msw = BitField(word_index=2, start_bit=0, width=16)
    _wp1_lat_lsw = BitField(word_index=3, start_bit=0, width=9) # Bits 0-8
    
    @property
    def wp1_latitude(self):
        return self._get_25bit_semicircle(2, 3)

    wp1_type = EnumField(word_index=3, start_bit=9, width=1, enum_cls=WaypointType)
    wp1_qualifier_valid = BitField(word_index=3, start_bit=10, width=1)
    wp1_qualifier_val = EnumField(word_index=3, start_bit=11, width=2, enum_cls=WaypointQualifier)
    
    # WP1 Longitude
    @property
    def wp1_longitude(self):
        return self._get_25bit_semicircle(4, 5)

    wp1_code = BitField(word_index=5, start_bit=9, width=7) # 0-99

    # --- Waypoint 2 Data (Ref 7.1.3.5 - 7.1.3.6) ---
    @property
    def wp2_latitude(self):
        return self._get_25bit_semicircle(6, 7)
    
    wp2_type = EnumField(word_index=7, start_bit=9, width=1, enum_cls=WaypointType)
    wp2_qualifier_valid = BitField(word_index=7, start_bit=10, width=1)
    wp2_qualifier_val = EnumField(word_index=7, start_bit=11, width=2, enum_cls=WaypointQualifier)

    @property
    def wp2_longitude(self):
        return self._get_25bit_semicircle(8, 9)

    wp2_code = BitField(word_index=9, start_bit=9, width=7)

    # --- Waypoint 3 Data (Ref 7.1.3.7 - 7.1.3.8) ---
    @property
    def wp3_latitude(self):
        return self._get_25bit_semicircle(10, 11)
        
    wp3_type = EnumField(word_index=11, start_bit=9, width=1, enum_cls=WaypointType)
    wp3_qualifier_valid = BitField(word_index=11, start_bit=10, width=1)
    wp3_qualifier_val = EnumField(word_index=11, start_bit=11, width=2, enum_cls=WaypointQualifier)

    @property
    def wp3_longitude(self):
        return self._get_25bit_semicircle(12, 13)

    wp3_code = BitField(word_index=13, start_bit=9, width=7)

    # --- Intercept Flight Director (Ref 7.1.3.9 - 7.1.3.10) ---
    ifd_x = BitField(word_index=14, start_bit=0, width=9) # Pixels
    ifd_mode = EnumField(word_index=14, start_bit=10, width=1, enum_cls=InterceptMode)
    ifd_style = EnumField(word_index=14, start_bit=11, width=1, enum_cls=LineStyle)
    
    ifd_y = BitField(word_index=15, start_bit=0, width=9) # Pixels

    # --- Intercept Zones (Ref 7.1.3.11 - 7.1.3.14) ---
    int_zone_rmin_y = BitField(word_index=16, start_bit=0, width=9)
    int_zone_rmax_y = BitField(word_index=17, start_bit=0, width=9)
    no_escape_rmax_y = BitField(word_index=18, start_bit=0, width=9)
    int_zone_target_tip_y = BitField(word_index=19, start_bit=0, width=9)

    # --- ASEC (Ref 7.1.3.15) ---
    asec_radius = BitField(word_index=20, start_bit=0, width=9)
    asec_blink = EnumField(word_index=20, start_bit=9, width=1, enum_cls=SymbolState)

    # --- Attack Steering Cue (Ref 7.1.3.16 - 7.1.3.17) ---
    asc_x = BitField(word_index=21, start_bit=0, width=9)
    asc_blink = EnumField(word_index=21, start_bit=10, width=1, enum_cls=SymbolState)
    asc_y = BitField(word_index=22, start_bit=0, width=9)

    # --- Tracked Target Info (Ref 7.1.3.18) ---
    hpt_in_int_zone = BitField(word_index=23, start_bit=0, width=1)
    hpt_datalink_corr = BitField(word_index=23, start_bit=1, width=1)
    hpt_identity = EnumField(word_index=23, start_bit=2, width=1, enum_cls=Identity)
    
    spt_in_int_zone = BitField(word_index=23, start_bit=3, width=1)
    spt_datalink_corr = BitField(word_index=23, start_bit=4, width=1)
    spt_identity = EnumField(word_index=23, start_bit=5, width=1, enum_cls=Identity)
    
    # TWS Targets in Zone (Bits 6-13)
    tws_tgt_1_in_zone = BitField(word_index=23, start_bit=6, width=1)
    tws_tgt_2_in_zone = BitField(word_index=23, start_bit=7, width=1)
    # ... bits 8-13 follow same logic for targets 3-8

    # --- Call Signs (Ref 7.1.3.19 - 7.1.3.20) ---
    hpt_callsign_ab = ASCIIField(word_index=24) # Chars 1 & 2
    hpt_callsign_cd = ASCIIField(word_index=25) # Chars 3 & 4
    
    spt_callsign_ab = ASCIIField(word_index=26)
    spt_callsign_cd = ASCIIField(word_index=27)

    # --- Track IDs (Ref 7.1.3.21 - 7.1.3.24) ---
    # These are 8-bit IDs. We use BitField manually.
    tws_id_01 = BitField(word_index=28, start_bit=0, width=8)
    tws_id_02 = BitField(word_index=28, start_bit=8, width=8)
    
    tws_id_03 = BitField(word_index=29, start_bit=0, width=8)
    tws_id_04 = BitField(word_index=29, start_bit=8, width=8)
    
    tws_id_05 = BitField(word_index=30, start_bit=0, width=8)
    tws_id_06 = BitField(word_index=30, start_bit=8, width=8)
    
    tws_id_07 = BitField(word_index=31, start_bit=0, width=8)
    tws_id_08 = BitField(word_index=31, start_bit=8, width=8)