import re

from django.forms import (
    CharField,
    DateTimeField,
    RadioSelect,
    TypedChoiceField,
    ValidationError,
)
from django.core.validators import RegexValidator
from django.utils.translation import gettext_lazy as _

from ..core.utils import parse_iso8601_string


class IsoDateTimeField(DateTimeField):
    input_formats = ["iso8601"]

    def prepare_value(self, value):
        try:
            return value.isoformat()
        except AttributeError:
            return value

    def to_python(self, value):
        """
        Validates that the input can be converted to a datetime. Returns a
        Python datetime.datetime object.
        """
        if value in self.empty_values:
            return None

        try:
            return parse_iso8601_string(value)
        except ValueError:
            raise ValidationError(self.error_messages["invalid"], code="invalid")


def ColorField(**kwargs):
    return CharField(
        validators=[
            RegexValidator(
                r"^#[0-9a-f]{6}$",
                flags=re.IGNORECASE,
                message=_(
                    "Value must be a 7-character string specifying an RGB color "
                    "in a hexadecimal format."
                ),
            )
        ],
        **kwargs
    )


class YesNoSwitchBase(TypedChoiceField):
    def prepare_value(self, value):
        """normalize bools to binary 1/0 so field works on them too"""
        if value in (True, "True", "true", 1, "1"):
            return 1
        return 0

    def clean(self, value):
        return self.prepare_value(value)


def YesNoSwitch(**kwargs):
    yes_label = kwargs.pop("yes_label", _("Yes"))
    no_label = kwargs.pop("no_label", _("No"))

    return YesNoSwitchBase(
        coerce=int,
        choices=[(1, yes_label), (0, no_label)],
        widget=RadioSelect(attrs={"class": "yesno-switch"}),
        **kwargs
    )