# enable logging
import workbook_logging
import logging
logger = logging.getLogger("workbook")

# helper functions
from workbook_utilities import run_compute_py, read_project_json, construct_navigation, read_metadata_json, create_new_dir

# flask
from flask import Flask, render_template, jsonify, send_file, send_from_directory, request

# core python libraries
import os
import sys
import json
import traceback

# Create the flask application object
app = Flask(__name__)

# Don't assume a template prefix name (allows for the app to serve templates
# from both templates/ and <project>/web/).
app.template_folder = '.'

# Turn on debug messages, direct them to the console
app.debug = True
app.logger.addHandler(logging.StreamHandler(sys.stdout))
app.logger.setLevel(logging.ERROR)

#
# Route the base URL to the main page
#
@app.route('/', methods=["POST"])
def home_createDir():
    logger.info("Processing index POST...")
    error = None
    success = None

    newDirName = request.form["dirName"]
    if os.path.isdir(newDirName):
        error = "Directory <b>" + newDirName + "</b> already exists!"
    else:
        create_new_dir(newDirName, request.form["projectName"], request.form["projectType"])
        success = "New directory <b>" + newDirName + "</b> created!"

    navigation = construct_navigation()
    return render_template('static/templates/mainPage.html', navigation=navigation, error=error, success=success)

@app.route('/')
def home():
    navigation = construct_navigation()
    return render_template('static/templates/mainPage.html', navigation=navigation)

#
# Files inside of /exercise/res and /exercise/web should be routed as
# static files.
#
@app.route('/<exerciseName>/res/<path:fileName>')
def fetchRes(exerciseName, fileName):
    logger.info(exerciseName + ":Sending static file: " + fileName)
    return send_from_directory(os.path.join(exerciseName, 'res'), fileName, cache_timeout=0)

@app.route('/<exerciseName>/web/<path:fileName>')
def fetchWeb(exerciseName, fileName):
    logger.info(exerciseName + ":Sending static file: " + fileName)
    return send_from_directory(os.path.join(exerciseName, 'web'), fileName, cache_timeout=0)

#
# A call to /exercise/py/ should compute (API)
#
@app.route('/<exerciseName>/py/')
def computePy(exerciseName):
    logger.info(exerciseName + ":Running compute.py")
    result = {}

    # Load and run compute.py
    try:
        run_compute_py(exerciseName)
        result["status"] = "Success"

        logger.info(exerciseName + ":compute.py ran without exception")
    except Exception as exc:
        result["status"] = "Error"
        result["error"] = str(exc)
        result["trace"] = str(traceback.format_exc())

        logger.error(exerciseName + ":compute.py generated an exception")

    return jsonify(result)

#
# Route everything else to an exercise:
#
@app.route('/<projectDir>/')
def fetchExercise(projectDir):
    logger.info(projectDir + ":Loading project")

    # Get the project info
    projectInfo = read_project_json(projectDir)
    if projectInfo == None:
        return "No project.json found."
    metadata = read_metadata_json(projectDir)

    # Figure out what to do based on the value of `show`
    show = request.args.get('show')

    showViz = False
    runPython = False

    if show == "viz":
        showViz = True
    if show == "py_viz":
        showViz = True
        runPython = True

    if runPython:
        projectInfo["ranCompute"] = True
        run_compute_py(projectDir)
    else:
        projectInfo["ranCompute"] = False


    navigation = construct_navigation()
    if showViz:
        projectInfo["showingViz"] = True
        return render_template(projectDir + '/web/index.html', project=projectInfo, navigation=navigation, metadata=metadata)
    else:
        # Project landing page
        projectInfo["showingViz"] = False
        return render_template('static/templates/projectLanding.html', project=projectInfo, navigation=navigation, metadata=metadata)

#
# Start the server with the `run` method
#
if __name__ == '__main__':
    app.run()