#!/usr/bin/env python

from flask import Flask, request, make_response
import sys
import json
import functools


app = Flask(__name__)
sys.stdout = sys.stderr
files = {}
files_done = {}
attempts = 0


def check_common_api_parameters(handle):
    @functools.wraps(handle)
    def checker(*args, **kwargs):
        """
        Check a request always has the consumer query parameter set to 'mrc'
        and some 'job_id' passed as a parameter of a multipart form.
        """
        global files

        if request.args.get('consumer') != 'mrc':
            return make_response("Not an MRC consumer\n", 403)

        if not request.form or not request.form.get('job_id'):
            return make_response("Must have a job_id set\n", 400)

        job_id = request.form.get('job_id')
        if job_id not in files:
            files[job_id] = {}
            files_done[job_id] = {}

        return handle(*args, **kwargs)

    return checker


@app.route('/1/upload/', methods=['POST'])
@check_common_api_parameters
def upload():
    global files
    global attempts

    job_id = request.form.get('job_id')

    if not request.files or not request.files.get('file'):
        return make_response("Must have a file to upload\n", 400)

    filename = request.files.get('file').filename
    if filename in files[job_id]:
        return make_response(
            "Trying to upload with an existing filename {}\n".format(filename), 409)

    attempts += 1
    if attempts % 2 > 0:
        return make_response('{"status":"error"}\n', 200)

    files[job_id][filename] = json.loads(request.files.get('file').stream.read())
    return make_response('{"status":"ok"}\n', 200)


@app.route('/1/upload/done/', methods=['POST'])
@check_common_api_parameters
def upload_done():
    global files
    global attempts

    job_id = request.form.get('job_id')

    recv_files = {value for value in request.form.getlist('filename')}
    diff = set(files[job_id].keys()) ^ recv_files

    if len(diff) != 0:
        resp = json.dumps({
            "status": "missing",
            "missing_files": [filename for filename in diff]
        })
        return (resp, 400)

    attempts += 1
    if attempts % 2 > 0:
        return make_response('{"status":"error"}\n', 200)

    files_done[job_id] = files[job_id]
    return make_response('{"status":"ok"}', 200)


@app.route('/get_data_for', methods=['GET'])
def get_data_for():
    if not request.args.get('job_id'):
        return make_response("No job ID is given\n", 400)

    job_id = request.args.get('job_id')
    return make_response(json.dumps(files_done[job_id], sort_keys=True), 200)


def main(argv=sys.argv):
    # Make flask to use HTTP/1.1 protocol (to support Keep Alive connections)
    from BaseHTTPServer import BaseHTTPRequestHandler
    BaseHTTPRequestHandler.protocol_version = "HTTP/1.1"

    app.run(sys.argv[1], sys.argv[2])


if __name__ == "__main__":
    main()
