"""Blueprint for the main routes that are required by the application. Provides
routes to display a landing page (home page), start application workflow runs,
and access run result files.
"""

from flask import Blueprint, request, render_template, send_file, url_for

from flowserv.model.files.base import FlaskFile

from app.workflow import flowapp


"""Blueprint that groups the routes for the main application view."""
bp = Blueprint('main', __name__, url_prefix='/')


# -----------------------------------------------------------------------------
# Homepage
# -----------------------------------------------------------------------------

@bp.route('/', methods=['GET'])
def home_page():
    """Render the main landing page for the application."""
    return render_template('index.html', app=flowapp)


# -----------------------------------------------------------------------------
# Run files
# -----------------------------------------------------------------------------

@bp.route('/runs/<string:run_id>/files')
def download_result_archive(run_id):
    """Download a gzipped tar-archive containing all result files that were
    generated by a a successful workflow run.
    """
    file = flowapp.get_file(run_id=run_id)
    return send_file(
        file.open(),
        as_attachment=True,
        attachment_filename=file.name,
        mimetype=file.mime_type
    )


@bp.route('/runs/<string:run_id>/files/<string:file_id>')
def download_result_file(run_id, file_id):
    """Download a single result file that was generated by a successful
    workflow run.
    """
    file = flowapp.get_file(run_id=run_id, file_id=file_id)
    return send_file(
        file.open(),
        as_attachment=True,
        attachment_filename=file.name,
        mimetype=file.mime_type
    )


# -----------------------------------------------------------------------------
# Workflow runs
# -----------------------------------------------------------------------------

@bp.route('/runs', methods=['GET'])
def workflow_input():
    """Render the input form for workflow parameters."""
    return render_template('submit_run.html', app=flowapp)


@bp.route('/runs', methods=['POST'])
def run_workflow():
    """Run the application workflow using the values from an input form that
    was submitted by the user.
    """
    # Create argument dictionary for workflow parameters from user request
    # form and file data.
    args = dict()
    for para in flowapp.parameters().values():
        val = None
        if para.is_file():
            if para.name in request.files:
                val = args[para.name] = FlaskFile(request.files.get(para.name))
        else:
            val = request.form.get(para.name)
        args[para.name] = val if val else para.default
    # Run the workflow synchronously.
    run = flowapp.start_run(args, poll_interval=1)
    if run.is_error():
        raise ValueError(run.messages())
    files = dict()
    for f in run.files():
        url = url_for(
            'main.download_result_file',
            run_id=run.run_id,
            file_id=f.file_id
        )
        files[f.name] = (f, url)
    return render_template(
        'run_result.html',
        app=flowapp,
        files=files,
        archive=url_for('main.download_result_archive', run_id=run.run_id)
    )
