# -*- coding: utf-8 -*-

import json

from django.http.response import HttpResponse
from django.shortcuts import render_to_response, render
from django.template import RequestContext
from django_yauth.decorators import yalogin_required

import settings
from common.util.clients import ClickhouseClient
from common.util.decorators import memoized_property
from common.util.meta import escape_string
from common.views import get_common
from .models import CompareMobileJobsManager
from mobilepage.models import MobileJob


@yalogin_required
def mobilecompare(request):
    """

    :param request: HttpRequest
    :return: HttpResponse
    """
    user = request.yauser
    common_data = get_common(request)
    manager = CompareMobileJobsManager(user.login)
    job_objects = get_mobilejob_objects(manager.get_jobs())
    job_colors = {job_objects[i].n: MobileComparePlot.color_mapping(i) for i in range(len(job_objects))}

    return render_to_response('mobilecompare.html', {
        'pagename': 'mobilecompare',
        'jobs': job_objects,
        'job_colors': job_colors,
        'common': common_data,
        'user_mobile_job_numbers': ','.join(str(j.n) for j in job_objects),
    }, RequestContext(request))


@yalogin_required
def no_compare_jobs(request):
    common_data = get_common(request)
    return render(request, 'error.html', {'common': common_data, 'error': 'no_mobilecompare_jobs'})


@yalogin_required
def get_compare_jobs(request):
    user = request.yauser
    manager = CompareMobileJobsManager(user.login)
    job_numbers = ','.join(str(j.n) for j in get_mobilejob_objects(manager.get_jobs()))
    return HttpResponse(json.dumps({'jobs': job_numbers}), content_type='application/json')


@yalogin_required
def reset_jobs(request):
    user = request.yauser
    job_numbers = [j.n for j in get_mobilejob_objects(request.POST.get('jobs', '').split(','))]
    manager = CompareMobileJobsManager(user.login)
    manager.set_jobs(job_numbers)
    return HttpResponse(json.dumps({'success': 1}), content_type='application/json')


@yalogin_required
def add_jobs(request):
    user = request.yauser
    job_numbers = [j.n for j in get_mobilejob_objects(request.POST.get('jobs', '').split(','))]
    manager = CompareMobileJobsManager(user.login)
    manager.add_jobs(job_numbers)
    return HttpResponse(json.dumps({'success': 1}), content_type='application/json')


@yalogin_required
def remove_jobs(request):
    user = request.yauser
    job_numbers = [j.n for j in get_mobilejob_objects(request.POST.get('jobs', '').split(','))]
    if job_numbers:
        manager = CompareMobileJobsManager(user.login)
        manager.remove_jobs(job_numbers)
        return HttpResponse(json.dumps({'success': 1}), content_type='application/json')
    else:
        return HttpResponse(json.dumps({'success': 0, 'error': 'nothing to delete'}), content_type='application/json')


def get_mobilejob_objects(job_numbers):
    """

    :param job_numbers: []
    :return:
    """
    job_numbers = [int(str(j).strip()) for j in job_numbers if str(j).strip().isdigit()]
    job_objects = []
    for job_n in job_numbers:
        job_objects.extend(MobileJob.objects.filter(n=job_n))
    return job_objects


@yalogin_required
def get_mobile_plot(request):
    plot_type_mapping = {
        'bar_avg': MobileCompareBarAvgPlot,
        'timeline_quantiles': MobileCompareTimelineQuantilesPlot,
    }
    plot_type = request.GET.get('type', '')
    selector = request.GET.get('selector')
    group_colors_by = request.GET.get('groupby')
    job_numbers = [j.n for j in get_mobilejob_objects(request.GET.get('job_numbers', '').split(','))]
    if settings.RUNTIME_ENV:
        ch_url = 'http://lunapark-clickhouse.n.yandex-team.ru:80'
    else:
        ch_url = 'https://' if request.is_secure() else 'http://'
        ch_url += request.get_host() + '/api/dungeon'
    plot = plot_type_mapping.get(plot_type, MobileCompareBarAvgPlot)(job_numbers,
                                                                     ch_url,
                                                                     selector=selector,
                                                                     group_colors_by=group_colors_by
                                                                     )

    return HttpResponse(json.dumps(plot.data()), content_type='application/json')


def get_mobile_metatable(request):
    job_numbers = [j.n for j in get_mobilejob_objects(request.GET.get('job_numbers', '').split(','))]
    if settings.RUNTIME_ENV:
        ch_url = 'http://lunapark-clickhouse.n.yandex-team.ru:80'
    else:
        ch_url = 'https://' if request.is_secure() else 'http://'
        ch_url += request.get_host() + '/api/dungeon'
    plot = MobileMetaTable(job_numbers, ch_url)

    return HttpResponse(json.dumps(plot.data()), content_type='application/json')


