import ctypes
import Grifo_E_1553lib.data_types.enum_map as em

# Constants for year of mission range
ICD1553_YEAR_OF_MISSION_MIN = 0
ICD1553_YEAR_OF_MISSION_MAX = 63

# Constants for month of mission range
ICD1553_MONTH_OF_MISSION_MIN = 1
ICD1553_MONTH_OF_MISSION_MAX = 12

# Constants for day of mission range
ICD1553_DAY_OF_MISSION_MIN = 1
ICD1553_DAY_OF_MISSION_MAX = 31

class _DateOfMissionStr(ctypes.LittleEndianStructure):
    _pack_ = 1
    _fields_ = [
        ("spare", ctypes.c_uint16,1),
        ("day_of_mission", ctypes.c_uint16,5),
        ("month_of_mission", ctypes.c_uint16,4),
        ("year_of_mission", ctypes.c_uint16,6)
    ]
class DateOfMission(ctypes.Union):
    _pack_ = 1
    _fields_ = [
        ("raw", ctypes.c_uint16),
        ("str", _DateOfMissionStr)
    ]

    # Bitfield accessors for year_of_mission
    def get_year_of_mission(self):
        return (self.raw >> 10) & 0x3F

    def set_year_of_mission(self, value):
        if not ICD1553_YEAR_OF_MISSION_MIN <= value <= ICD1553_YEAR_OF_MISSION_MAX:
            raise ValueError(f"Year of Mission value must be between {ICD1553_YEAR_OF_MISSION_MIN} and {ICD1553_YEAR_OF_MISSION_MAX}")
        self.raw &= ~(0x3F << 10)
        self.raw |= (value << 10)

    # Bitfield accessors for month_of_mission
    def get_month_of_mission(self):
        return (self.raw >> 6) & 0x0F

    def set_month_of_mission(self, value):
        if not ICD1553_MONTH_OF_MISSION_MIN <= value <= ICD1553_MONTH_OF_MISSION_MAX:
            raise ValueError(f"Month of Mission value must be between {ICD1553_MONTH_OF_MISSION_MIN} and {ICD1553_MONTH_OF_MISSION_MAX}")
        self.raw &= ~(0x0F << 6)
        self.raw |= (value << 6)

    # Bitfield accessors for day_of_mission
    def get_day_of_mission(self):
        return (self.raw >> 1) & 0x1F

    def set_day_of_mission(self, value):
        if not ICD1553_DAY_OF_MISSION_MIN <= value <= ICD1553_DAY_OF_MISSION_MAX:
            raise ValueError(f"Day of Mission value must be between {ICD1553_DAY_OF_MISSION_MIN} and {ICD1553_DAY_OF_MISSION_MAX}")
        self.raw &= ~(0x1F << 1)
        self.raw |= (value << 1)

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

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