from UniTAP.dev.ports.modules.pdc.pdo_private_types import *
from UniTAP.dev.ports.modules.pdc.pdo_types import *


def get_pdo_value(pdo: PdoType) -> int:
    if isinstance(pdo, FixedPdoSink):
        value = int(pdo.oper_current / 10) | (int(pdo.voltage / 50) << 10) | (pdo.dual_data_role << 25) | (pdo.usb_communication << 26) | \
                (pdo.unconstrained_power << 27) | (pdo.higher_capability << 28) | (pdo.dual_power_role << 29)
        return value
    elif isinstance(pdo, FixedPdoSource):
        value = int(pdo.max_current / 10) | (int(pdo.voltage / 50) << 10) | (pdo.peak_current.value << 20) | (pdo.dual_data_role << 25) | \
                (pdo.usb_communication << 26) | (pdo.unconstrained_power << 27) | (pdo.higher_capability << 28) | \
                pdo.dual_power_role << 29
        return value
    elif isinstance(pdo, BatteryPdo):
        value = int(pdo.max_power / 250) | (int(pdo.min_voltage / 50) << 10) | (int(pdo.max_voltage / 50) << 20) | (1 << 30)
        return value
    elif isinstance(pdo, VariablePdo):
        value = int(pdo.max_current / 10) | (int(pdo.min_voltage / 50) << 10) | (int(pdo.max_voltage / 50) << 20) | (2 << 30)
        return value


def interpret_pdo_value(old_type: PdoType, new_type: PdoType) -> PdoTypeStruct:
    if new_type == FixedPdoSink:
        return PdoUnion(get_pdo_value(old_type)).fixed_pdo_sink
    elif new_type == FixedPdoSource:
        return PdoUnion(get_pdo_value(old_type)).fixed_pdo_source
    elif new_type == BatteryPdo:
        return PdoUnion(get_pdo_value(old_type)).battery_pdo
    elif new_type == VariablePdo:
        return PdoUnion(get_pdo_value(old_type)).variable_pdo
