from typing import Callable

from jschon.exceptions import CatalogError
from jschon.json import JSON, JSONCompatible
from jschon.jsonschema import JSONSchema, Result
from jschon.vocabulary import Keyword

__all__ = [
    'FormatKeyword',
    'FormatValidator',
]

FormatValidator = Callable[[JSONCompatible], None]
"""The type of a ``"format"`` keyword validator.

A :class:`~jschon.vocabulary.format.FormatValidator` is a
callable accepting a JSON-compatible Python object as its
only argument. It must raise a :exc:`ValueError` if the
argument is invalid per the applicable format specification.
"""


class FormatKeyword(Keyword):
    key = "format"

    def __init__(self, parentschema: JSONSchema, value: str):
        super().__init__(parentschema, value)

        try:
            self.validator: FormatValidator = parentschema.catalog.get_format_validator(value)
        except CatalogError:
            self.validator = None

    def evaluate(self, instance: JSON, result: Result) -> None:
        result.annotate(self.json.data)
        if self.validator is not None:
            try:
                self.validator(instance.data)
            except ValueError as e:
                result.fail(f'The instance is invalid against the "{self.json.data}" format: {e}')
        else:
            result.noassert()
