from UniTAP.libs.lib_tsi.tsi_io import PortIO
from UniTAP.libs.lib_tsi.tsi_private_types import *
from .pdc_private_dpam_types import DPAMCaps, DPAMState, DPAMCommand, DPAMConfig, DPAMDiscModes, DPAMRecv
from .pdc_private_types import HWControlCommand, HWStatus, HWCaps, PDCStatus, PDCControlCommand, PDCState, PDCCaps, \
    PDCContractInfo
from .pdo_private_types import PdoUnion


class PDCPortIO:

    def __init__(self, port_io: PortIO):
        self.__io = port_io
        self.write_adc_control()

    def write_dpam_caps(self, caps: DPAMCaps):
        self.__io.set(TSI_PDC_DPAM_CAPS, caps.value(), c_uint32)

    def read_dpam_caps(self) -> DPAMCaps:
        return self.__io.get(TSI_PDC_DPAM_CAPS, DPAMCaps)[1]

    def read_dpam_caps2(self) -> bool:
        return (self.__io.get(TSI_PDC_DPAM_CAPS2, c_uint32)[1] & 0x1) != 0

    def read_dpam_state(self) -> DPAMState:
        return self.__io.get(TSI_PDC_DPAM_STATE_R, DPAMState)[1]

    def write_dpam_control(self, command: DPAMCommand):
        self.__io.set(TSI_PDC_DPAM_CONTROL_W, command.value, c_uint32)

    def read_dpam_config(self) -> DPAMConfig:
        return self.__io.get(TSI_PDC_DPAM_CONFIG_R, DPAMConfig)[1]

    def read_dpam_disc_modes(self) -> DPAMDiscModes:
        return self.__io.get(TSI_PDC_DPAM_DISC_MODES_R, DPAMDiscModes)[1]

    def read_dpam_recv(self) -> DPAMRecv:
        return self.__io.get(TSI_PDC_DPAM_RECV_STS_R, DPAMRecv)[1]

    def write_hw_command(self, command: HWControlCommand):
        self.__io.set(TSI_PDC_HW_CONTROL_W, command.value, c_uint32)

    def read_hw_status(self) -> HWStatus:
        return self.__io.get(TSI_PDC_HW_STATUS_R, HWStatus)[1]

    def read_hw_caps(self) -> HWCaps:
        return self.__io.get(TSI_PDC_HW_CAPS_R, HWCaps)[1]

    def read_pdc_status(self) -> PDCStatus:
        return self.__io.get(TSI_PDC_STATUS_R, PDCStatus)[1]

    def write_pdc_command(self, command: PDCControlCommand):
        self.__io.set(TSI_PDC_CONTROL, command.value, c_uint32)

    def read_pdc_state(self) -> PDCState:
        return self.__io.get(TSI_PDC_STATE, PDCState)[1]

    def read_pdc_caps(self) -> PDCCaps:
        return self.__io.get(TSI_PDC_CAPS, PDCCaps)[1]

    def write_pdc_contract_control(self, caps: PDCContractInfo):
        self.__io.set(TSI_USBC_PWR_CONTRACT_CONTROL, caps.value(), c_uint32)

    def read_pdc_contract_control(self) -> PDCContractInfo:
        return self.__io.get(TSI_USBC_PWR_CONTRACT_CONTROL, PDCContractInfo)[1]

    def read_local_spr_source_pdo(self) -> list:
        return self.__io.get(TSI_USBC_PWR_LOCAL_SOURCE_PDO, PdoUnion, self.read_hw_caps().pdo_count)[1]

    def write_local_spr_source_pdo(self, data: list):
        self.__io.set(TSI_USBC_PWR_LOCAL_SOURCE_PDO, data, c_uint32, len(data))

    def read_local_spr_sink_pdo(self) -> list:
        return self.__io.get(TSI_USBC_PWR_LOCAL_SINK_PDO, PdoUnion, self.read_hw_caps().pdo_count)[1]

    def write_local_spr_sink_pdo(self, data: list):
        self.__io.set(TSI_USBC_PWR_LOCAL_SINK_PDO, data, c_uint32, len(data))

    def read_tx_id_vdo_count(self) -> int:
        return self.__io.get(TSI_PDC_TX_ID_VDO_CNT, c_uint32)[1]

    def read_tx_id_vdo(self) -> list:
        return self.__io.get(TSI_PDC_TX_ID_VDO, c_uint32, self.read_tx_id_vdo_count())[1]

    def write_tx_id_vdo(self, data: list):
        self.__io.set(TSI_PDC_TX_ID_VDO, data, c_uint32, len(data))

    def read_contract_data(self) -> list:
        return self.__io.get(TSI_PDC_CONTRACT_DATA, c_uint32, 4)[1]

    def write_contract_data(self, data: list):
        self.__io.set(TSI_PDC_CONTRACT_DATA, data, c_uint32, len(data))

    def read_power_contract_select(self) -> int:
        return self.__io.get(TSI_USBC_PWR_CONTRACT_SELECT, c_uint32)[1]

    def write_power_contract_select(self, index: int):
        self.__io.set(TSI_USBC_PWR_CONTRACT_SELECT, index, c_uint32)

    def read_resistance(self) -> int:
        return self.__io.get(TSI_USBC_RESISTANCE_CONTROL, c_uint32)[1]

    def write_resistance(self, resistance: int):
        self.__io.set(TSI_USBC_RESISTANCE_CONTROL, resistance, c_uint32)

    def read_adc_vbus_status(self) -> list:
        return self.__io.get(TSI_ADC_VBUS_VOLTAGE_R, c_uint32, TSI_ADC_BLOCK_SIZE_WORDS)[1]

    def read_internal_resistance(self) -> int:
        return self.__io.get(TSI_USBC_INT_RESISTANCE_STATUS_R, c_uint32)[1]

    def read_external_resistance(self) -> int:
        return self.__io.get(TSI_USBC_EXT_RESISTANCE_STATUS_R, c_uint32)[1]

    def write_adc_control(self):
        self.__io.set(TSI_W_USBC_ADC_CTRL, 1, c_uint32)
