import copy
from datetime import datetime

from jsonschema import Draft4Validator, FormatChecker, validators
from jsonschema.compat import str_types

from .common import TIME_FORMAT
from .compat import iteritems


@FormatChecker.cls_checks("readable_time", raises=ValueError)
def check_datetime(instance):
    if not isinstance(instance, str_types):
        return True
    return datetime.strptime(instance, TIME_FORMAT)


@FormatChecker.cls_checks("url")
def simple_check_url(url):
    b1 = ":"
    b2 = "://"
    if isinstance(url, bytes):
        b1 = b":"
        b2 = b"://"
    if len(url) > 0:
        t = url.find(b1)
        if t > 0 and url[t : t + 3] == b2:
            return True
    return False


ERROR_TYPES = set(["HTTP", "SSL", "RULE", "SERVER", "DNS"])


@FormatChecker.cls_checks("error_reason")
def check_error_reason(err_string):
    c = err_string.split(" ")
    if len(c) != 2:
        return False

    return c[0] in ERROR_TYPES and c[1].lstrip("-").isdigit()


def extend_with_default(validator_class):
    validate_properties = validator_class.VALIDATORS["properties"]

    def set_defaults(validator, properties, instance, schema):
        for property, subschema in iteritems(properties):
            if "default" in subschema:
                o = subschema["default"]
                if callable(o):
                    o = o()
                instance.setdefault(property, o)

        for error in validate_properties(validator, properties, instance, schema):
            yield error

    return validators.extend(validator_class, {"properties": set_defaults})


DefaultPropertyDraft4Validator = extend_with_default(Draft4Validator)

EXTRA_TYPES = {"datetime": datetime, "bytes": bytes}


def create_validator(schema, extra_types=None, format_checker=None):
    types = copy.deepcopy(EXTRA_TYPES)
    if extra_types:
        types.update(extra_types)
    if format_checker is None:
        format_checker = FormatChecker()

    return DefaultPropertyDraft4Validator(
        schema, types=types, format_checker=format_checker
    )
