import ctypes
from .enums import FrequencyAgilityType, FrequencyGroupSelector, WaveformInterleave, LPRFThreshold
import Grifo_E_1553lib.data_types.enum_map as em
# Constants for channel range
ICD1553_CHANNEL_MIN = 1
ICD1553_CHANNEL_MAX = 30

em.ENUM_MAP.update({
    "lprf_threshold" : LPRFThreshold,
    "waveform_interleave_selection" : WaveformInterleave,
    "frequency_group_5_selector" : FrequencyGroupSelector,
    "frequency_group_4_selector" : FrequencyGroupSelector,
    "frequency_group_3_selector" : FrequencyGroupSelector,
    "frequency_group_2_selector" : FrequencyGroupSelector,
    "frequency_group_1_selector" : FrequencyGroupSelector,
    "frequency_agility_type" : FrequencyAgilityType
})

class _FrequencyStr(ctypes.LittleEndianStructure):
    _pack_ = 1
    _fields_ = [
        ("lprf_threshold", ctypes.c_uint16,1),
        ("waveform_interleave_selection", ctypes.c_uint16, 2),
        ("frequency_channel", ctypes.c_uint16,6),
        ("frequency_group_5_selector", ctypes.c_uint16,1),
        ("frequency_group_4_selector", ctypes.c_uint16,1),
        ("frequency_group_3_selector", ctypes.c_uint16,1),
        ("frequency_group_2_selector", ctypes.c_uint16,1),
        ("frequency_group_1_selector", ctypes.c_uint16,1),
        ("frequency_agility_type", ctypes.c_uint16,2)
        
    ]

class Frequency(ctypes.Structure):
    _pack_ = 1
    _fields_ = [
        ("raw", ctypes.c_uint16),
        ("str", _FrequencyStr)
    ]

    # Bitfield accessors for agility
    def get_agility(self):
        return  (self.raw >> 14) & 0x03

    def set_agility(self, value):
        self.raw &= ~(0x03 << 14)
        self.raw |= (value << 14)

    # Bitfield accessors for frq_group1
    def get_frq_group1(self):
        return  (self.raw >> 13) & 0x01

    def set_frq_group1(self, value):
        self.raw &= ~(0x01 << 13)
        self.raw |= (value << 13)

    # Bitfield accessors for frq_group2
    def get_frq_group2(self):
        return  (self.raw >> 12) & 0x01

    def set_frq_group2(self, value):
        self.raw &= ~(0x01 << 12)
        self.raw |= (value << 12)

    # Bitfield accessors for frq_group3
    def get_frq_group3(self):
        return  (self.raw >> 11) & 0x01

    def set_frq_group3(self, value):
        self.raw &= ~(0x01 << 11)
        self.raw |= (value << 11)

    # Bitfield accessors for frq_group4
    def get_frq_group4(self):
        return  (self.raw >> 10) & 0x01

    def set_frq_group4(self, value):
        self.raw &= ~(0x01 << 10)
        self.raw |= (value << 10)

    # Bitfield accessors for frq_group5
    def get_frq_group5(self):
        return  (self.raw >> 9) & 0x01

    def set_frq_group5(self, value):
        self.raw &= ~(0x01 << 9)
        self.raw |= (value << 9)

    # Bitfield accessors for channel
    def get_channel(self):
        return (self.raw >> 3) & 0x3F

    def set_channel(self, value):
        if not ICD1553_CHANNEL_MIN <= value <= ICD1553_CHANNEL_MAX:
            raise ValueError(f"Channel value must be between {ICD1553_CHANNEL_MIN} and {ICD1553_CHANNEL_MAX}")
        self.raw &= ~(0x3F << 3)
        self.raw |= (value << 3)

    # Bitfield accessors for waveform
    def get_waveform(self):
        return  (self.raw >> 1) & 0x03

    def set_waveform(self, value):
        self.raw &= ~(0x03 << 1)
        self.raw |= (value << 1)

    # Bitfield accessors for lprf_threshold
    def get_lprf_threshold(self):
        return (self.raw >> 0) & 0x01

    def set_lprf_threshold(self, value):
        self.raw &= ~(0x01 << 0)
        self.raw |= (value << 0)

class BeaconDelayAndCode(ctypes.Structure):
    _pack_ = 1
    _fields_ = [
        ("raw", ctypes.c_uint16)
    ]

    # Bitfield accessors for delay
    def get_delay(self):
        return (self.raw >> 4) & 0xFFF

    def set_delay(self, value):
        self.raw &= ~(0xFFF << 4)
        self.raw |= (value << 4)

    # Bitfield accessors for code
    def get_code(self):
        return (self.raw >> 0) & 0x0F

    def set_code(self, value):
        self.raw &= ~(0x0F << 0)
        self.raw |= (value << 0)
        
