from flask_wtf import FlaskForm
from wtforms import StringField, PasswordField, SubmitField, DateField, SelectField
from wtforms.fields.simple import TextAreaField
from wtforms.validators import InputRequired, Length, EqualTo, ValidationError, DataRequired, Regexp
from overflow.models import Utilisateur, Matiere, Post
from flask_login import current_user

"""
LoginForm is a class which takes care of a login attempt

matricule : UNamur id (eid)
mot_de_passe : password of the account
submit: button that sends and verifies the data inputed in the form which is described above
"""


class LoginForm(FlaskForm):
    matricule = StringField('Matricule', validators=[InputRequired(
        message="Veuillez entrer votre identifiant UNamur."), DataRequired("Veuillez entrer votre identifiant UNamur.")], render_kw={"autofocus": True})
    mot_de_passe = PasswordField('Mot de passe', validators=[InputRequired(
        message="Veuillez entrer votre mot de passe."), DataRequired(message="Veuillez entrer votre mot de passe.")])


class RegisterForm(FlaskForm):
    """
    RegisterForm is a class which takes care of a login attempt

    matricule : UNamur id (eid)
    prenom : first name of the person wishing to create a new account
    nom : name of the person wishing to create a new account
    anniversaire: birth date of the person wishing to create a new account
    email: email of the person wishing to create a new account (no restriction of what's after the @)
    mot_de_passe : password of the account
    mot_de_passe2 : password of the account (for Confirmation)
    submit: it's the button to send and verify the data entered in the form which is described above
    """
    # Form to register/sign up/ create an account  in the "app"
    # les eids font tous 7 caractères?
    matricule = StringField('Matricule', validators=[
                            InputRequired(message="Veuillez entrer votre UNamur eid."), DataRequired(message="Veuillez entrer votre UNamur eid.")], render_kw={"autofocus": True})

    prenom = StringField('Prénom', validators=[InputRequired(message="Veuillez entrer votre pénom."), DataRequired(message="Veuillez entrer votre pénom."),
                                               Length(min=2, message="Le prénom doit contenir au moins 2 caractères.")])

    nom = StringField('Nom', validators=[InputRequired(message="Veuillez entrer votre nom."), DataRequired(message="Veuillez entrer votre nom."),
                                         Length(min=2, message="Le prénom doit contenir au moins 2 caractères.")])

    email = StringField('Adresse email', validators=[InputRequired(message="Veuillez entrer votre adresse mail."), DataRequired(message="Veuillez entrer votre adresse mail."),
                                                     Regexp("^[a-zA-Z0-9.!#$%&'*+/=?^_`{|}~-]+@[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?(?:\.[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?)*$", message="Veuillez entrer une adresse email valide")])
    anniversaire = DateField('Date de naissance', validators=[InputRequired(
        message="Veuillez entrer votre date d'anniversaire.")])

    mot_de_passe = PasswordField('Mot de passe',
                                 validators=[InputRequired(message="Veuillez entrer votre mot de passe."), DataRequired(message="Veuillez entrer votre mot de passe."),
                                             Length(min=3, message="Le mot de passe doit contenir au moins contenir 3 caractères.")])

    mot_de_passe2 = PasswordField('Confirmation du mot de passe',
                                  validators=[InputRequired(message="Veuillez entrer une seconde fois votre mot de passe."), DataRequired(message="Veuillez entrer une seconde fois votre mot de passe."),
                                              Length(min=3),
                                              EqualTo('mot_de_passe', message="Les deux mots de passes ne correspondent pas!")])

    submit = SubmitField('Register')

    # Checks whether the chosen eid is already taken
    def validate_eid(self, field):
        if field.data in [x.matricule for x in Utilisateur.query.all()]:
            raise ValidationError('Eid déjà utilisé par un autre compte.')


class PasswordForm (FlaskForm):

    old_password = PasswordField(label=('Ancien mot de passe:'),
                                 validators=[InputRequired(message="Cette entrée doit être complétée."), DataRequired(message="Cette entrée doit être complétée."), Length(min=2, message='Password should be at least %(min)d characters long')], render_kw={"autofocus": True})

    password = PasswordField(label=('Nouveau mot de passe:'),
                             validators=[InputRequired(message="Cette entrée doit être complétée."), DataRequired(message="Cette entrée doit être complétée."), Length(min=2, message='Password should be at least %(min)d characters long')])

    confirm_password = PasswordField(label=('Confirmer le mot de passe:'), validators=[InputRequired(),
                                                                                       EqualTo('password', message='Both password fields must be equal!')])

    def validate_old_password(self, old_password):
        if not current_user.check_password(self.old_password.data):
            raise ValidationError(
                'Votre ancien mot de passe n\'est pas correct.')

    def validate_password(self, password):
        if self.old_password.data == self.password.data:
            raise ValidationError(
                'Votre nouveau mot de passe n\'est pas différent de l\'ancien.')


class NewAndEditPostForm(FlaskForm):
    """
    NewAndEditPostForm is a class form for the creation and modification of post

    titre : it's the title of the post (STR)
    description : it's the description of the post (STR)
    matricule : it's the ID of the post

    """

    titre = StringField('Titre du poste :', validators=[InputRequired(message="Cette entrée doit être complétée."), DataRequired(message="Cette entrée doit être complétée."),
                                                        Length(min=5, max=200, message="Le titre doit contenir au moins 5 caractère.")], render_kw={"autofocus": True})

    description = TextAreaField('Description du post : ', validators=[InputRequired(message="Cette entrée doit être complétée."), DataRequired(message="Cette entrée doit être complétée."),
                                                                      Length(min=5, max=500, message="Le titre doit contenir au moins 5 caractère.")])

    matricule = SelectField('Matricule du cours : ', choices=[
                            cours.matricule for cours in Matiere.query.all()], validators=[InputRequired(message="Cette entrée doit être complétée.")])

    # this is a method for verifying if the post already exists when you edit a post

    def v_titre(self, field, id_post):
        post = Post.query.filter_by(titre=field.data)
        if post.count() > 0 and post.all()[0].id != id_post:
            raise ValidationError(
                "le Post existe déjà, veuillez revenir à la page précédente et mettre un titre valide")
        return True


class AnswerForm(FlaskForm):
    """
    Class form for the creation and modification of answer

    titre : it's the title of the post (STR)
    description : it's the description of the post (STR)
    matricule : it's the ID of the post

    """

    contenu = StringField('Votre réponse :', validators=[Length(min=5, message="La réponse doit contenir au moins 5 caractères."), InputRequired(
        message="Cette entrée doit être complétée."), DataRequired(message="Cette entrée doit être complétée.")], render_kw={"autofocus": True})
