from .base import Api, Http400
from django.db import connection
from django.http import Http404
from common.models import Job, JobTrail, Component
import datetime
import logging
from collections import OrderedDict


class RegressJobList(Api):
    def get(self, request, *args):
        try:
            regr = Component.objects.get(n=args[0])
        except:
            raise Http404('Regression component not found')
        count = request.GET.get('count', 20)
        if not str(count).isdigit():
            raise Http400('count must be digital')
        count = int(count)

        td_from = request.GET.get('from', 0)
        version = request.GET.get('version', '')

        jobs = Job.objects.filter(component=regr.n, td__isnull=False).order_by('-n')
        flag = request.GET.get('flag', 0)
        if flag:
            jobs = jobs.filter(flag=1)
        if version:
            jobs = jobs.filter(ver=version)
        if td_from:
            datetime_from = datetime.datetime(
                int(td_from[0:4] or 0),
                int(td_from[4:6] or 0),
                int(td_from[6:8] or 0),
                int(td_from[8:10] or 0),
                int(td_from[10:12] or 0),
                int(td_from[12:14] or 0)
            )
            # print datetime_from
            jobs = jobs.filter(td__gt=datetime_from)
        jobs = jobs[:count]
        try:
            assert jobs.count()
        except AssertionError:
            return []

        job_ids = [str(j.n) for j in jobs]

        fields = request.GET.get('fields', '''n, fd, flag,
                                    imbalance, imbalance_rps, 
                                    q50, q75, q80, q85, q90, q95, q98, q99,
                                    name, version, dsc''')
        fields = [f.strip() for f in fields.split(',') if f]

        if 'imbalance' or 'imbalance_rps' in fields:
            imbalances_sql = '''
                select up,  
                    case 
                        when hum_isimbalance=1 then hum_imbalance 
                        when rob_isimbalance=1 and hum_processed=0 then rob_imbalance 
                        else 0 
                    end 
                    from job_imbalance 
                    where up in ({});
            '''.format(','.join(job_ids))
            cursor = connection.cursor()
            imbalances_data = []
            try:
                cursor.execute(imbalances_sql)
                imbalances_data = cursor.fetchall()
            except:
                logging.exception('')
            finally:
                cursor.close()
            imbalances = {d[0]: d[1] for d in imbalances_data}
        else:
            imbalances = {}

        rules = {
            'n': lambda job: job.n,
            'fd': lambda job: str(job.fd),
            'flag': lambda job: job.flag,
            'imbalance': lambda job: imbalances.get(job.n, 0),
            'imbalance_rps': lambda job: imbalances.get(job.n, 0),  # alias
            'q50': lambda job: self.quantiles(job)['q50'],
            'q75': lambda job: self.quantiles(job)['q75'],
            'q80': lambda job: self.quantiles(job)['q80'],
            'q85': lambda job: self.quantiles(job)['q85'],
            'q90': lambda job: self.quantiles(job)['q90'],
            'q95': lambda job: self.quantiles(job)['q95'],
            'q98': lambda job: self.quantiles(job)['q98'],
            'q99': lambda job: self.quantiles(job)['q99'],
            'name': lambda job: job.name,
            'version': lambda job: job.ver,
            'dsc': lambda job: job.dsc,
        }

        res = []
        for job in jobs:
            for field in fields:
                if field not in list(rules.keys()):
                    raise Http400('Field {} not found'.format(field))

            res.append(OrderedDict(
                [(col, rules[col](job)) for col in fields]
            ))

        return res


    @staticmethod
    def quantiles(job):
        q50 = 0
        q75 = 0
        q80 = 0
        q85 = 0
        q90 = 0
        q95 = 0
        q98 = 0
        q99 = 0  # q100 = 0
        try:
            tr = JobTrail.objects.get(up=job.n)
            q50 = tr.q50 or 0
            q75 = tr.q75 or 0
            q80 = tr.q80 or 0
            q85 = tr.q85 or 0
            q90 = tr.q90 or 0
            q95 = tr.q95 or 0
            q98 = tr.q98 or 0
            q99 = tr.q99 or 0  # q100 = tr.q100 or 0
        except:
            pass

        return {
            'q50': q50,
            'q75': q75,
            'q80': q80,
            'q85': q85,
            'q90': q90,
            'q95': q95,
            'q98': q98,
            'q99': q99,
        }
