"""Utility functions for icalendar."""

from __future__ import annotations

import random
from datetime import date, datetime, tzinfo
from string import ascii_letters, digits
from warnings import warn

from icalendar.parser_tools import to_unicode

from .error import WillBeRemovedInVersion7


class UIDGenerator:
    """Use this only if you're too lazy to create real UUIDs.
    
    .. deprecated:: 6.2.1

        Use the Python standard library's :func:`uuid.uuid4` instead.
    """

    chars = list(ascii_letters + digits)

    @staticmethod
    def rnd_string(length=16) -> str:
        """Generates a string with random characters of length.

         .. deprecated:: 6.2.1

             Use the Python standard library's :func:`uuid.uuid4` instead.
        """
        warn(
            "Use https://docs.python.org/3/library/uuid.html#uuid.uuid4 instead.",
            WillBeRemovedInVersion7,
            stacklevel=1
        )
        return "".join([random.choice(UIDGenerator.chars) for _ in range(length)])

    @staticmethod
    def uid(host_name="example.com", unique=""):
        """Generates a unique ID consisting of ``datetime-uniquevalue@host``.

        For example:
            
            .. code-block:: text

                20050105T225746Z-HKtJMqUgdO0jDUwm@example.com
        
        .. deprecated:: 6.2.1

            Use the Python standard library's :func:`uuid.uuid5` instead.
        """
        from icalendar.prop import vDatetime, vText
        warn(
            "Use https://docs.python.org/3/library/uuid.html#uuid.uuid5 instead.",
            WillBeRemovedInVersion7,
            stacklevel=1
        )

        host_name = to_unicode(host_name)
        unique = unique or UIDGenerator.rnd_string()
        today = to_unicode(vDatetime(datetime.today()).to_ical())
        return vText(f"{today}-{unique}@{host_name}")


def is_date(dt: date) -> bool:
    """Whether this is a date and not a datetime."""
    return isinstance(dt, date) and not isinstance(dt, datetime)


def is_datetime(dt: date) -> bool:
    """Whether this is a date and not a datetime."""
    return isinstance(dt, datetime)


def to_datetime(dt: date) -> datetime:
    """Make sure we have a datetime, not a date."""
    if is_date(dt):
        return datetime(dt.year, dt.month, dt.day)  # noqa: DTZ001
    return dt


def is_pytz(tz: tzinfo):
    """Whether the timezone requires localize() and normalize()."""
    return hasattr(tz, "localize")


def is_pytz_dt(dt: date):
    """Whether the time requires localize() and normalize()."""
    return is_datetime(dt) and is_pytz(dt.tzinfo)


def normalize_pytz(dt: date):
    """We have to normalize the time after a calculation if we use pytz.

    pytz requires this function to be used in order to correctly calculate the
    timezone's offset after calculations.
    """
    if is_pytz_dt(dt):
        return dt.tzinfo.normalize(dt)
    return dt


__all__ = [
    "UIDGenerator",
    "is_date",
    "is_datetime",
    "to_datetime",
    "is_pytz",
    "is_pytz_dt",
    "normalize_pytz",
]
