"""
Provide Betty's ancestry event types.
"""

from __future__ import annotations

from typing import TYPE_CHECKING

from betty.locale import Str, DEFAULT_LOCALIZER

if TYPE_CHECKING:
    from betty.model.ancestry import Person


class EventTypeProvider:
    @property
    def entity_types(self) -> set[type[EventType]]:
        raise NotImplementedError(repr(self))


class EventType:
    def __new__(cls):
        raise RuntimeError("Event types cannot be instantiated.")

    @classmethod
    def name(cls) -> str:
        raise NotImplementedError(repr(cls))

    @classmethod
    def label(cls) -> Str:
        raise NotImplementedError(repr(cls))

    @classmethod
    def comes_before(cls) -> set[type[EventType]]:
        return set()

    @classmethod
    def comes_after(cls) -> set[type[EventType]]:
        return set()


class UnknownEventType(EventType):
    @classmethod
    def name(cls) -> str:
        return "unknown"

    @classmethod
    def label(cls) -> Str:
        return Str._("Unknown")


class DerivableEventType(EventType):
    pass


class CreatableDerivableEventType(DerivableEventType):
    @classmethod
    def may_create(cls, person: Person, lifetime_threshold: int) -> bool:
        return True


class PreBirthEventType(EventType):
    @classmethod
    def comes_before(cls) -> set[type[EventType]]:
        return {Birth}


class StartOfLifeEventType(EventType):
    pass


class DuringLifeEventType(EventType):
    @classmethod
    def comes_after(cls) -> set[type[EventType]]:
        return {Birth}

    @classmethod
    def comes_before(cls) -> set[type[EventType]]:
        return {Death}


class EndOfLifeEventType(EventType):
    pass


class PostDeathEventType(EventType):
    @classmethod
    def comes_after(cls) -> set[type[EventType]]:
        return {Death}


class Birth(CreatableDerivableEventType, StartOfLifeEventType):
    @classmethod
    def name(cls) -> str:
        return "birth"

    @classmethod
    def label(cls) -> Str:
        return Str._("Birth")

    @classmethod
    def comes_before(cls) -> set[type[EventType]]:
        return {DuringLifeEventType}


class Baptism(DuringLifeEventType, StartOfLifeEventType):
    @classmethod
    def name(cls) -> str:
        return "baptism"

    @classmethod
    def label(cls) -> Str:
        return Str._("Baptism")


class Adoption(DuringLifeEventType):
    @classmethod
    def name(cls) -> str:
        return "adoption"

    @classmethod
    def label(cls) -> Str:
        return Str._("Adoption")


class Death(CreatableDerivableEventType, EndOfLifeEventType):
    @classmethod
    def name(cls) -> str:
        return "death"

    @classmethod
    def label(cls) -> Str:
        return Str._("Death")

    @classmethod
    def comes_after(cls) -> set[type[EventType]]:
        return {DuringLifeEventType}

    @classmethod
    def may_create(cls, person: Person, lifetime_threshold: int) -> bool:
        from betty.privatizer import Privatizer

        return Privatizer(lifetime_threshold, localizer=DEFAULT_LOCALIZER).has_expired(
            person, 1
        )


class FinalDispositionEventType(
    PostDeathEventType, DerivableEventType, EndOfLifeEventType
):
    pass


class Funeral(FinalDispositionEventType):
    @classmethod
    def name(cls) -> str:
        return "funeral"

    @classmethod
    def label(cls) -> Str:
        return Str._("Funeral")


class Cremation(FinalDispositionEventType):
    @classmethod
    def name(cls) -> str:
        return "cremation"

    @classmethod
    def label(cls) -> Str:
        return Str._("Cremation")


class Burial(FinalDispositionEventType):
    @classmethod
    def name(cls) -> str:
        return "burial"

    @classmethod
    def label(cls) -> Str:
        return Str._("Burial")


class Will(PostDeathEventType):
    @classmethod
    def name(cls) -> str:
        return "will"

    @classmethod
    def label(cls) -> Str:
        return Str._("Will")


class Engagement(DuringLifeEventType):
    @classmethod
    def name(cls) -> str:
        return "engagement"

    @classmethod
    def label(cls) -> Str:
        return Str._("Engagement")

    @classmethod
    def comes_before(cls) -> set[type[EventType]]:
        return {Marriage}


class Marriage(DuringLifeEventType):
    @classmethod
    def name(cls) -> str:
        return "marriage"

    @classmethod
    def label(cls) -> Str:
        return Str._("Marriage")


class MarriageAnnouncement(DuringLifeEventType):
    @classmethod
    def name(cls) -> str:
        return "marriage-announcement"

    @classmethod
    def label(cls) -> Str:
        return Str._("Announcement of marriage")

    @classmethod
    def comes_before(cls) -> set[type[EventType]]:
        return {Marriage}


class Divorce(DuringLifeEventType):
    @classmethod
    def name(cls) -> str:
        return "divorce"

    @classmethod
    def label(cls) -> Str:
        return Str._("Divorce")

    @classmethod
    def comes_after(cls) -> set[type[EventType]]:
        return {Marriage}


class DivorceAnnouncement(DuringLifeEventType):
    @classmethod
    def name(cls) -> str:
        return "divorce-announcement"

    @classmethod
    def label(cls) -> Str:
        return Str._("Announcement of divorce")

    @classmethod
    def comes_after(cls) -> set[type[EventType]]:
        return {Marriage}

    @classmethod
    def comes_before(cls) -> set[type[EventType]]:
        return {Divorce}


class Residence(DuringLifeEventType):
    @classmethod
    def name(cls) -> str:
        return "residence"

    @classmethod
    def label(cls) -> Str:
        return Str._("Residence")


class Immigration(DuringLifeEventType):
    @classmethod
    def name(cls) -> str:
        return "immigration"

    @classmethod
    def label(cls) -> Str:
        return Str._("Immigration")


class Emigration(DuringLifeEventType):
    @classmethod
    def name(cls) -> str:
        return "emigration"

    @classmethod
    def label(cls) -> Str:
        return Str._("Emigration")


class Occupation(DuringLifeEventType):
    @classmethod
    def name(cls) -> str:
        return "occupation"

    @classmethod
    def label(cls) -> Str:
        return Str._("Occupation")


class Retirement(DuringLifeEventType):
    @classmethod
    def name(cls) -> str:
        return "retirement"

    @classmethod
    def label(cls) -> Str:
        return Str._("Retirement")


class Correspondence(EventType):
    @classmethod
    def name(cls) -> str:
        return "correspondence"

    @classmethod
    def label(cls) -> Str:
        return Str._("Correspondence")


class Confirmation(DuringLifeEventType):
    @classmethod
    def name(cls) -> str:
        return "confirmation"

    @classmethod
    def label(cls) -> Str:
        return Str._("Confirmation")


class Missing(DuringLifeEventType):
    @classmethod
    def name(cls) -> str:
        return "missing"

    @classmethod
    def label(cls) -> Str:
        return Str._("Missing")


class Conference(DuringLifeEventType):
    @classmethod
    def name(cls) -> str:
        return "conference"

    @classmethod
    def label(cls) -> Str:
        return Str._("Conference")
