
import numbers
from abc import ABC, abstractmethod
from typing import Union, Tuple


class Shape(ABC):

    proper_space: int
    embedding_space: int

    @abstractmethod
    def area(self):
        """Calculate shape area"""

    @abstractmethod
    def length(self):
        """Calculate shape length"""

    @abstractmethod
    def bounding_box(self) -> Union[None, Tuple[numbers.Real, numbers.Real, numbers.Real, numbers.Real]]:
        """Calculate bounding box
        with format x_min, y_min, x_max, y_max
        """

    @abstractmethod
    def clone(self) -> 'Shape':
        """
        Clone a shape."""

    @property
    def dimension(self) -> numbers.Integral:
        """The embedding space dimension of the shape instance"""
        return self.embedding_space


Category = Union[str, numbers.Integral]


if __name__ == "__main__":

    import doctest

    doctest.testmod()


def check_equal_dimension(
        first: Shape,
        second: Shape):
    """Check that the two shapes have equal dimension."""

    return first.embedding_space == second.embedding_space
