import os

from flask import Flask, render_template
from flask_bootstrap import Bootstrap
from flask_wtf import FlaskForm
from flask_wtf.file import FileRequired, FileAllowed
from wtforms.validators import DataRequired
from wtforms.fields import StringField, IntegerField, FloatField, SubmitField, FileField
from wtforms import widgets, SelectMultipleField
from collections import namedtuple
import logging

logger = logging.getLogger(__name__)
logger.setLevel(logging.DEBUG)

app = Flask(__name__)

shared_folder = os.getenv("SHARED_FOLDER_PATH")

Parameters = namedtuple("Parameters", ["training_data_filename",
                                       "validation_data_filename",
                                       "test_data_filename",
                                       "embeddings",
                                       "epochs",
                                       "learning_rate",
                                       "batch_size",
                                       "model_filename"]
                        )

parameters = Parameters(training_data_filename=None,
                        validation_data_filename=None,
                        test_data_filename=None,
                        embeddings=["wikipedia"],
                        epochs=20,
                        learning_rate=0.1,
                        batch_size=64,
                        model_filename="my-ner-model")


class MultiCheckboxField(SelectMultipleField):
    widget = widgets.ListWidget(prefix_label=False)
    option_widget = widgets.CheckboxInput()


class TrainerInputForm(FlaskForm):
    TrainingDataFilename = FileField("Training data", validators=[FileRequired(),
                                                                  FileAllowed(['txt'], 'Text only!')])
    ValidationDataFilename = FileField("Validation data", validators=[FileRequired(),
                                                                      FileAllowed(['txt'], 'Text only!')])
    TestDataFilename = FileField("Test data", validators=[FileRequired(),
                                                          FileAllowed(['txt'], 'Text only!')])

    string_of_files = "wikipedia,character,crawl,bpe,flair,bert"
    list_of_files = string_of_files.split(",")
    files = [(x, x) for x in list_of_files]
    Embeddings = MultiCheckboxField('Embeddings', choices=[
        ("wikipedia", "FastText embeddings"),
        ("character", "Character embeddings"),
        ("crawl", "CommonCrawl FastText embeddings"),
        ("flair", "Flair embeddings"),
        ("bpe", "German BPE Embeddings"),
        ("bert", "Multilingual BERT embeddings"),
    ], render_kw={'style': 'border: 0px'})

    EmptyField = StringField("", default="", render_kw={'style': 'margin-top: 80px; visibility: hidden'})
    Epochs = IntegerField('Epochs', validators=[DataRequired()], default=parameters.epochs)
    LearningRate = FloatField('Learning rate', validators=[DataRequired()], default=parameters.learning_rate)
    BatchSize = IntegerField('BatchSize', validators=[DataRequired()], default=parameters.batch_size)
    ModelFilename = StringField('ModelFilename', validators=[DataRequired()], default=parameters.model_filename)
    Save = SubmitField('Save Parameters')


@app.route('/', methods=['GET', 'POST'])
def training_input():
    global parameters
    form = TrainerInputForm()

    if form.Save.data and form.validate_on_submit():
        logger.debug("Processing user inputs")
        parameters = Parameters(
            training_data_filename=form.TrainingDataFilename,
            validation_data_filename=form.ValidationDataFilename,
            test_data_filename=form.TestDataFilename,
            embeddings=form.Embeddings.data,
            epochs=form.Epochs.data,
            learning_rate=form.LearningRate.data,
            batch_size=form.BatchSize.data,
            model_filename=form.ModelFilename.data)

        logger.debug(f"User inputs taken: {parameters}")
        parameters.training_data_filename.data.save(
            f"{shared_folder}/{parameters.training_data_filename.data.filename}")
        parameters.validation_data_filename.data.save(
            f"{shared_folder}/{parameters.validation_data_filename.data.filename}")
        parameters.test_data_filename.data.save(f"{shared_folder}/{parameters.test_data_filename.data.filename}")

        return render_template("display_prediction.html")

    return render_template("index.html", example_form=form)


def get_parameters():
    logger.debug(f"return training parameters: {parameters}")
    return parameters


def app_run():
    app.secret_key = "ner-ner_trainingconfig"
    bootstrap = Bootstrap(app)
    app.run(host="0.0.0.0", port=8062)
    # app.run()
