import uuid
from typing import List

from opentrons.motion_planning.deck_conflict import HeaterShakerModule
from opentrons.protocol_api import Well, TrashBin, WasteChute
from opentrons.types import Location

from ..data.data import Data

from ..data.dbo.module import ModuleWrapper
from helpers import get_location_from_str


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

    @staticmethod
    def module_is_valid(module: ModuleWrapper | None):
        return module is not None and module.module_instance is not None

    def get_valid_module_by_id(self, module_id):
        module: ModuleWrapper = self.data.static_items.get_module_by_id(module_id)
        if not self.module_is_valid(module):
            raise RuntimeError("Module Heater Shaker id not valid")
        return module

    def close_labware_latch(self, module_id: uuid.UUID):
        module = self.get_valid_module_by_id(module_id)

        module.module_instance.close_labware_latch()

    def open_labware_latch(self, module_id: uuid.UUID):
        module = self.get_valid_module_by_id(module_id)

        module.module_instance.open_labware_latch()

    def deactivate_heater(self, module_id: uuid.UUID):
        module = self.get_valid_module_by_id(module_id)

        module.module_instance.deactivate_heater()

    def deactivate_shaker(self, module_id: uuid.UUID):
        module = self.get_valid_module_by_id(module_id)

        module.module_instance.deactivate_shaker()

    def set_and_wait_for_shake_speed(self, module_id: uuid.UUID, rpm: int):
        module = self.get_valid_module_by_id(module_id)

        module.module_instance.set_and_wait_for_shake_speed(rpm)

    def set_and_wait_for_temperature(self, module_id: uuid.UUID, celsius: float):
        module = self.get_valid_module_by_id(module_id)

        module.module_instance.set_and_wait_for_temperature(celsius)

    def set_target_temperature(self, module_id: uuid.UUID, celsius: float):
        module = self.get_valid_module_by_id(module_id)

        module.module_instance.set_target_temperature(celsius)

    def wait_for_temperature(self, module_id: uuid.UUID):
        module = self.get_valid_module_by_id(module_id)

        module.module_instance.wait_for_temperature()
    def load_adapter(self, module_id: uuid.UUID, load_name: str, location: str, namespace: str | None):
        module: ModuleWrapper = self.data.static_items.get_module_by_id(module_id)

        if not self.module_is_valid(module):
            raise RuntimeError("Module Heater Shaker id not valid")

        old_adapter = self.data.static_items.get_labware_by_deck_location(location)
        if len(old_adapter) is not 0:
            for key, value in old_adapter.items():
                if value.data.load_name == load_name and value.data.namespace == namespace:
                    return key

        adapter = module.module_instance.load_adapter(name=load_name,
                                                      namespace=namespace)

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

    def load_labware(self, module_id: uuid.UUID, load_name: str, location: str, namespace: str | None = None, adapter_name: str | None = None):
        module: ModuleWrapper = self.data.static_items.get_module_by_id(module_id)

        if not self.module_is_valid(module):
            raise RuntimeError("Module Heater Shaker id not valid")

        old_labware = self.data.static_items.get_labware_by_deck_location(location)
        if len(old_labware) is not 0:
            for key, value in old_labware.items():
                if value.data.load_name == load_name and value.data.namespace == namespace:
                    return key

        labware = module.module_instance.load_labware(name=load_name,
                                                      namespace=namespace,
                                                      adapter=adapter_name)

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

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