import datetime
from _typeshed import Incomplete, SupportsItems
from collections.abc import Callable, Iterable
from typing import Any, ClassVar, Final, Literal, NamedTuple, TypeVar, overload
from typing_extensions import Self

from .alarms import Alarms
from .caselessdict import CaselessDict
from .error import IncompleteComponent as IncompleteComponent
from .parser import Contentline, Contentlines
from .parser_tools import ICAL_TYPE
from .prop import TypesFactory, _vType, vRecur
from .timezone.tzp import TZP

_D = TypeVar("_D")

__all__ = [
    "Alarm",
    "Calendar",
    "Component",
    "ComponentFactory",
    "Event",
    "FreeBusy",
    "INLINE",
    "Journal",
    "Timezone",
    "TimezoneDaylight",
    "TimezoneStandard",
    "Todo",
    "component_factory",
    "get_example",
    "IncompleteComponent",
]

def get_example(component_directory: str, example_name: str) -> bytes: ...

class ComponentFactory(CaselessDict[Incomplete]):
    # Inherit complex __init__ from CaselessDict<-dict.
    ...

INLINE: CaselessDict[int]

class Component(CaselessDict[Incomplete]):
    name: ClassVar[str | None]
    required: ClassVar[tuple[str, ...]]
    singletons: ClassVar[tuple[str, ...]]
    multiple: ClassVar[tuple[str, ...]]
    exclusive: ClassVar[tuple[str, ...]]
    inclusive: ClassVar[tuple[tuple[str, ...], ...]]
    ignore_exceptions: ClassVar[bool]
    subcomponents: list[Incomplete]
    errors: list[str]

    # Inherit complex __init__ from CaselessDict<-dict.
    def __bool__(self) -> bool: ...
    __nonzero__ = __bool__
    def is_empty(self) -> bool: ...

    @overload
    def add(self, name: str, value: Any, *, encode: Literal[False]) -> None: ...
    @overload
    def add(self, name: str, value: Any, parameters: None, encode: Literal[False]) -> None: ...
    @overload
    def add(
        self, name: str, value: Any, parameters: SupportsItems[str, str | None] | None = None, encode: Literal[True] = True
    ) -> None: ...

    def decoded(self, name: str, default: _D = ...) -> Incomplete | _D: ...
    def get_inline(self, name: str, decode: bool = True) -> list[Incomplete]: ...

    @overload
    def set_inline(self, name: str, values: Iterable[str], encode: Literal[False] = ...) -> None: ...
    @overload
    def set_inline(self, name: str, values: Iterable[Incomplete], encode: Literal[True] = True) -> None: ...

    def add_component(self, component: Component) -> None: ...
    def walk(self, name: str | None = None, select: Callable[[Component], bool] = ...) -> list[Component]: ...
    def property_items(self, recursive: bool = True, sorted: bool = True) -> list[tuple[str, object]]: ...

    @overload
    @classmethod
    def from_ical(cls, st: str, multiple: Literal[False] = False) -> Component: ...  # or any of its subclasses
    @overload
    @classmethod
    def from_ical(cls, st: str, multiple: Literal[True]) -> list[Component]: ...  # or any of its subclasses

    def content_line(self, name: str, value: _vType | ICAL_TYPE, sorted: bool = True) -> Contentline: ...
    def content_lines(self, sorted: bool = True) -> Contentlines: ...
    def to_ical(self, sorted: bool = True) -> bytes: ...
    def __eq__(self, other: Component) -> bool: ...  # type: ignore[override]

    @property
    def DTSTAMP(self) -> datetime.datetime | None: ...
    @DTSTAMP.setter
    def DTSTAMP(self, value: datetime.datetime) -> None: ...
    @DTSTAMP.deleter
    def DTSTAMP(self) -> None: ...

    @property
    def LAST_MODIFIED(self) -> datetime.datetime | None: ...
    @LAST_MODIFIED.setter
    def LAST_MODIFIED(self, value: datetime.datetime) -> None: ...
    @LAST_MODIFIED.deleter
    def LAST_MODIFIED(self) -> None: ...

    def is_thunderbird(self) -> bool: ...

