import re
from datetime import date

from rest_framework.exceptions import ValidationError


class NumberValidator(object):

    @staticmethod
    def validate(password):
        if not re.findall('\\d', password):
            raise ValidationError("The password must contain at least 1 digit, 0-9.")


class SizeValidator(object):

    @staticmethod
    def validate(password):
        if len(password) < 8:
            raise ValidationError("The password size must be more than 8 characters")


class UppercaseValidator(object):

    @staticmethod
    def validate(password):
        if not re.findall('[A-Z]', password):
            raise ValidationError("The password must contain at least 1 uppercase letter, A-Z.")


class LowercaseValidator(object):

    @staticmethod
    def validate(password):
        if not re.findall('[a-z]', password):
            raise ValidationError("The password must contain at least 1 lowercase letter, a-z.")


class OnlyCharNumericValidator:
    """Validator only numeric and latin alphabet."""
    @staticmethod
    def validate(data: str, *, field_name: str = 'username'):
        if not re.findall('^[a-zA-Z0-9]*$', data):
            raise ValidationError(f'The {field_name} must be contain only latin alphabet and digit, 0-9')


def timezone_validation(data):
    """
    Validate timezone field
    :param data: serializer post data
    :return: data if timezone field exists in data dict  and validation errors in other cases
    """
    try:
        data['timezone']

    except KeyError:
        raise ValidationError("Timezone is required")


def password_validation(data):
    """
    Validate password for UppercaseValidator,LowercaseValidator,NumberValidator
    :param data: serializer post data
    :return: data if OK and validation errors in other cases
    """
    try:
        password = data['user']['password']
        UppercaseValidator.validate(password)
        LowercaseValidator.validate(password)
        NumberValidator.validate(password)
        SizeValidator.validate(password)
    except KeyError:
        return data


def validate_expire_date(data):
    """
    Validate field expire_date
    :param data: data
    :return: if expire_date in the past return validation error, else return data.Today's date also cannot be specified
    """
    try:
        expire_date = data["expire_date"]
        if expire_date and expire_date <= date.today():
            raise ValidationError("The user's blocking date should be in the future")
        return data
    except KeyError:
        return data
