text: # -*- encoding: utf-8 -*-
  """
  Copyright (c) 2019 - present AppSeed.us
  """
  import json
  import os
  import io
  import sys
  import traceback
  
  import pandas as pd
  import numpy
  import flask
  
  from app.base.db_models.ModelLabels import ModelLabels
  from app.base.db_models.ModelProfile import ModelProfile
  from app.base.db_models.ModelAPIDetails import ModelAPIDetails
  from flask import jsonify, render_template, redirect, request, send_file, make_response, url_for, Response, Flask
  from flask_login import (
      current_user,
      login_required,
      login_user,
      logout_user
  )
  from matplotlib.backends.backend_template import FigureCanvas
  from werkzeug.utils import secure_filename
  
  from app import db, login_manager
  from app.base import blueprint
  from app.base.forms import LoginForm, CreateAccountForm
  from app.base.models import User
  
  from app.base.util import verify_pass
  from mylib.apis.v1.APIHelper import APIHelper
  from mylib.data_manipulation.AdjustDataFrame import create_figure, encode_prediction_data_frame
  from mylib.db_helper.AttributesHelper import get_features, get_labels, get_model_name, encode_testing_features_values, \
      get_api_details
  from mylib.utiles.ProjConstants import ProjConstants
  from mylib.utiles.CVSReader import getcvsheader, reorder_csv_file, improve_data_file
  from mylib.utiles.CVSReader import get_new_headers_list
  from mylib.utiles.CVSReader import improve_data_file
  from mylib.controllers.ModelController import run_model, predict_values_from_model, get_model_status, delet_model
  from mylib.utiles.utilities import listToString
  from mylib.apis.v1.APIsServices import predictvalues
  
  app = Flask(__name__)
  app.config['UPLOAD_FOLDER'] = 'app/data/'
  app.config['DOCS_TEMPLATES_FOLDER'] = 'docs_templates/'
  app.config['OUTPUT_DOCS'] = 'app/base/output_docs/'
  app.config['OUTPUT_PDF_DOCS'] = '/output_docs/'
  root_path = app.root_path
  
  
  @blueprint.route('/')
  def route_default():
      return redirect(url_for('base_blueprint.login'))
  
  
  ## Login & Registration
  
  @blueprint.route('/login', methods=['GET', 'POST'])
  def login():
      login_form = LoginForm(request.form)
      if 'login' in request.form:
          # encode_prediction_data_frame()
          # read form data
          username = request.form['username']
          password = request.form['password']
  
          # Locate user
          user = User.query.filter_by(username=username).first()
  
          # Check the password
          if user and verify_pass(password, user.password):
              login_user(user)
              xx = get_model_status()
              # return redirect(url_for('base_blueprint.route_default'))
              return redirect(url_for('base_blueprint.showdashboard', segment=''))
  
          # Something (user or pass) is not ok
          return render_template('accounts/login.html', msg='Wrong user or password', form=login_form)
  
      if not current_user.is_authenticated:
          return render_template('accounts/login.html',
                                 form=login_form)
      # return redirect(url_for('home_blueprint.index'))
      return redirect(url_for('base_blueprint.showdashboard'))  # @blueprint.errorhandler(500)
  
  
  @blueprint.route('/register', methods=['GET', 'POST'])
  def register():
      login_form = LoginForm(request.form)
      create_account_form = CreateAccountForm(request.form)
      if 'register' in request.form:
  
          username = request.form['username']
          email = request.form['email']
  
          # Check usename exists
          user = User.query.filter_by(username=username).first()
          if user:
              return render_template('accounts/register.html',
                                     msg='Username already registered',
                                     success=False,
                                     form=create_account_form)
  
          # Check email exists
          user = User.query.filter_by(email=email).first()
          if user:
              return render_template('accounts/register.html',
                                     msg='Email already registered',
                                     success=False,
                                     form=create_account_form)
  
          # else we can create the user
          user = User(**request.form)
          db.session.add(user)
          db.session.commit()
  
          return render_template('accounts/register.html',
                                 msg='User created please <a href="/login">login</a>',
                                 success=True,
                                 form=create_account_form)
  
      else:
          return render_template('accounts/register.html', form=create_account_form)
  
  
  @blueprint.route('/logout')
  def logout():
      logout_user()
      return redirect(url_for('base_blueprint.login'))
  
  
  @blueprint.route('/createmodel')
  @login_required
  def createmodel():
      return render_template('models/selectds.html', segment='createmodel')
  
  
  @blueprint.route('/uploadcsvds', methods=['GET', 'POST'])
  @login_required
  def uploadcsvds():
      if request.method == 'POST':
          f = request.files['filename']
          filePath = os.path.join(app.config['UPLOAD_FOLDER'], secure_filename(f.filename))
          f.save(filePath)
  
          # Check if the dataset if engough
          data = pd.read_csv(filePath)
          count_row = data.shape[0]
          if(count_row > 50):
              # Get the DS file header
              headersArray = getcvsheader(filePath)
              fname = f.filename
              return render_template('models/selectfields.html', headersArray=headersArray, fname=fname,
                                     segment='createmodel', message='No')
          else:
              return render_template('models/selectfields.html', message= 'Uploaded data document does not have enough data, the document must have minimum 50 records of data for accurate processing.',
                                     segment='createmodel')
  
  
  @blueprint.route('/creatingthemodel', methods=['GET', 'POST'])
  @login_required
  def creatingthemodel():
      if request.method == 'POST':
          predictionvalues = numpy.array((request.form.getlist('predcitedvalues')))
          fname = request.form.get('fname')
          loading_icon_path = os.path.join('/images/', 'loading_icon.gif')
          progress_icon_path = os.path.join('/images/', 'progress_icon.gif')
          return render_template('models/creatingthemodel.html', predictionvalues=predictionvalues,
                                 progress_icon_path=progress_icon_path, fname=fname, loading_icon_path=loading_icon_path,
                                 segment='createmodel')
  
  
  @blueprint.route('/sendpredictionvalues', methods=['GET', 'POST'])
  @login_required
  def sendpredictionvalues():
      try:
          if request.method == 'POST':
              predictionvalues = numpy.array((request.form.getlist('predcitedvalues')))
              fname = request.form.get('fname')
              idf = improve_data_file(fname, app.config['UPLOAD_FOLDER'], predictionvalues)
  
              # run model
              data_file_path = os.path.join(app.config['UPLOAD_FOLDER'], fname)
              df = pd.read_csv(data_file_path, sep=",")
              data_sample = (df.sample(n=5))
              model_controller = run_model(root_path, data_file_path, predictionvalues)
  
              # Webpage details
              page_url = request.host_url + "predictevalues"
              page_embed = "<iframe width='500' height='500' src='" + page_url + "'></iframe>"
  
              # APIs details and create APIs document
              model_api_details = ModelAPIDetails.query.first()
              apihelper = APIHelper()
              generate_apis_docs = apihelper.generateapisdocs('heart',
                                                              str(request.host_url + 'api/' + model_api_details.api_version),
                                                              app.config['DOCS_TEMPLATES_FOLDER'],
                                                              app.config['OUTPUT_DOCS'])
  
              return render_template('models/modelstatus.html', accuracy=model_controller['accuracy'],
                                     confusion_matrix=model_controller['confusion_matrix'],
                                     plot_image_path=model_controller['plot_image_path'], sample_data=[
                      data_sample.to_html(border=0, classes='table table-hover', header="false",
                                          justify="center").replace(
                          "<th>", "<th class='text-warning'>")],
                                     Mean_Absolute_Error=model_controller['Mean_Absolute_Error'],
                                     Mean_Squared_Error=model_controller['Mean_Squared_Error'],
                                     Root_Mean_Squared_Error=model_controller['Root_Mean_Squared_Error'],
                                     segment='createmodel', page_url=page_url, page_embed=page_embed,
                                     created_on=model_controller['created_on'], updated_on=model_controller['updated_on'],
                                     last_run_time=model_controller['last_run_time'], fname=fname)
      except Exception as e:
  
          tb = sys.exc_info()[2]
          print(tb)
          return render_template('page-500.html', error=e.with_traceback(tb))
  
  
  @blueprint.route('/runthemodel', methods=['GET', 'POST'])
  @login_required
  def runthemodel():
      try:
          predictionvalues = numpy.array(ModelLabels.query.with_entities(ModelLabels.label_name).all()).flatten()
          fname = ModelProfile.query.with_entities(ModelProfile.model_name).first()[0] + '.csv'
  
          # run model
          data_file_path = os.path.join(app.config['UPLOAD_FOLDER'], fname)
          df = pd.read_csv(data_file_path, sep=",")
          data_sample = (df.sample(n=5))
          model_controller = run_model(root_path, data_file_path, predictionvalues)
  
          # Webpage details
          page_url = request.host_url + "predictevalues"
          page_embed = "<iframe width='500' height='500' src='" + page_url + "'></iframe>"
  
          # APIs details
          # model_api_details = get_api_details()
          # APIs details and create APIs document
          model_api_details = ModelAPIDetails.query.first()
          apihelper = APIHelper()
          generate_apis_docs = apihelper.generateapisdocs('heart',
                                                          str(request.host_url + 'api/' + model_api_details.api_version),
                                                          app.config['DOCS_TEMPLATES_FOLDER'],
                                                          app.config['OUTPUT_DOCS'])
  
          return render_template('models/modelstatus.html', accuracy=model_controller['accuracy'],
                                 confusion_matrix=model_controller['confusion_matrix'],
                                 plot_image_path=model_controller['plot_image_path'], sample_data=[
                  data_sample.to_html(border=0, classes='table table-hover', header="false",
                                      justify="center").replace(
                      "<th>", "<th class='text-warning'>")],
                                 Mean_Absolute_Error=model_controller['Mean_Absolute_Error'],
                                 Mean_Squared_Error=model_controller['Mean_Squared_Error'],
                                 Root_Mean_Squared_Error=model_controller['Root_Mean_Squared_Error'],
                                 segment='createmodel', page_url=page_url, page_embed=page_embed,
                                 created_on=model_controller['created_on'], updated_on=model_controller['updated_on'],
                                 last_run_time=model_controller['last_run_time'], fname=fname)
      except Exception as e:
          print(e)
          return render_template('page-500.html', error=e.with_traceback(), segment='error')
  
  
  @app.route('/plot.png')
  @login_required
  def plot_png():
      fig = create_figure()
      output = io.BytesIO()
      FigureCanvas(fig).print_png(output)
      return Response(output.getvalue(), mimetype='image/png', segment='createmodel')
  
  
  @blueprint.route('/predictevalues', methods=['GET', 'POST'])
  def predictevalues():
      features_list = get_features()
      labels_list = get_labels()
      testing_values = []
      opt_param = len(request.form)
      if opt_param == 0:
          return render_template('models/predictevalues.html', features_list=features_list, labels_list=labels_list,
                                 predicted_value='nothing', testing_values='nothing')
      else:
          if request.method == 'POST':
              for i in features_list:
                  feature_value = request.form.get(i)
                  final_feature_value = float(feature_value) if feature_value.isnumeric() else feature_value
                  testing_values.append(final_feature_value)
              model_name = get_model_name()
              predicted_value = predict_values_from_model(model_name, testing_values)
              return render_template('models/predictevalues.html', features_list=features_list, labels_list=labels_list,
                                     predicted_value=predicted_value, testing_values=testing_values)
  
  
  @blueprint.route('/showdashboard')
  @login_required
  def showdashboard():
      profile = get_model_status()
  
      if len(profile) > 0:
          fname = profile['model_name'] + '.csv'
          data_file_path = os.path.join(app.config['UPLOAD_FOLDER'], fname)
          df = pd.read_csv(data_file_path, sep=",")
          data_sample = (df.sample(n=5, replace=True))
  
          # Webpage details
          page_url = request.host_url + "predictevalues"
          page_embed = "<iframe width='500' height='500' src='" + page_url + "'></iframe>"
  
          return render_template('models/dashboard.html', accuracy=profile['prediction_results_accuracy'],
                                 confusion_matrix='',
                                 plot_image_path=profile['plot_image_path'], sample_data=[
                  data_sample.to_html(border=0, classes='table table-hover', header="false", justify="center").replace(
                      "<th>", "<th class='text-warning'>")], Mean_Absolute_Error=profile['mean_absolute_error'],
                                 Mean_Squared_Error=profile['mean_squared_error'],
                                 Root_Mean_Squared_Error=profile['root_mean_squared_error'], message='No',
                                 fname=profile['model_name'], page_url=page_url, page_embed=page_embed,
                                 segment='showdashboard', created_on=profile['created_on'],
                                 updated_on=profile['updated_on'], last_run_time=profile['last_run_time'])
      else:
          return render_template('models/dashboard.html', message='You do not have any running model yet.',
                                 segment='showdashboard')
  
  
  @blueprint.route('/deletemodel', methods=['GET', 'POST'])
  @login_required
  def deletemodel():
      delete_model = delet_model()
      return render_template('models/dashboard.html', message='You do not have any running model yet.',
                             segment='deletemodel')
  
  
  @blueprint.route('/applications', methods=['GET', 'POST'])
  @login_required
  def appliications():
      return render_template('page-comingsoon.html', segment='applications')
  
  
  ## APIs
  
  @blueprint.route('/api/v1/predictevalues', methods=['POST'])
  def predictevalues_api():
      content = request.json
      # apihelper = APIHelper()
      # apireturn_json = apihelper.api_runner(content)  # predictvalues(content['inputs'])
      # inputs = content['inputs']
      apireturn_json = predictvalues(content)
      return apireturn_json
  
  
  @blueprint.route('/downloadapisdocument', methods=['GET', 'POST'])
  @login_required
  def downloadapisdocument():
      # For windows you need to use drive name [ex: F:/Example.pdf]
      path = root_path + app.config['OUTPUT_PDF_DOCS'] + '/heart_ProjectX_APIs_document.docx'
      return send_file(path, as_attachment=True)
  
  
  ## Errors
  
  @login_manager.unauthorized_handler
  def unauthorized_handler():
      return render_template('page-403.html', segment='error'), 403
  
  
  @blueprint.errorhandler(403)
  def access_forbidden(error):
      return render_template('page-403.html', segment='error'), 403
  
  
  @blueprint.errorhandler(404)
  def not_found_error(error):
      return render_template('page-404.html', segment='error'), 404
  
  
  @blueprint.errorhandler(500)
  def internal_error(error):
      return render_template(('page-500.html'), error, segment='error'), 500
  