from flask_wtf import FlaskForm
from flask_login import current_user
from wtforms import StringField, PasswordField, BooleanField, HiddenField, SubmitField, IntegerField, DateField
from wtforms.validators import DataRequired, EqualTo, ValidationError, NumberRange
from config import CURRENCY, DECIMAL, THOUSANDS
import bcrypt
import re
from flask_babel import lazy_gettext
from app import userDao


class LoginForm(FlaskForm):
    username = StringField("username", validators=[DataRequired()])
    password = PasswordField("password", validators=[DataRequired()])
    remember_me = BooleanField("remember_me", default=False)

    def validate_username(self, field: StringField):
        if not userDao.user_exists(self.username.data):
            raise ValidationError(lazy_gettext("User doesn't exist"))


class TableEditForm(FlaskForm):
    update = HiddenField("update", default="insert")
    art_num = StringField("art_num", validators=[DataRequired()])
    kat = StringField("kat", validators=[DataRequired()])
    count = IntegerField("count", validators=[DataRequired(
        message=lazy_gettext("This field is required as must be a number.")),
                                              NumberRange(min=0, message=lazy_gettext("Number below zero"))])
    price = StringField("price", validators=[DataRequired()])
    submit_edit = SubmitField(lazy_gettext("Insert"))

    def validate_price(self, field: StringField):
        sub = str(field.data).split(DECIMAL, 1)[1].replace(CURRENCY, "")
        if len(sub) is not 2:
            raise ValidationError(lazy_gettext("Too many or too few decimal places"))
        try:
            int(sub)
        except ValueError:
            ValidationError(lazy_gettext("Decimal place not numbers"))
        new_data = re.sub("[0123456789{}{}{} ]".format(CURRENCY, DECIMAL, THOUSANDS), "", field.data)
        if new_data is not "":
            raise ValidationError(lazy_gettext("Invalid price."))


class ChangeNameForm(FlaskForm):
    new_name = StringField("new_name", validators=[DataRequired()])
    submit_name = SubmitField(lazy_gettext("Update"))


class ChangePasswordForm(FlaskForm):
    old_password = PasswordField("old_password", validators=[DataRequired()])
    new_password = PasswordField("new_password", validators=[DataRequired()])
    repeat_new_password = PasswordField("repeat_new_password",
                                        validators=[DataRequired(),
                                                    EqualTo("new_password",
                                                    message=lazy_gettext("Passwords must match."))])
    submit_pw = SubmitField(lazy_gettext("Update"))

    def validate_old_password(self, field):
        old_hash = current_user.pw_hash
        new_hash = bcrypt.checkpw(field.data, old_hash)
        if not new_hash:
            raise ValidationError(lazy_gettext("Password wrong."))


class NewTableForm(FlaskForm):
    name = StringField("name", validators=[DataRequired()])
    submit = SubmitField(lazy_gettext("Create"))


class PrintForm(FlaskForm):
    date = DateField("date", [DataRequired()], "%d.%m.%Y")
    headline = StringField("headline", [DataRequired()])
    submit_print = SubmitField(lazy_gettext("Create"))
