from flask_login import current_user
from wtforms.validators import ValidationError
from app.models.users import User, Member
from app.utils.valid_name import valid_name
from app.utils.unicode_names import normalize
from config import V5Config


def name_valid(form, name):
    valid = valid_name(name.data)
    default = "Nom d'utilisateur invalide (erreur interne)"
    msg = {
        "too-short":
            "Le nom d'utilisateur doit faire au moins "
            f"{V5Config.USER_NAME_MINLEN} caractères.",
        "too-long":
            "Le nom d'utilisateur doit faire au plus "
            f"{V5Config.USER_NAME_MAXLEN} caractères.",
        "cant-normalize":
            "Ce nom d'utilisateur contient des caractères interdits. Les "
            "caractères autorisés sont les lettres, lettres accentuées, "
            'chiffres ainsi que "-" (tiret), "." (point), "~" (tilde) et '
            '"_" (underscore).',
        "no-letter":
            "Le nom d'utilisateur doit contenir au moins une lettre.",
        "forbidden":
            "Ce nom d'utilisateur est interdit."
    }
    if valid is not True:
        err = ' '.join(msg.get(code, default) for code in valid)
        raise ValidationError(err)


def name_available(form, name):
    # If the name is invalid, name_valid() will return a meaningful message
    try:
        norm = normalize(name.data)
    except ValueError:
        return

    member = Member.query.filter_by(norm=norm).first()
    if member is not None:
        raise ValidationError("Ce nom d'utilisateur est indisponible.")


def email(form, email):
    member = Member.query.filter_by(email=email.data).first()
    if member is not None:
        raise ValidationError('Adresse email déjà utilisée.')


def password(form, password):
    if len(password.data) != 0 and len(password.data) < 10:
        raise ValidationError('Mot de passe est trop court (10 caractères minimum).')
        # TODO: add more rules >:]


def avatar(form, avatar):
    pass


def old_password(form, field):
    if field.data:
        if not form.old_password.data:
            raise ValidationError('Votre ancien mot de passe est requis pour cette modification.')
        if not current_user.check_password(form.old_password.data):
            raise ValidationError('Mot de passe actuel erroné.')
