from abc import ABC, abstractmethod

from opentrons.types import Location, Point
from opentrons_shared_data.labware.dev_types import LabwareDefinition


class AbstractLabwareGeometry(ABC):
    """Convenience interface for accessing geometry properties of a labware."""

    @property
    @abstractmethod
    def parent(self) -> Location:
        ...

    @property
    @abstractmethod
    def offset(self) -> Point:
        ...

    @property
    @abstractmethod
    def x_dimension(self) -> float:
        ...

    @property
    @abstractmethod
    def y_dimension(self) -> float:
        ...

    @property
    @abstractmethod
    def z_dimension(self) -> float:
        ...


class LabwareGeometry(AbstractLabwareGeometry):
    def __init__(self, definition: LabwareDefinition, parent: Location):
        """Constructor"""
        self._parent = parent
        offset = definition["cornerOffsetFromSlot"]
        self._offset = Point(offset["x"], offset["y"], offset["z"]) + parent.point

        dimensions = definition["dimensions"]
        self._x_dimension = dimensions["xDimension"]
        self._y_dimension = dimensions["yDimension"]
        self._z_dimension = dimensions["zDimension"]

    @property
    def parent(self) -> Location:
        return self._parent

    @property
    def offset(self) -> Point:
        return self._offset

    @property
    def x_dimension(self) -> float:
        return self._x_dimension

    @property
    def y_dimension(self) -> float:
        return self._y_dimension

    @property
    def z_dimension(self) -> float:
        return self._z_dimension
