#!/usr/bin/env python
# -*- coding: utf-8 -*-
from .base import ApiJob
from common.models import Component, JobImbalance, KPI, Job, MobileJobDataKey
from django.http import HttpResponseBadRequest, HttpResponseServerError, \
    HttpResponse
from collections import OrderedDict
from django_yauth.decorators import yalogin_required
import json
import logging


class JobMetaInfo(ApiJob):
    """
    job edit
    """
    http_method_names = ['post']

    @staticmethod
    def post(request, job):
        """
        :param request: HTTP request
        :param job: job object passed from request
        """
        params = request.body.decode('utf-8')  # POST.get('params')

        if not params:
            logging.error("Params not set")
            return HttpResponseBadRequest(json.dumps('Params not set!'), content_type='application/json')

        params = json.loads(params)

        params_d = {'starred': 'flag', 'description': 'dsc', 'component': 'component', 'loop': 'loop_cnt',
                    'ammo': 'ammo_path', 'version': 'ver',
                    'tank_type': 'type', 'instances': 'instances', 'command_line': 'command_line', 'name': 'name'}

        set_smth = 0
        for name, val in params_d.items():
            if name in params:
                set_smth = 1
                new_val = params[name]
                if name in ('version', 'name') and new_val:
                    new_val = new_val[0:120]
                elif name == 'ammo' and new_val:
                    new_val = new_val[0:256]
                elif name == 'command_line' and new_val:
                    new_val = new_val[0:512]
                elif name == 'component':
                    if new_val and new_val.isdigit():  # numeric
                        try:
                            component_obj = Component.objects.get(
                                n=int(new_val),
                            )
                            new_val = component_obj.n
                        except Component.DoesNotExist:  # we don't need new numeric components
                            logging.error('Digital component for job {}!'.format(job.n))
                            return HttpResponseBadRequest(json.dumps('Digital component!'), content_type='application/json')
                    elif new_val and not new_val.isdigit():  # not numeric
                        component_obj, _is_new = Component.objects.get_or_create(
                            name=new_val,
                            tag=job.task.split('-')[0],
                        )
                        new_val = component_obj.n
                        if _is_new:
                            create_default_kpis(component_obj)
                    else:  # no component
                        new_val = 0
                setattr(job, val, new_val)

        mobile_key = params.get('mobile_key', '')
        if mobile_key:
            mjdk = MobileJobDataKey.objects.get_or_create(job=job)[0]
            mjdk.mobile_data_key = mobile_key
            mjdk.save()

        imb_val = params.get('imbalance', '')
        if imb_val != '':
            if isinstance(imb_val, int):
                imb = job.jobimbalance_set.all()
                if imb:
                    imb = imb[0]
                else:
                    imb = JobImbalance(up=job)
                person = params.get('person', '')
                if person:
                    imb.user = person
                imb.hum_processed = 1
                if imb_val != -1:
                    imb.hum_isimbalance = 1
                    imb.hum_imbalance = imb_val
                else:
                    imb.hum_isimbalance = 0
                imb.save()
                # update job_imbalance
                # set user='$user', hum_processed=1, hum_isimbalance=$is_imb, hum_imbalance=$user_imb
                # where up=$job
            else:
                logging.exception('Imbalance is not numeric: {}'.format(imb_val))

        if set_smth:
            try:  # save what was changed
                job.save()
            except:
                logging.exception('Failed to edit job')
                return HttpResponseServerError(json.dumps('Can not edit job!'), content_type='application/json')  # !!!

        return [{'success': 1}]


def create_default_kpis(component_obj):
    """
    creates default kpis for component only if there no kpi for this component at all
    :param component_obj: Component OBJECT
    """
    try:
        if not KPI.objects.filter(component_id=component_obj.n).count():
            KPI.objects.create(
                ktype='job_trail__quantiles',
                component_id=component_obj.n,
                params_json=json.dumps({
                    'graphs': ['q99', 'q98', 'q95', 'q90', 'q85', 'q80', 'q75', 'q50'],
                    'case': '',
                    'sla': OrderedDict(),
                }),
                dsc='Кумулятивные квантили',
                essential=True)
            KPI.objects.create(
                ktype='imbalance',
                component_id=component_obj.n,
                params_json=json.dumps({
                   'graphs': ['imbalance'],
                   'sla': OrderedDict(),
                }),
                dsc='RPS разладки',
                essential=True)
    except:
        logging.exception('Could not create default KPIs for component {} due to:'.format(component_obj.name))
        pass


@yalogin_required
def jobedit_frontend(request):
    """
    frontend handler
    :param request:
    """

    job_n = request.GET.get('job_n')
    try:
        assert job_n
    except AssertionError:
        return HttpResponseBadRequest('job_n required')

    params = request.POST

    job = Job.objects.get(n=job_n)

    success = update_job_metainfo(job, params)

    return HttpResponse(json.dumps({'success': success}))


def update_job_metainfo(job, params):
    """
    for frontend handler
    :param job:
    :param params:
    """

    params_d = {'starred': 'flag', 'description': 'dsc', 'component': 'component', 'loop': 'loop_cnt',
                'ammo': 'ammo_path', 'version': 'ver',
                'tank_type': 'type', 'instances': 'instances', 'command_line': 'command_line', 'name': 'name',
                'test_type': 'test_type'}

    set_smth = 0
    for name, val in params_d.items():
        if name in params:
            set_smth = 1
            new_val = params[name]
            if name in ('version', 'name') and new_val:
                new_val = new_val[0:120]
            elif name == 'ammo' and new_val:
                new_val = new_val[0:256]
            elif name == 'command_line' and new_val:
                new_val = new_val[0:512]
            setattr(job, val, new_val)

    if set_smth:
        try:  # save what was changed
            job.save()
            return True
        except:
            logging.exception("Failed to edit job")
            return False
