from flask_login import current_user
from flask_wtf import FlaskForm
from flask_wtf.file import FileField, FileRequired
from wtforms import (
    PasswordField,
    SelectField,
    StringField,
    SubmitField,
    TextAreaField,
    ValidationError
)
from wtforms.validators import (
    DataRequired,
    Email,
    EqualTo,
    Length,
    Regexp
)
from app.models import User, UserSettingJobStatusMailNotificationLevel
from app.wtforms.validators import FileSize


class UpdateAccountInformationForm(FlaskForm):
    email = StringField(
        'E-Mail',
        validators=[DataRequired(), Length(max=254), Email()]
    )
    username = StringField(
        'Username',
        validators=[
            DataRequired(),
            Length(max=64),
            Regexp(
                User.username_pattern,
                message=(
                    'Usernames must have only letters, numbers, dots or '
                    'underscores'
                )
            )
        ]
    )
    submit = SubmitField()
    
    def __init__(self, user, *args, **kwargs):
        if 'data' not in kwargs:
            kwargs['data'] = user.to_json_serializeable()
        if 'prefix' not in kwargs:
            kwargs['prefix'] = 'update-account-information-form'
        super().__init__(*args, **kwargs)
        self.user = user

    def validate_email(self, field):
        if (field.data != self.user.email
                and User.query.filter_by(email=field.data).first()):
            raise ValidationError('Email already registered')

    def validate_username(self, field):
        if (field.data != self.user.username
                and User.query.filter_by(username=field.data).first()):
            raise ValidationError('Username already in use')


class UpdateProfileInformationForm(FlaskForm):
    full_name = StringField(
        'Full name',
        validators=[Length(max=128)]
    )
    about_me = TextAreaField(
        'About me', 
        validators=[
            Length(max=254)
        ]
    )
    website = StringField(
        'Website',
        validators=[
            Length(max=254)
        ]
    )
    organization = StringField(
        'Organization',
        validators=[
            Length(max=128)
        ]
    )
    location = StringField(
        'Location',
        validators=[
            Length(max=128)
        ]
    )
    submit = SubmitField()

    def __init__(self, user, *args, **kwargs):
        if 'data' not in kwargs:
            kwargs['data'] = user.to_json_serializeable()
        if 'prefix' not in kwargs:
            kwargs['prefix'] = 'update-profile-information-form'
        super().__init__(*args, **kwargs)


class UpdateAvatarForm(FlaskForm):
    avatar = FileField('File', validators=[FileRequired(), FileSize(2)])
    submit = SubmitField()

    def validate_avatar(self, field):
        valid_mimetypes = ['image/jpeg', 'image/png']
        if field.data.mimetype not in valid_mimetypes:
            raise ValidationError('JPEG and PNG files only!')

    def __init__(self, *args, **kwargs):
        if 'prefix' not in kwargs:
            kwargs['prefix'] = 'update-avatar-form'
        super().__init__(*args, **kwargs)


class UpdatePasswordForm(FlaskForm):
    password = PasswordField('Old password', validators=[DataRequired()])
    new_password = PasswordField(
        'New password',
        validators=[
            DataRequired(),
            EqualTo('new_password_2', message='Passwords must match')
        ]
    )
    new_password_2 = PasswordField(
        'New password confirmation',
        validators=[
            DataRequired(),
            EqualTo('new_password', message='Passwords must match')
        ]
    )
    submit = SubmitField()

    def __init__(self, user, *args, **kwargs):
        if 'prefix' not in kwargs:
            kwargs['prefix'] = 'update-password-form'
        super().__init__(*args, **kwargs)
        self.user = user

    def validate_current_password(self, field):
        if not self.user.verify_password(field.data):
            raise ValidationError('Invalid password')


class UpdateNotificationsForm(FlaskForm):
    job_status_mail_notification_level = SelectField(
        'Job status mail notification level',
        choices=[
            (x.name, x.name.capitalize())
            for x in UserSettingJobStatusMailNotificationLevel
        ],
        validators=[DataRequired()]
    )
    submit = SubmitField()

    def __init__(self, user, *args, **kwargs):
        if 'data' not in kwargs:
            kwargs['data'] = user.to_json_serializeable()
        if 'prefix' not in kwargs:
            kwargs['prefix'] = 'update-notifications-form'
        super().__init__(*args, **kwargs)