import uuid
from dataclasses import dataclass
from typing import Literal, List

from opentrons.protocol_api import InstrumentContext

from ..data import StaticItemsDict, DynamicItemsDict


@dataclass
class InstrumentData:
    instrument_name: str
    """Instrument name used for loading the module"""
    mount: str | None = None
    """Where the instrument is mounted on the OT"""
    tip_racks: List[uuid.UUID] | None = None
    """Default tip racks assigned to this instrument"""

    def update(self, instance: InstrumentContext, static_items: StaticItemsDict):
        new_tip_racks = []

        for tip_rack in instance.tip_racks:
            tip_rack_id = static_items.get_generic_id_by_reference(tip_rack)
            if tip_rack_id is not None:
                new_tip_racks.append(tip_rack_id)
            else:
                raise RuntimeError()

        self.tip_racks = new_tip_racks

    @staticmethod
    def from_instance(instance: InstrumentContext, static_items: StaticItemsDict):
        mount: str | None = None
        if instance.channels != 96 and (instance.mount == "left" or instance.mount == "right"):
            mount = instance.mount

        data = InstrumentData(instrument_name=instance.name, mount=mount)
        data.update(instance, static_items)
        return data


@dataclass
class InstrumentWrapper:
    instrument_instance: InstrumentContext | None
    """The instance used for usage in the Opentrons API"""
    data: InstrumentData
    """Data needed to instantiate the instance"""

    def __eq__(self, other):
        if isinstance(other, InstrumentWrapper):
            return self.instrument_instance == other.instrument_instance
        if isinstance(other, InstrumentContext):
            return self.instrument_instance == other
        return False

    @staticmethod
    def from_instance(instance: InstrumentContext, static_items: StaticItemsDict):
        data = InstrumentData.from_instance(instance, static_items)
        data.update(instance, static_items)
        return InstrumentWrapper(instrument_instance=instance,
                                 data=data)