# type_def is a TypeForm
def create_single_property(
    prop: str, value_attr: str | None, value_type: tuple[type, ...], type_def: Any, doc: str, vProp: type[Incomplete] = ...
) -> property: ...

class Event(Component):
    name: ClassVar[Literal["VEVENT"]]
    @property
    def alarms(self) -> Alarms: ...
    @classmethod
    def example(cls, name: str = "rfc_9074_example_3") -> Event: ...

    @property
    def DTSTART(self) -> datetime.date | datetime.datetime | None: ...
    @DTSTART.setter
    def DTSTART(self, value: datetime.date | datetime.datetime | None) -> None: ...
    @DTSTART.deleter
    def DTSTART(self) -> None: ...

    @property
    def DTEND(self) -> datetime.date | datetime.datetime | None: ...
    @DTEND.setter
    def DTEND(self, value: datetime.date | datetime.datetime | None) -> None: ...
    @DTEND.deleter
    def DTEND(self) -> None: ...

    @property
    def DURATION(self) -> datetime.timedelta | None: ...
    @DURATION.setter
    def DURATION(self, value: datetime.timedelta | None) -> None: ...
    @DURATION.deleter
    def DURATION(self) -> None: ...

    @property
    def duration(self) -> datetime.timedelta: ...

    @property
    def start(self) -> datetime.date | datetime.datetime: ...
    @start.setter
    def start(self, value: datetime.date | datetime.datetime | None) -> None: ...

    @property
    def end(self) -> datetime.date | datetime.datetime: ...
    @end.setter
    def end(self, value: datetime.date | datetime.datetime | None) -> None: ...

    @property
    def X_MOZ_SNOOZE_TIME(self) -> datetime.datetime | None: ...
    @X_MOZ_SNOOZE_TIME.setter
    def X_MOZ_SNOOZE_TIME(self, value: datetime.datetime) -> None: ...
    @X_MOZ_SNOOZE_TIME.deleter
    def X_MOZ_SNOOZE_TIME(self) -> None: ...

    @property
    def X_MOZ_LASTACK(self) -> datetime.datetime | None: ...
    @X_MOZ_LASTACK.setter
    def X_MOZ_LASTACK(self, value: datetime.datetime) -> None: ...
    @X_MOZ_LASTACK.deleter
    def X_MOZ_LASTACK(self) -> None: ...

    @property
    def color(self) -> str: ...
    @color.setter
    def color(self, value: str) -> None: ...
    @color.deleter
    def color(self) -> None: ...

    @property
    def sequence(self) -> int: ...
    @sequence.setter
    def sequence(self, value: int) -> None: ...
    @sequence.deleter
    def sequence(self) -> None: ...

    @property
    def categories(self) -> list[str]: ...
    @categories.setter
    def categories(self, cats: list[str]) -> None: ...
    @categories.deleter
    def categories(self) -> None: ...

    @property
    def rdates(
        self,
    ) -> list[tuple[datetime.date, None] | tuple[datetime.datetime, None] | tuple[datetime.datetime, datetime.datetime]]: ...
    @property
    def exdates(self) -> list[datetime.date | datetime.datetime]: ...
    @property
    def rrules(self) -> list[vRecur]: ...

    @property
    def uid(self) -> str: ...
    @uid.setter
    def uid(self, value: str) -> None: ...
    @uid.deleter
    def uid(self) -> None: ...

