import uuid

from opentrons.protocol_api._types import OffDeckType

from ..data.data import Data
from ..data.dbo.labware import LabwareWrapper


class LabwareLogic:
    def __init__(self, data: Data):
        self.data = data

    @staticmethod
    def labware_is_valid(instrument: LabwareWrapper | None):
        return instrument is not None and instrument.labware_instance is not None

    def child(self, labware_id: uuid.UUID):
        labware = self.get_valid_labware_by_id(labware_id)

        if labware.labware_instance.child is None:
            return None

        return self.data.static_items.get_generic_id_by_reference(labware.labware_instance.child)

    def parent(self, labware_id: uuid.UUID):
        labware = self.get_valid_labware_by_id(labware_id)

        parent = labware.labware_instance.parent

        if isinstance(parent, OffDeckType):
            return None

        if isinstance(parent, str):
            return parent


        return self.data.static_items.get_generic_id_by_reference(parent)

    def highest_z(self, labware_id: uuid.UUID):
        labware = self.get_valid_labware_by_id(labware_id)

        return labware.labware_instance.highest_z

    def tip_length(self, labware_id: uuid.UUID):
        labware = self.get_valid_labware_by_id(labware_id)

        return labware.labware_instance.tip_length

    def load_labware(self, labware_id: uuid.UUID, load_name: str, namespace: str = ""):
        parent_labware = self.get_valid_labware_by_id(labware_id)

        ns: str | None = namespace

        if len(namespace) == 0:
            ns = None

        child_labware = parent_labware.labware_instance.load_labware(name=load_name, namespace=ns)

        self.data.dynamic_items.register_wells_by_labware(labware=child_labware)

        return self.data.static_items.register_labware(labware=child_labware)

    def wells(self, labware_id: uuid.UUID):
        labware = self.get_valid_labware_by_id(labware_id)

        wells = labware.labware_instance.wells()

        well_ids = self.data.dynamic_items.get_well_ids_by_reference(wells)

        return well_ids

    def rows(self, labware_id: uuid.UUID):
        labware = self.get_valid_labware_by_id(labware_id)

        rows = labware.labware_instance.rows()

        new_rows = []

        for row in rows:
            new_rows.append(self.data.dynamic_items.get_well_ids_by_reference(row))

        return new_rows

    def columns(self, labware_id: uuid.UUID):
        labware = self.get_valid_labware_by_id(labware_id)

        columns = labware.labware_instance.columns()

        new_columns = []

        for column in columns:
            new_columns.append(self.data.dynamic_items.get_well_ids_by_reference(column))

        return new_columns

    def reset(self, labware_id: uuid.UUID):
        labware = self.get_valid_labware_by_id(labware_id)

        labware.labware_instance.reset()

    def get_valid_labware_by_id(self, labware_id: uuid.UUID):
        labware = self.data.static_items.get_labware_by_id(labware_id)
        if not self.labware_is_valid(labware):
            raise RuntimeError("Labware id not valid")
        return labware
