from flask import (abort, current_app, flash, make_response, render_template,
                   url_for)
from flask_login import current_user, login_required
from werkzeug.utils import secure_filename
from . import services
from .. import db
from ..jobs.forms import AddFileSetupJobForm, AddNLPJobForm, AddOCRJobForm
from ..models import Job, JobInput
import json
import os


SERVICES = {'corpus_analysis': {'name': 'Corpus analysis'},
            'file-setup': {'name': 'File setup',
                           'resources': {'mem_mb': 4096, 'n_cores': 4},
                           'add_job_form': AddFileSetupJobForm},
            'nlp': {'name': 'Natural Language Processing',
                    'resources': {'mem_mb': 4096, 'n_cores': 2},
                    'add_job_form': AddNLPJobForm},
            'ocr': {'name': 'Optical Character Recognition',
                    'resources': {'mem_mb': 8192, 'n_cores': 4},
                    'add_job_form': AddOCRJobForm}}


@services.route('/<service>', methods=['GET', 'POST'])
@login_required
def service(service):
    if service not in SERVICES:
        abort(404)
    if service == 'corpus_analysis':
        return render_template('services/{}.html.j2'.format(service),
                               title=SERVICES[service]['name'])
    add_job_form = SERVICES[service]['add_job_form'](prefix='add-job-form')
    if add_job_form.is_submitted():
        if not add_job_form.validate():
            return make_response(add_job_form.errors, 400)
        service_args = []
        if service == 'nlp':
            service_args.append('-l {}'.format(add_job_form.language.data))
            if add_job_form.check_encoding.data:
                service_args.append('--check-encoding')
        if service == 'ocr':
            service_args.append('-l {}'.format(add_job_form.language.data))
            if add_job_form.binarization.data:
                service_args.append('--binarize')
        job = Job(creator=current_user,
                  description=add_job_form.description.data,
                  mem_mb=SERVICES[service]['resources']['mem_mb'],
                  n_cores=SERVICES[service]['resources']['n_cores'],
                  service=service, service_args=json.dumps(service_args),
                  service_version=add_job_form.version.data,
                  status='preparing', title=add_job_form.title.data)
        if job.service != 'corpus_analysis':
            job.create_secure_filename()
        db.session.add(job)
        db.session.commit()
        relative_dir = os.path.join(str(job.user_id), 'jobs', str(job.id))
        absolut_dir = os.path.join(current_app.config['NOPAQUE_STORAGE'],
                                   relative_dir)
        try:
            os.makedirs(absolut_dir)
        except OSError:
            job.delete()
            flash('Internal Server Error')
            return make_response({'redirect_url': url_for('services.service',
                                                          service=service)},
                                 500)
        else:
            for file in add_job_form.files.data:
                filename = secure_filename(file.filename)
                file.save(os.path.join(absolut_dir, filename))
                job_input = JobInput(dir=relative_dir, filename=filename,
                                     job=job)
                db.session.add(job_input)
            job.status = 'submitted'
            db.session.commit()
            flash('Job added!')
            return make_response(
                {'redirect_url': url_for('jobs.job', job_id=job.id)}, 201)
    return render_template('services/{}.html.j2'.format(service),
                           title=SERVICES[service]['name'],
                           add_job_form=add_job_form)