from flask_wtf import FlaskForm
from wtforms import StringField, PasswordField, BooleanField, TextAreaField, SubmitField, DecimalField, SelectField, RadioField
from wtforms.fields.datetime import DateField
from wtforms.fields.simple import EmailField
from wtforms.validators import InputRequired, Optional, Email, EqualTo
from flask_wtf.file import FileField  # Cuz' wtforms' FileField is shitty
import app.utils.validators as vd


class RegistrationForm(FlaskForm):
    username = StringField(
        'Pseudonyme',
        description='Ce nom est définitif !',
        validators=[InputRequired(), vd.name.valid, vd.name.available])

    email = EmailField(
        'Adresse Email',
        validators=[
            InputRequired(),
            Email(message="Adresse email invalide."),
            vd.email
        ])

    password = PasswordField(
        'Mot de passe',
        validators=[InputRequired(), vd.password.is_strong])

    password2 = PasswordField(
        'Répéter le mot de passe',
        validators=[
            InputRequired(),
            EqualTo('password', message="Les mots de passe doivent être identiques.")
        ])

    guidelines = BooleanField(
        """J'accepte les <a href="#">CGU</a>""",
        validators=[InputRequired()])

    newsletter = BooleanField(
        'Inscription à la newsletter',
        description='Un mail par trimestre environ, pour être prévenu des concours, évènements et nouveautés.')

    submit = SubmitField("S'inscrire")


class UpdateAccountBaseForm(FlaskForm):
    avatar = FileField(
        'Avatar',
        validators=[Optional(), vd.file.is_image, vd.file.avatar_size])

    email = EmailField(
        'Adresse email',
        validators=[
            Optional(),
            Email(message="Addresse email invalide."),
            vd.email,
            # For users: vd.password.old_password is added dynamically
        ])

    password = PasswordField(
        'Nouveau mot de passe',
        description="L'ancien mot de passe ne pourra pas être récupéré !",
        validators=[
            Optional(),
            vd.password.is_strong,
            # For users: vd.password.old_password is added dynamically
        ])

    birthday = DateField(
        'Anniversaire',
        validators=[Optional()])

    signature = TextAreaField(
        'Signature',
        validators=[Optional()])

    biography = TextAreaField(
        'Présentation',
        validators=[Optional()])

    title = SelectField(
        'Titre',
        coerce=int,
        validators=[
            Optional(),
            # For users: vd.own_title (admins can assign any title!)
        ])

    newsletter = BooleanField(
        'Inscription à la newsletter',
        description='Un mail par trimestre environ, pour être prévenu des concours, évènements et nouveautés.')

    submit = SubmitField('Mettre à jour')


class UpdateAccountForm(UpdateAccountBaseForm):
    password2 = PasswordField(
        'Répéter le mot de passe',
        validators=[
            Optional(),
            EqualTo('password', message="Les mots de passe doivent être identiques.")
        ])

    old_password = PasswordField(
        'Mot de passe actuel',
        validators=[Optional()])

    theme = RadioField(
        'Thème du site',
        choices=[
            ('default_theme',    'Planète Casio v5'),
            ('FK_dark_theme',    'Thème sombre (FlamingKite)'),
            ('Tituya_v43_theme', 'Thème Planète Casio v4 (Tituya)'),
        ])


class AdminUpdateAccountForm(UpdateAccountBaseForm):
    username = StringField(
        'Pseudonyme',
        validators=[Optional(), vd.name.valid, vd.name.available])

    email_confirmed = BooleanField(
        "Confirmer l'email",
        description="Si décoché, l'utilisateur devra demander explicitement un"
            " email de validation, ou faire valider son adresse email par un"
            " administrateur.")

    xp = DecimalField(
        'XP',
        validators=[Optional()])


class DeleteAccountBaseForm(FlaskForm):
    transfer = BooleanField(
        'Conserver les posts sous forme anonyme',
        description="Aucune information personnelle n'est conservée ; seul le texte de posts reste. Cela permet de garder un historique fidèle des échanges.",
        default=True)

    delete = BooleanField(
        'Confirmer la suppression',
        validators=[InputRequired()],
        description='Attention, cette opération est irréversible !')

    submit = SubmitField('Supprimer le compte')


class DeleteAccountForm(DeleteAccountBaseForm):
    old_password = PasswordField(
        'Mot de passe',
        validators=[InputRequired(), vd.password.old_password])


class AdminDeleteAccountForm(DeleteAccountBaseForm):
    pass


class AskResetPasswordForm(FlaskForm):
    email = EmailField(
        'Adresse email',
        validators=[Optional(), Email(message="Addresse email invalide.")])

    submit = SubmitField('Valider')


class ResetPasswordForm(FlaskForm):
    password = PasswordField(
        'Mot de passe',
        validators=[Optional(), vd.password.is_strong])

    password2 = PasswordField(
        'Répéter le mot de passe',
        validators=[
            Optional(),
            EqualTo('password', message="Les mots de passe doivent être identiques.")
        ])

    submit = SubmitField('Valider')


class AdminAccountEditTrophyForm(FlaskForm):
    # Boolean inputs are generated on-the-fly from trophy list
    submit = SubmitField('Modifier')


class AdminAccountEditGroupForm(FlaskForm):
    # Boolean inputs are generated on-the-fly from group list
    submit = SubmitField('Modifier')
