"""Defines enums"""

# pylint: disable=too-few-public-methods

from enum import Enum, auto
from typing import Callable


class BaseClass():
    """Demo only"""

class TestLecture(BaseClass):
    """This constructor has type Callable[[int, str], TestLecture]"""
    def __init__(self, id_: int, action: str):
        print(f"CadLecture constructor called with id {id_} and action {action}")

class TestSection(BaseClass):
    """This constructor has type Callable[[int, str], TestSection]"""
    def __init__(self, id_: int, action: str):
        print(f"CadSection constructor called with id {id_} and action {action}")

class TestCourse(BaseClass):
    """This constructor has type Callable[[int, str], TestCourse]"""
    def __init__(self, id_: int, action: str):
        print(f"CadCourse constructor called with id {id_} and action {action}")

class TestGroup(BaseClass):
    """This constructor has type Callable[[int, str], TestGroup]"""
    def __init__(self, id_: int, action: str):
        print(f"CadGroup constructor called with id {id_} and action {action}")

class TestSite(BaseClass):
    """This constructor has type Callable[[int, str], TestSite]"""
    def __init__(self, id_: int, action: str):
        print(f"CadSite constructor called with id {id_} and action {action}")


class EntityType(Enum):
    """Types of entities"""
    SITE = auto()
    GROUP = auto()
    COURSE = auto()
    SECTION = auto()
    LECTURE = auto()

    @property
    def to_s(self) -> str:
        """:return: lower-case name of this instance"""
        return self.name.lower()

    @property
    def parent(self) -> 'EntityType':
        """:return: entity type of parent; site has no parent"""
        return EntityType(max(self.value - 1, 1))

    @property
    def construct(self) -> Callable:
        """:return: the appropriate Callable for each enum value"""
        if self == EntityType.LECTURE:
            return TestLecture
        if self == EntityType.SECTION:
            return TestSection
        if self == EntityType.COURSE:
            return TestCourse
        if self == EntityType.GROUP:
            return TestGroup
        return TestSite


if __name__ == "__main__":  # Just for demonstration
    print("Specifying individual values:")
    print(f"  {EntityType.SITE.value}: {EntityType.SITE.to_s}")
    print(f"  {EntityType.GROUP.value}: {EntityType.GROUP.to_s}")
    print(f"  {EntityType.COURSE.value}: {EntityType.COURSE.to_s}")
    print(f"  {EntityType.SECTION.value}: {EntityType.SECTION.to_s}")
    print(f"  {EntityType.LECTURE.value}: {EntityType.LECTURE.to_s}")

    print("\nIterating through all values:")
    for entity_type in EntityType:
        print(f"  {entity_type.value}: {entity_type.to_s}")

    print("\nConstructing a class specific to each EntityType value by invoking the appropriate Callable:")
    EntityType.LECTURE.construct(id_=55, action="gimme_lecture")
    EntityType.SECTION.construct(id_=13, action="gimme_section")
    EntityType.COURSE.construct(id_=140, action="gimme_course")
    EntityType.GROUP.construct(id_=103, action="gimme_group")
    EntityType.SITE.construct(id_=1, action="gimme_site")