class Todo(Component):
    name: ClassVar[Literal["VTODO"]]

    @property
    def DTSTART(self) -> datetime.datetime | datetime.date | None: ...
    @DTSTART.setter
    def DTSTART(self, value: datetime.datetime | datetime.date | None) -> None: ...
    @DTSTART.deleter
    def DTSTART(self) -> None: ...

    @property
    def DUE(self) -> datetime.datetime | datetime.date | None: ...
    @DUE.setter
    def DUE(self, value: datetime.datetime | datetime.date | None) -> None: ...
    @DUE.deleter
    def DUE(self) -> None: ...

    @property
    def DURATION(self) -> datetime.timedelta | None: ...
    @DURATION.setter
    def DURATION(self, value: datetime.timedelta | None) -> None: ...
    @DURATION.deleter
    def DURATION(self) -> None: ...

    @property
    def start(self) -> datetime.datetime | datetime.date: ...
    @start.setter
    def start(self, value: datetime.datetime | datetime.date | None) -> None: ...

    @property
    def end(self) -> datetime.datetime | datetime.date: ...
    @end.setter
    def end(self, value: datetime.datetime | datetime.date | None) -> None: ...

    @property
    def duration(self) -> datetime.timedelta: ...

    @property
    def X_MOZ_SNOOZE_TIME(self) -> datetime.datetime | None: ...
    @X_MOZ_SNOOZE_TIME.setter
    def X_MOZ_SNOOZE_TIME(self, value: datetime.datetime) -> None: ...
    @X_MOZ_SNOOZE_TIME.deleter
    def X_MOZ_SNOOZE_TIME(self) -> None: ...

    @property
    def X_MOZ_LASTACK(self) -> datetime.datetime | None: ...
    @X_MOZ_LASTACK.setter
    def X_MOZ_LASTACK(self, value: datetime.datetime) -> None: ...
    @X_MOZ_LASTACK.deleter
    def X_MOZ_LASTACK(self) -> None: ...

    @property
    def alarms(self) -> Alarms: ...

    @property
    def color(self) -> str: ...
    @color.setter
    def color(self, value: str) -> None: ...
    @color.deleter
    def color(self) -> None: ...

    @property
    def sequence(self) -> int: ...
    @sequence.setter
    def sequence(self, value: int) -> None: ...
    @sequence.deleter
    def sequence(self) -> None: ...

    @property
    def categories(self) -> list[str]: ...
    @categories.setter
    def categories(self, cats: list[str]) -> None: ...
    @categories.deleter
    def categories(self) -> None: ...

    @property
    def rdates(
        self,
    ) -> list[tuple[datetime.date, None] | tuple[datetime.datetime, None] | tuple[datetime.datetime, datetime.datetime]]: ...
    @property
    def exdates(self) -> list[datetime.date | datetime.datetime]: ...
    @property
    def rrules(self) -> list[vRecur]: ...

    @property
    def uid(self) -> str: ...
    @uid.setter
    def uid(self, value: str) -> None: ...
    @uid.deleter
    def uid(self) -> None: ...

class Journal(Component):
    name: ClassVar[Literal["VJOURNAL"]]

    @property
    def DTSTART(self) -> datetime.date | datetime.datetime | None: ...
    @DTSTART.setter
    def DTSTART(self, value: datetime.date | datetime.datetime | None) -> None: ...
    @DTSTART.deleter
    def DTSTART(self) -> None: ...

    @property
    def start(self) -> datetime.date | datetime.datetime: ...
    @start.setter
    def start(self, value: datetime.date | datetime.datetime | None) -> None: ...

    end = start
    @property
    def duration(self) -> datetime.timedelta: ...

    @property
    def color(self) -> str: ...
    @color.setter
    def color(self, value: str) -> None: ...
    @color.deleter
    def color(self) -> None: ...

    @property
    def sequence(self) -> int: ...
    @sequence.setter
    def sequence(self, value: int) -> None: ...
    @sequence.deleter
    def sequence(self) -> None: ...

    @property
    def categories(self) -> list[str]: ...
    @categories.setter
    def categories(self, cats: list[str]) -> None: ...
    @categories.deleter
    def categories(self) -> None: ...

    @property
    def rdates(
        self,
    ) -> list[tuple[datetime.date, None] | tuple[datetime.datetime, None] | tuple[datetime.datetime, datetime.datetime]]: ...
    @property
    def exdates(self) -> list[datetime.date | datetime.datetime]: ...
    @property
    def rrules(self) -> list[vRecur]: ...

    @property
    def uid(self) -> str: ...
    @uid.setter
    def uid(self, value: str) -> None: ...
    @uid.deleter
    def uid(self) -> None: ...

