from plone import schema  # Also import zope.schema
from plone.namedfile.field import NamedBlobFile
from plone.namedfile.field import NamedBlobImage
from ploneintranet.core import _
from ploneintranet.schema.interfaces import IGooglePlace
from ploneintranet.schema.interfaces import IMultipleFileInput
from ploneintranet.schema.interfaces import IPIEmail
from ploneintranet.schema.interfaces import ITelephone
from zope.interface import classImplementsFirst
from zope.schema.interfaces import WrongContainedType


class WrongContainedFile(WrongContainedType):
    __doc__ = _(
        "One or more of the uploaded files is invalid or has a wrong content type. "
    )


class PIEmail(schema.Email):
    """An email field."""

    def _validate(self, value):
        """We customize this value to allow a default equal to an empty string,
        see:

        - https://github.com/plone/plone.schema/issues/35
        """
        if value:
            super()._validate(value)


classImplementsFirst(PIEmail, IPIEmail)


class GooglePlace(schema.Choice):
    """
    This takes a choice from a list of city or place names as input,
    then renders a link to Google Maps for that city or place name.
    """


classImplementsFirst(GooglePlace, IGooglePlace)


class PIBool(schema.Bool):
    """A boolean with an extra label."""

    def __init__(self, *args, **kwargs):
        self.label_content = kwargs.pop("label_content", None)
        super().__init__(*args, **kwargs)


class Telephone(schema.TextLine):
    """A telephone field."""


classImplementsFirst(Telephone, ITelephone)


class MultipleFileInput(schema.List):
    """A field that takes multiple file inputs.

    It requires to specify the type of file that is expected,
    either NamedBlobFile or NamedBlobImage.
    """

    def __init__(self, **kw):
        if "accept" in kw:
            self.accept = kw.pop("accept")

        self.value_type = kw.pop("value_type", NamedBlobFile)
        if not isinstance(self.value_type, (NamedBlobFile, NamedBlobImage)):
            raise ValueError(
                "The value_type has to either be a NamedBlobFile (the default) "
                "or a NamedBlobImage"
            )
        super().__init__(**kw)

    def _validate(self, value):
        try:
            return super()._validate(value)
        except WrongContainedType as e:
            # Rework the validation error message to suggest that the user
            # might have uploaded a file with an invalid content type
            raise WrongContainedFile(*e.args) from e


classImplementsFirst(MultipleFileInput, IMultipleFileInput)