class MobileComparePlot(object):

    selectors = None

    def __init__(self, job_numbers, ch_url, selector=None, group_colors_by=None):
        """

        :param job_numbers: int[]
        :param ch_url: str depends on environment and database location
        """
        self.job_numbers = job_numbers
        self.ch_client = ClickhouseClient(url=ch_url, readonly=True)
        self.selector = selector
        self.group_colors_by = group_colors_by

    @memoized_property
    def job_objects(self):
        job_numbers = [int(str(j).strip()) for j in self.job_numbers if str(j).strip().isdigit()]
        job_objects = []
        for job_n in job_numbers:
            job_objects.extend(MobileJob.objects.filter(n=job_n))
        return job_objects

    @memoized_property
    def tasks(self):
        return sorted(set(j.task for j in self.job_objects))

    @memoized_property
    def components(self):
        return sorted(set(j.component for j in self.job_objects))

    @staticmethod
    def color_mapping(index):
        """
        uses default highcharts colors
        from ver. 3.0.10
        """
        v3_colors = ['#2f7ed8',
                     # '#0d233a',
                     '#f28f43',
                     '#8bbc21',
                     '#910000',
                     '#1aadce',
                     '#492970',
                     '#77a1e5',
                     '#c42525',
                     '#a6c96a']
        return v3_colors[index % len(v3_colors)]


class MobileCompareBarAvgPlot(MobileComparePlot):

    def data(self):

        jobs_old = [j for j in self.job_objects if j.version != '2']
        jobs_new = [j for j in self.job_objects if j.version == '2']

        sql_old = '''
            select test_id, round(avg(value), 3)
            from volta.current
            where test_id in ({job_ids})
            group by test_id
        '''
        if jobs_old:
            jobs_old_data = self.ch_client.select(
                sql_old,
                query_params={
                    'job_ids': ','.join(
                        "'{}'".format(j.test_id)
                        for j in jobs_old
                    ),
                }
            )
        else:
            jobs_old_data = ()
        # for jobs with version == '2'
        sql_new = '''  
            select test_id, round(avg(value), 3)
            from volta.currents
            where test_id in ({job_ids})
            group by test_id
        '''
        if jobs_new:
            jobs_new_data = self.ch_client.select(
                sql_new,
                query_params={
                    'job_ids': ','.join(
                        "'{}'".format(escape_string(j.test_id))
                        for j in jobs_new
                    ),
                }
            )
        else:
            jobs_new_data = ()

        jobs_data = list(jobs_old_data) + list(jobs_new_data)
        jobs_data = dict(jobs_data) if jobs_data else {}
        series = []
        for job in self.job_objects:
            ser = {
                'name': job.name,
                'data': [jobs_data.get(job.test_id, 0)],
                'color': self.color_mapping(self.job_objects.index(job))
            }
            # TODO: перенести в color_mapping
            if self.group_colors_by == 'task':
                ser['color'] = self.color_mapping(self.tasks.index(job.task))
            elif self.group_colors_by == 'component':
                if job.component:
                    ser['color'] = self.color_mapping(self.components.index(job.component))
                else:
                    ser['color'] = self.color_mapping(len(self.components) + self.job_objects.index(job))

            series.append(ser)

        return {'data': series, 'selectors': self.selectors}


class MobileCompareTimelineQuantilesPlot(MobileComparePlot):

    selectors = 'avg', '99', '98', '95', '90', '85', '80', '75', '50'

    def data(self):
        series = []
        for job in self.job_objects:

            sql = '''
                select
            '''
            if self.selector == 'avg':
                sql += '''
                round(avg(value), 3)
                '''
            elif self.selector == "100":
                sql += '''
                round(max(value), 3)
                '''
            else:
                sql += '''
                round(quantile(0.{selector})(value), 3)
                '''
            if job.version == '2':
                sql += '''
                    from volta.currents
                    where test_id = '{test_id}'
                    group by intDiv(uts, 1000000)*1000000
                    order by intDiv(uts, 1000000)*1000000
                '''
            else:
                sql += '''
                    from volta.current
                    where test_id = '{test_id}'
                    group by intDiv(time, 10000)*10000
                    order by intDiv(time, 10000)*10000
                '''
            job_data = self.ch_client.select(sql,
                                             query_params={
                                                 'test_id': job.test_id,
                                                 'selector': self.selector,
                                             })

            ser = {
                'name': '{} - {}'.format(job.n, job.name),
                'data': [j[0] for j in job_data],
                'color': self.color_mapping(self.job_objects.index(job))
            }
            if self.group_colors_by == 'task':
                ser['color'] = self.color_mapping(self.tasks.index(job.task))
            elif self.group_colors_by == 'component':
                if job.component:
                    ser['color'] = self.color_mapping(self.components.index(job.component))
                else:
                    ser['color'] = self.color_mapping(len(self.components) + self.job_objects.index(job))

            series.append(ser)

        return {'data': series, 'selectors': self.selectors}


class MobileMetaTable(MobileComparePlot):

    @memoized_property
    def job_objects(self):
        job_numbers = [int(str(j).strip()) for j in self.job_numbers if str(j).strip().isdigit()]
        job_objects = []
        for job_n in job_numbers:
            job_objects.extend(MobileJob.objects.filter(n=job_n))
        return job_objects

    def data(self):
        d = []
        for job in self.job_objects:
            value = {
                'name': job.name,
                'task': job.task,
                'header': job.n,
                'dsc': job.dsc,
                'app': job.app,
                'ver': job.ver,
                'device_model': job.device_model,
                'color': self.color_mapping(self.job_objects.index(job))
            }
            if self.group_colors_by == 'task':
                value['color'] = self.color_mapping(self.tasks.index(job.task))
            elif self.group_colors_by == 'component':
                if job.component:
                    value['color'] = self.color_mapping(self.components.index(job.component))
                else:
                    value['color'] = self.color_mapping(len(self.components) + self.job_objects.index(job))
            d.append(value)

        return d


def favicon(request):
    return HttpResponse('')