class FreeBusy(Component):
    name: ClassVar[Literal["VFREEBUSY"]]

    @property
    def uid(self) -> str: ...
    @uid.setter
    def uid(self, value: str) -> None: ...
    @uid.deleter
    def uid(self) -> None: ...

class Timezone(Component):
    subcomponents: list[TimezoneStandard | TimezoneDaylight]
    name: ClassVar[Literal["VTIMEZONE"]]
    @classmethod
    def example(cls, name: str = "pacific_fiji") -> Calendar: ...
    def to_tz(self, tzp: TZP = ..., lookup_tzid: bool = True) -> datetime.tzinfo: ...
    @property
    def tz_name(self) -> str: ...
    def get_transitions(self) -> tuple[list[datetime.datetime], list[tuple[datetime.timedelta, datetime.timedelta, str]]]: ...
    @classmethod
    def from_tzinfo(
        cls, timezone: datetime.tzinfo, tzid: str | None = None, first_date: datetime.date = ..., last_date: datetime.date = ...
    ) -> Self: ...
    @classmethod
    def from_tzid(cls, tzid: str, tzp: TZP = ..., first_date: datetime.date = ..., last_date: datetime.date = ...) -> Self: ...
    @property
    def standard(self) -> list[TimezoneStandard]: ...
    @property
    def daylight(self) -> list[TimezoneDaylight]: ...

class TimezoneStandard(Component):
    name: ClassVar[Literal["STANDARD"]]

    @property
    def DTSTART(self) -> datetime.date | datetime.datetime | None: ...
    @DTSTART.setter
    def DTSTART(self, value: datetime.date | datetime.datetime | None) -> None: ...
    @DTSTART.deleter
    def DTSTART(self) -> None: ...

    @property
    def TZOFFSETTO(self) -> datetime.timedelta | None: ...
    @TZOFFSETTO.setter
    def TZOFFSETTO(self, value: datetime.timedelta | None) -> None: ...
    @TZOFFSETTO.deleter
    def TZOFFSETTO(self) -> None: ...

    @property
    def TZOFFSETFROM(self) -> datetime.timedelta | None: ...
    @TZOFFSETFROM.setter
    def TZOFFSETFROM(self, value: datetime.timedelta | None) -> None: ...
    @TZOFFSETFROM.deleter
    def TZOFFSETFROM(self) -> None: ...

    @property
    def rdates(
        self,
    ) -> list[tuple[datetime.date, None] | tuple[datetime.datetime, None] | tuple[datetime.datetime, datetime.datetime]]: ...
    @property
    def exdates(self) -> list[datetime.date | datetime.datetime]: ...
    @property
    def rrules(self) -> list[vRecur]: ...

class TimezoneDaylight(Component):
    name: ClassVar[Literal["DAYLIGHT"]]

    @property
    def DTSTART(self) -> datetime.date | datetime.datetime | None: ...
    @DTSTART.setter
    def DTSTART(self, value: datetime.date | datetime.datetime | None) -> None: ...
    @DTSTART.deleter
    def DTSTART(self) -> None: ...

    @property
    def TZOFFSETTO(self) -> datetime.timedelta | None: ...
    @TZOFFSETTO.setter
    def TZOFFSETTO(self, value: datetime.timedelta | None) -> None: ...
    @TZOFFSETTO.deleter
    def TZOFFSETTO(self) -> None: ...

    @property
    def TZOFFSETFROM(self) -> datetime.timedelta | None: ...
    @TZOFFSETFROM.setter
    def TZOFFSETFROM(self, value: datetime.timedelta | None) -> None: ...
    @TZOFFSETFROM.deleter
    def TZOFFSETFROM(self) -> None: ...

    @property
    def rdates(
        self,
    ) -> list[tuple[datetime.date, None] | tuple[datetime.datetime, None] | tuple[datetime.datetime, datetime.datetime]]: ...
    @property
    def exdates(self) -> list[datetime.date | datetime.datetime]: ...
    @property
    def rrules(self) -> list[vRecur]: ...

class Alarm(Component):
    name: ClassVar[Literal["VALARM"]]

    @property
    def REPEAT(self) -> int: ...
    @REPEAT.setter
    def REPEAT(self, value: int) -> None: ...
    @REPEAT.deleter
    def REPEAT(self) -> None: ...

    @property
    def DURATION(self) -> datetime.timedelta | None: ...
    @DURATION.setter
    def DURATION(self, value: datetime.timedelta | None) -> None: ...
    @DURATION.deleter
    def DURATION(self) -> None: ...

    @property
    def ACKNOWLEDGED(self) -> datetime.datetime | None: ...
    @ACKNOWLEDGED.setter
    def ACKNOWLEDGED(self, value: datetime.datetime | None) -> None: ...
    @ACKNOWLEDGED.deleter
    def ACKNOWLEDGED(self) -> None: ...

    @property
    def TRIGGER(self) -> datetime.timedelta | datetime.datetime | None: ...
    @TRIGGER.setter
    def TRIGGER(self, value: datetime.timedelta | datetime.datetime | None) -> None: ...
    @TRIGGER.deleter
    def TRIGGER(self) -> None: ...

    @property
    def TRIGGER_RELATED(self) -> Literal["START", "END"]: ...
    @TRIGGER_RELATED.setter
    def TRIGGER_RELATED(self, value: Literal["START", "END"]) -> None: ...

    class Triggers(NamedTuple):
        start: tuple[datetime.timedelta, ...]
        end: tuple[datetime.timedelta, ...]
        absolute: tuple[datetime.datetime, ...]

    @property
    def triggers(self) -> Alarm.Triggers: ...

    @property
    def uid(self) -> str: ...
    @uid.setter
    def uid(self, value: str) -> None: ...
    @uid.deleter
    def uid(self) -> None: ...

class Calendar(Component):
    name: ClassVar[Literal["VCALENDAR"]]
    @classmethod
    def example(cls, name: str = "example") -> Calendar: ...
    @property
    def freebusy(self) -> list[FreeBusy]: ...
    @property
    def events(self) -> list[Event]: ...
    @property
    def todos(self) -> list[Todo]: ...
    def get_used_tzids(self) -> set[str]: ...
    def get_missing_tzids(self) -> set[str]: ...
    @property
    def timezones(self) -> list[Timezone]: ...
    def add_missing_timezones(self, first_date: datetime.date = ..., last_date: datetime.date = ...) -> None: ...

    @property
    def calendar_name(self) -> str | None: ...
    @calendar_name.setter
    def calendar_name(self, value: str) -> None: ...
    @calendar_name.deleter
    def calendar_name(self) -> None: ...

    @property
    def description(self) -> str | None: ...
    @description.setter
    def description(self, value: str) -> None: ...
    @description.deleter
    def description(self) -> None: ...

    @property
    def color(self) -> str: ...
    @color.setter
    def color(self, value: str) -> None: ...
    @color.deleter
    def color(self) -> None: ...

    @property
    def categories(self) -> list[str]: ...
    @categories.setter
    def categories(self, cats: list[str]) -> None: ...
    @categories.deleter
    def categories(self) -> None: ...

    @property
    def uid(self) -> str: ...
    @uid.setter
    def uid(self, value: str) -> None: ...
    @uid.deleter
    def uid(self) -> None: ...

types_factory: Final[TypesFactory]
component_factory: Final[ComponentFactory]
