# -*- coding: utf-8 -*-
"""
Created on Nov 8, 2013

@author: noob
"""

from .plots_base import Table
from collections import OrderedDict
from common.models import Server
from common.util.aggregators import MonitoringAggregator, \
    RTDetailsAggregator, ProtoCodesAggregator, NetCodesAggregator, RTHistogramsAggregator
from common.util.decorators import Memoize
from httplib import responses
from itertools import izip
from monitoring.models import Metric
from os import strerror
import logging


class CasesDistTable(Table):
    title = u'Responses per tag distribution'

    def get_columns(self):
        """
        returns list of http codes and it's count
        """
        data = OrderedDict()
        try:
            sql = '''
                select round(toFloat32(sum(resps)), 3), 
                round(toFloat32(sumArray([connect_time_sum, send_time_sum, latency_sum, receive_time_sum]))/1000/toFloat32(sum(resps)), 3),
                round(toFloat32(sum(connect_time_sum))/1000/toFloat32(sum(resps)), 3), 
                round(toFloat32(sum(send_time_sum))/1000/toFloat32(sum(resps)), 3), 
                round(toFloat32(sum(latency_sum))/1000/toFloat32(sum(resps)), 3), 
                round(toFloat32(sum(receive_time_sum))/1000/toFloat32(sum(resps)), 3)
                from loaddb.rt_microsecond_details_buffer
                where job_id=%(job)s 
                and job_date=toDate(%(job_date)s)
                and time >= toDateTime(%(start)s) 
                and time <= toDateTime(%(end)s)
                group by tag 
                order by tag
            '''
            avg_times_data = self.ch_client.select(sql, query_params=self.query_params)
            cases = [u''] + self.job_obj.cases
            for i in range(len(cases)):
                case = cases[i]
                data[case] = {}
                try:
                    data[case]['count'] = avg_times_data[i][0]
                except:
                    data[case]['count'] = 0.0
                try:
                    data[case]['expect'] = avg_times_data[i][1]
                except:
                    data[case]['expect'] = 0.0
                try:
                    data[case]['connect_time'] = avg_times_data[i][2]
                except:
                    data[case]['connect_time'] = 0.0
                try:
                    data[case]['send_time'] = avg_times_data[i][3]
                except:
                    data[case]['send_time'] = 0.0
                try:
                    data[case]['latency'] = avg_times_data[i][4]
                except:
                    data[case]['latency'] = 0.0
                try:
                    data[case]['receive_time'] = avg_times_data[i][5]
                except:
                    data[case]['receive_time'] = 0.0

            # form data
            columns_data = [
                {'weight': 'bold', 'align': 'left', 'title': u' ',
                 'values': [u'Overall'] + [key for key in data.keys() if key]},
                {'align': 'right', 'title': u'Count', 'values': [data[key]['count'] for key in data.keys()]},
                {'align': 'right', 'title': u'Percent',
                 'values': ['100.000%'] + self.count_percentage([data[key]['count'] for key in data.keys() if key])},
                {'align': 'right', 'title': u'Overall Time',
                 'values': [str(data[key]['expect']) + ' ms' for key in data.keys()]},
                {'align': 'right', 'title': u'Connect Time',
                 'values': [str(data[key]['connect_time']) + ' ms' for key in data.keys()]},
                {'align': 'right', 'title': u'Send Time',
                 'values': [str(data[key]['send_time']) + ' ms' for key in data.keys()]},
                {'align': 'right', 'title': u'Latency',
                 'values': [str(data[key]['latency']) + ' ms' for key in data.keys()]},
                {'align': 'right', 'title': u'Receive Time',
                 'values': [str(data[key]['receive_time']) + ' ms' for key in data.keys()]},
            ]
            logging.debug('Got resps count for job %s', self.job)
            return columns_data
        except:
            logging.exception('Could not get cases resps data for job %s due to:', self.job)
            return None


class CasesNetCodesTable(Table):
    title = u'Net codes per tag'

    def get_columns(self):
        """
        returns list of http codes and it's count
        """
        columns_data = [{'weight': 'bold', 'align': 'left', 'title': u' ',
                         'values': [u'Overall'] + self.job_obj.cases}]
        sql = '''select code, tag, 
            toFloat32(sum(cnt))
            from loaddb.net_codes_buffer
            where job_id=%(job)s
            and job_date = toDate(%(job_date)s)
            and time >= toDateTime(%(start)s) 
            and time <= toDateTime(%(end)s)
            group by code, tag
            order by code, tag
            '''
        query_params = self.job_obj.basic_query_params.copy()
        query_params.update({
            'start': self.slider_start,
            'end': self.slider_end,
        })
        data = self.ch_client.select(sql, query_params=query_params)
        net_codes = sorted(set([c[0] for c in data]))
        i = 0
        for code in net_codes:
            column = {'align': 'right', 'title': str(code), 'values': []}
            code_values = {}
            while i < len(data) and data[i][0] == code:
                code_values[data[i][1]] = data[i][2]
                i += 1
            for tag in [''] + self.job_obj.cases:
                column['values'].append(code_values.get(tag, 0))
            columns_data.append(column)
        logging.debug('Got net_codes count per case for job %s', self.job)
        return columns_data


class CasesHttpCodesTable(Table):
    title = u'HTTP codes per tag'

    def get_columns(self):
        """
        returns list of http codes and it's count
        """
        columns_data = [{'weight': 'bold', 'align': 'left', 'title': u' ',
                         'values': [u'Overall'] + self.job_obj.cases}]
        sql = '''select code, tag, 
            toFloat32(sum(cnt))
            from loaddb.proto_codes_buffer
            where job_id=%(job)s
            and job_date = toDate(%(job_date)s)
            and time >= toDateTime(%(start)s) 
            and time <= toDateTime(%(end)s)
            group by code, tag
            order by code, tag
            '''
        query_params = self.job_obj.basic_query_params.copy()
        query_params.update({
            'start': self.slider_start,
            'end': self.slider_end,
        })
        data = self.ch_client.select(sql, query_params=query_params)
        http_codes = sorted(set([c[0] for c in data]))
        i = 0
        for code in http_codes:
            column = {'align': 'right', 'title': str(code), 'values': []}
            code_values = {}
            while i < len(data) and data[i][0] == code:
                code_values[data[i][1]] = data[i][2]
                i += 1
            for tag in [''] + self.job_obj.cases:
                column['values'].append(code_values.get(tag, 0))
            columns_data.append(column)
        logging.debug('Got http_codes count per case for job %s', self.job)
        return columns_data


class CasesCumulativeQuantilesTable(Table):
    title = u'Cumulative quantiles per tag'
    quantiles = '99%', '98%', '95%', '90%', '85%', '80%', '75%', '50%'

    def get_columns(self):
        """
        returns list of http codes and it's count
        """
        columns_data = [
            {'weight': 'bold', 'align': 'left', 'title': u' ',
             'values': [u'Overall'] + self.job_obj.cases},
        ]
        sql = '''select 
            quantilesExactWeighted(0.5, 0.75, 0.8, 0.85, 0.9, 0.95, 0.98, 0.99)(bin, cnt)
            from loaddb.rt_microsecond_histograms_buffer
            where job_id=%(job)s
            and job_date = toDate(%(job_date)s)
            and time >= toDateTime(%(start)s) 
            and time <= toDateTime(%(end)s)
            group by tag
            order by tag
            '''
        query_params = self.job_obj.basic_query_params.copy()
        query_params.update({
            'start': self.slider_start,
            'end': self.slider_end,
        })
        tags_data = self.ch_client.select(sql, query_params=query_params)

        for i in xrange(len(self.quantiles)):
            columns_data.append({'align': 'right',
                                 'title': self.quantiles[i],
                                 'values': [str(value[0][::-1][i]/1000) + ' ms' for value in tags_data]})
        logging.debug('Got columns data for %s for job %s', self.__class__.__name__, self.job)
        return columns_data


class HttpDistTable(Table):
    title = u'HTTP codes'

    def get_columns(self):
        """
        returns list of dicts with column settings and data
        """
        aggregator = ProtoCodesAggregator(self.job_obj, self.tag, self.slider_start, self.slider_end)
        data = aggregator.get_raw_data()

        count_data = [value[1] for value in data]
        http_codes_explained = []
        for value in data:
            http_codes_explained.append(str(value[0]) + ' - ' + responses.get(int(value[0]), '???'))
        columns = [{'weight': 'bold', 'align': 'left', 'title': u' ', 'values': http_codes_explained},
                   {'align': 'right', 'title': u'Count', 'values': count_data},
                   {'align': 'right', 'title': u'Percent', 'values': aggregator.count_percentage(count_data)}]
        logging.debug('Got http_codes for %s job %s', self.tag, self.job)
        return columns


class NetDistTable(Table):
    title = u'Net codes'

    def get_columns(self):
        """
        returns list of dicts with column settings and data
        """
        aggregator = NetCodesAggregator(self.job_obj, self.tag, self.slider_start, self.slider_end)
        data = aggregator.get_raw_data()

        count_data = [value[1] for value in data]
        columns = [{'weight': 'bold', 'align': 'left', 'title': u' ',
                    'values': [str(value[0]) + ' - ' + strerror(int(value[0])) for value in data]},
                   {'align': 'right', 'title': u'Count', 'values': count_data},
                   {'align': 'right', 'title': u'Percent', 'values': aggregator.count_percentage(count_data)}]
        logging.debug('Got http_codes for %s job %s', self.tag, self.job)
        return columns


class TimesDistTable(Table):
    title = u'Response time distribution'

    def get_columns(self):
        """
        returns list of dicts with column settings and data
        """
        aggregator = RTHistogramsAggregator(self.job_obj, self.tag, self.slider_start, self.slider_end)
        data = aggregator.get_raw_data()

        time_to_column = {'weight': 'bold', 'align': 'right', 'title': u' ',
                          'values': [value[0] for value in data][::-1]}
        time_count_column = {'align': 'right', 'title': u'Count', 'values': [value[1] for value in data][::-1]}
        time_percentage_column = {'align': 'right', 'title': u'Percent',
                                  'values': aggregator.count_percentage([value[1] for value in data])[::-1]}
        time_quantiles_column = {'align': 'right', 'title': u'Quantile',
                                 'values': aggregator.count_quantiles([value[1] for value in data])[::-1]}

        return [time_to_column, time_count_column, time_percentage_column, time_quantiles_column]


class QuantilesCumulativeTable(Table):
    title = u'Cumulative quantiles'
    rows = '99%', '98%', '95%', '90%', '85%', '80%', '75%', '50%'

    def get_columns(self):
        """
        returns list of dicts with column settings and data
        """
        sql = '''select 
            quantilesExactWeighted(0.5, 0.75, 0.8, 0.85, 0.9, 0.95, 0.98, 0.99)(bin, cnt)
            from loaddb.rt_microsecond_histograms_buffer
            where job_id=%(job)s 
            and job_date = toDate(%(job_date)s) '''
        if self.job_obj.multitag and self.tag:
            sql += 'and tag in (%(cases_with_tag)s) '
        else:
            sql += '''and tag='%(tag)s'  '''
        if self.slider_start:
            sql += '''
                and time >= toDateTime(%(start)s)
                '''
        if self.slider_end:
            sql += '''
                and time <= toDateTime(%(end)s)
                '''
        query_params = self.job_obj.basic_query_params.copy()
        query_params.update({
            'start': self.slider_start,
            'end': self.slider_end,
            'cases_with_tag': ','.join(
                ["'" + case + "'" for case in self.job_obj.cases if self.tag in case.split('|')]),
            'tag': self.tag,
        })
        raw_data = self.ch_client.select(sql, query_params=query_params)
        quantiles = [float(d) / 1000
                     for d in raw_data[0][0][::-1]] if raw_data and raw_data[0] else [0] * len(self.rows)

        data = [{'weight': 'bold', 'align': 'right', 'title': ' ', 'values': self.rows},
                {'align': 'right', 'title': u'Quantile', 'values': quantiles}]
        logging.debug('Got quantiles data for %s JOB %s: %s', self.__class__.__name__, self.job, data)
        return data


class AggregatesTable(Table):
    title = u'Aggregates'

    def get_columns(self):
        """
        returns list of dicts with column settings and data
        """
        avg_values = []
        stddev_values = []
        min_values = []
        max_values = []
        median_values = []

        aggregator = RTDetailsAggregator(self.job_obj, self.tag, self.slider_start, self.slider_end)

        for param in self.params:
            values = aggregator.get_param_data(param)
            avg_values.append(values[0] or 0)
            stddev_values.append(values[1] or 0)
            min_values.append(values[2] or 0)
            max_values.append(values[3] or 0)
            median_values.append(values[4] or 0)
        data = [
            {
                'weight': 'bold', 'align': 'left', 'title': u' ',
                'values': [self.params_dict[param] for param in self.params],
            },
            {'align': 'right', 'title': u'Minimum', 'values': min_values},
            {'align': 'right', 'title': u'Average', 'values': avg_values},
            {'align': 'right', 'title': u'Median', 'values': median_values},
            {'align': 'right', 'title': u'Maximim', 'values': max_values},
            {'align': 'right', 'title': u'StdDev', 'values': stddev_values},
        ]
        logging.debug('Got column data for %s for job %s: %s', self.__class__.__name__, self.job, data)
        return data

    @property
    def params(self):
        return self.params_dict.keys()

    @property
    def params_dict(self):
        return OrderedDict((
            ('resps', u'Resp per sec'),
            ('expect', u'Overall Time'),
            ('connect_time', u'Connect Time'),
            ('send_time', u'Send Time'),
            ('latency', u'Latency'),
            ('receive_time', u'Receive Time'),
            ('threads', u'Threads'),
        ))


class MonitoringAggregatesTable(Table):
    title = u'Monitoring aggregates'

    @property
    def target_n(self):
        return int(self.raw_case)

    @property
    @Memoize
    def targets(self):
        if self.target_n == -1:  # all targets
            targets = self.job_obj.targets
        else:
            targets = [Server.objects.get(n=self.target_n)]
        return targets

    def get_columns(self):
        """
        returns list of dicts with column settings and data
        """
        target_hosts = []
        metric_groups = []
        metric_names = []
        min_values = []
        avg_values = []
        median_values = []
        max_values = []
        stddev_values = []

        aggregator = MonitoringAggregator(self.job_obj, start=self.slider_start, end=self.slider_end)
        data = aggregator.aggregate()

        for target_obj in self.targets:
            target_hosts.extend(
                [target_obj.dsc or 'mysterious host %s' % target_obj.n] * len(self.sorted_target_metrics[target_obj.n]))
            metric_groups.extend(self.metric_groups(target_obj.n))
            metric_names.extend(self.metric_names(target_obj.n))
            values = data[target_obj.host]
            avg_values.extend([values[metric.code]['average'] for metric in self.sorted_target_metrics[target_obj.n]])
            stddev_values.extend(
                [values[metric.code]['stddev'] for metric in self.sorted_target_metrics[target_obj.n]])
            min_values.extend([values[metric.code]['minimum'] for metric in self.sorted_target_metrics[target_obj.n]])
            max_values.extend([values[metric.code]['maximum'] for metric in self.sorted_target_metrics[target_obj.n]])
            median_values.extend(
                [values[metric.code]['median'] for metric in self.sorted_target_metrics[target_obj.n]])
        data = [
            {'align': 'left', 'title': u'Target', 'values': target_hosts},
            {'align': 'left', 'title': u'Metrics group', 'values': metric_groups},
            {'align': 'left', 'title': u'Metric', 'values': metric_names},
            {'align': 'right', 'title': u'Minimum', 'values': min_values},
            {'align': 'right', 'title': u'Average', 'values': avg_values},
            {'align': 'right', 'title': u'Median', 'values': median_values},
            {'align': 'right', 'title': u'Maximum', 'values': max_values},
            {'align': 'right', 'title': u'StdDev', 'values': stddev_values},
        ]
        return data

    @property
    @Memoize
    def sorted_target_metrics(self):
        try:
            sorted_target_metrics = {}
            for target_obj in self.targets:
                sql = '''
                    select metric_name
                    from loaddb.monitoring_verbose_data_buffer
                    where job_id=%(job)s 
                    and job_date=toDate(%(job_date)s)
                    and target_host='%(target)s'
                    group by metric_name
                '''
                query_params = self.query_params.copy()
                query_params['target'] = target_obj.host
                fetched_data = self.ch_client.select(sql, query_params=query_params)
                metric_ids = [metric_id[0] for metric_id in fetched_data]
                sorted_target_metrics[target_obj.n] = sorted([Metric.objects.get_or_create(
                    code=m)[0] for m in metric_ids], key=lambda m: m.code, reverse=False)
            return sorted_target_metrics
        except:
            logging.exception('Could not get sorted_target_metrics for job due to:', self.job_obj.n)
            return {}

    def metric_groups(self, target_n):
        """
        returns list of values
        :param target_n: Server NUMBER
        """
        try:
            metric_groups = []
            for metric_obj in self.sorted_target_metrics[target_n]:
                metric_groups.append(metric_obj.code.split(':')[0].split('_')[0])  # ':' for custom
            return metric_groups
        except:
            logging.exception('Could not get metric groups for monitoring aggregates for job %s', self.job_obj.n)
            return []

    def metric_names(self, target_n):
        """
        returns list of values
        :param target_n: Server NUMBER
        """
        try:
            metric_names = []
            for metric_obj in self.sorted_target_metrics[target_n]:
                if ':' not in metric_obj.code:
                    metric_names.append(metric_obj.code[metric_obj.code.find('_') + 1:])
                else:
                    metric_names.append(metric_obj.code[metric_obj.code.find(':') + 1:])
            return metric_names
        except:
            logging.exception('Could not get metric names for monitoring aggregates for job %s', self.job_obj.n)
            return []


class MultitagTable(Table):
    delimiter = '|'

    @property
    @Memoize
    def tags(self):
        """
        multitags are got from cases where there is a delimiter;
        some responses can have more then 1 tag;
        i.e. case == 'tag1<delimiter>tag2'
        """
        tags = []
        for case in self.job_obj.cases:
            tags.extend(case.split(self.delimiter))
        logging.info("Multitags for job %s are: %s", self.job_obj.n, tags)
        return sorted([tag for tag in set(tags)])


class MultitagDistTable(MultitagTable):
    title = u"Responses count per tag distribution"

    def get_tag_avg_times(self, tag):
        """
        weighs times on the quantity of responses
        """
        try:
            sql = '''
                select toFloat32(sum(resps)), 
                toFloat32(sumArray([connect_time_sum, send_time_sum, latency_sum, receive_time_sum]))/1000/toFloat32(sum(resps)),
                toFloat32(sum(connect_time_sum))/1000/toFloat32(sum(resps)),
                toFloat32(sum(send_time_sum))/1000/toFloat32(sum(resps)),
                toFloat32(sum(latency_sum))/1000/toFloat32(sum(resps)),
                toFloat32(sum(receive_time_sum))/1000/toFloat32(sum(resps))
                from loaddb.rt_microsecond_details_buffer
                where job_id=%(job)s 
                and job_date=toDate(%(job_date)s)
                and tag in (%(cases_with_tag)s)
                and time >= toDateTime(%(start)s) 
                and time <= toDateTime(%(end)s)
            '''
            query_params = self.query_params.copy()
            query_params['cases_with_tag'] = ','.join(
                ["'" + case + "'" for case in self.job_obj.cases if tag in case.split('|')])
            fetched_data = self.ch_client.select(sql, query_params=query_params)
            resps_count = sum([value[0] for value in fetched_data])
            data = [
                resps_count,
                round(sum([value[1] * value[0] for value in fetched_data]) / resps_count, 3),
                round(sum([value[2] * value[0] for value in fetched_data]) / resps_count, 3),
                round(sum([value[3] * value[0] for value in fetched_data]) / resps_count, 3),
                round(sum([value[4] * value[0] for value in fetched_data]) / resps_count, 3),
                round(sum([value[5] * value[0] for value in fetched_data]) / resps_count, 3),
            ]
            return data
        except:
            logging.exception("Could not get avg times for %s for job % for tag %s, due to:", self.__class__.__name__,
                              self.job_obj.n, tag)
            return []

    def get_columns(self):
        """
        returns list of http codes and it's count
        """
        data = OrderedDict()
        for tag in self.tags:
            data[tag] = {}
            avg_times_data = self.get_tag_avg_times(tag)
            try:
                data[tag]['count'] = avg_times_data[0]
            except:
                data[tag]['count'] = 0.0
            try:
                data[tag]['expect'] = avg_times_data[1]
            except:
                data[tag]['expect'] = 0.0
            try:
                data[tag]['connect_time'] = avg_times_data[2]
            except:
                data[tag]['connect_time'] = 0.0
            try:
                data[tag]['send_time'] = avg_times_data[3]
            except:
                data[tag]['send_time'] = 0.0
            try:
                data[tag]['latency'] = avg_times_data[4]
            except:
                data[tag]['latency'] = 0.0
            try:
                data[tag]['receive_time'] = avg_times_data[5]
            except:
                data[tag]['receive_time'] = 0.0

        # form data
        columns_data = [
            {'weight': 'bold', 'align': 'left', 'title': u' ',
             'values': [key for key in data.keys() if key]},
            {'align': 'right', 'title': u'Count', 'values': [data[key]['count'] for key in data.keys()]},
            {'align': 'right', 'title': u'Overall Time',
             'values': [str(data[key]['expect']) + ' ms' for key in data.keys()]},
            {'align': 'right', 'title': u'Connect Time',
             'values': [str(data[key]['connect_time']) + ' ms' for key in data.keys()]},
            {'align': 'right', 'title': u'Send Time',
             'values': [str(data[key]['send_time']) + ' ms' for key in data.keys()]},
            {'align': 'right', 'title': u'Latency',
             'values': [str(data[key]['latency']) + ' ms' for key in data.keys()]},
            {'align': 'right', 'title': u'Receive Time',
             'values': [str(data[key]['receive_time']) + ' ms' for key in data.keys()]},
        ]
        logging.debug('Got resps count for job %s', self.job)
        return columns_data


class MultitagCumulativeQuantilesTable(MultitagTable):
    title = u'Cumulative quantriles per tag'
    quantiles = '99%', '98%', '95%', '90%', '85%', '80%', '75%', '50%'

    def get_data_values(self, tag):
        """
        gets data for non-precise quantiles for cases and different time intervals.
        """
        sql = '''select 
            quantilesExactWeighted(0.5, 0.75, 0.8, 0.85, 0.9, 0.95, 0.98, 0.99)(bin, cnt)
            from loaddb.rt_microsecond_histograms_buffer
            where job_id=%(job)s 
            and job_date = toDate(%(job_date)s)
            and tag in (%(cases_with_tag)s)
            and time >= toDateTime(%(start)s) 
            and time <= toDateTime(%(end)s)
            '''
        query_params = self.job_obj.basic_query_params.copy()
        query_params.update({
            'cases_with_tag': ','.join(["'" + case + "'" for case in self.job_obj.cases if
                                        tag in case.split(self.delimiter)]),
            'start': self.slider_start,
            'end': self.slider_end
        })
        raw_data = self.ch_client.select(sql, query_params=query_params)
        quantiles = [float(d) / 1000 for d in raw_data[0][0][::-1]] if raw_data and raw_data[0] else [0] * len(
            self.rows.keys())
        logging.debug('Got data_values for %s for job %s: %s', self.__class__.__name__, self.job, quantiles)
        return dict(izip(self.quantiles, quantiles))

    def get_columns(self):
        """
        returns list of http codes and it's count
        """
        columns_data = [
            {'weight': 'bold', 'align': 'left', 'title': u' ',
             'values': self.tags},
        ]
        tags_data = {tag: self.get_data_values(tag) for tag in self.tags}
        for quantile in self.quantiles:
            column = [{'align': 'right', 'title': quantile, 'values': [tags_data[tag][quantile] for tag in self.tags]}]
            columns_data += column
        logging.debug('Got net_codes count per tag for job %s', self.job)
        return columns_data


class MultitagHttpCodesTable(MultitagTable):
    title = u'HTTP codes per tag'

    def get_httpcode_data(self):
        data = []
        for tag in self.tags:
            sql = '''select code, toFloat32(sum(cnt))
                    from loaddb.proto_codes_buffer
                    where job_id=%(job)s 
                    and job_date = toDate(%(job_date)s)
                    and tag in (%(cases_with_tag)s)
                    and time >= toDateTime(%(start)s) 
                    and time <= toDateTime(%(end)s)
                    group by code'''
            query_params = self.job_obj.basic_query_params.copy()
            query_params.update({
                'cases_with_tag': ','.join(["'" + case + "'" for case in self.job_obj.cases if
                                            tag in case.split(self.delimiter)]),
                'start': self.slider_start,
                'end': self.slider_end
            })
            fetched_data = self.ch_client.select(sql, query_params=query_params)
            data.extend([[tag] + list(d) for d in fetched_data])
        return data

    def get_columns(self):
        """
        returns list of http codes and it's count
        """
        data = self.get_httpcode_data()
        http_codes = sorted(list(set([c[1] for c in data])))
        columns_data = [
            {"weight": "bold", "align": "left", "title": u" ",
             "values": self.tags},
        ]
        for code in http_codes:
            column = {"align": "right", "title": str(code), "values": []}
            for tag in self.tags:
                tag_val = 0
                i = 0
                while i < len(data):
                    if data[i][1] == code and data[i][0] == tag:
                        tag_val += data[i][2]
                    i += 1
                column["values"].append(tag_val)
            columns_data.append(column)
        logging.debug("Got http_codes count per tag for job %s", self.job)
        return columns_data


class MultitagNetCodesTable(MultitagTable):
    title = u"Net codes per tag"

    def get_netcode_data(self):
        data = []
        for tag in self.tags:
            sql = '''select code, toFloat32(sum(cnt))
                    from loaddb.net_codes_buffer
                    where job_id=%(job)s 
                    and job_date = toDate(%(job_date)s)
                    and tag in (%(cases_with_tag)s)
                    and time >= toDateTime(%(start)s) 
                    and time <= toDateTime(%(end)s)
                    group by code'''
            query_params = self.job_obj.basic_query_params.copy()
            query_params.update({
                'cases_with_tag': ','.join(["'" + case + "'" for case in self.job_obj.cases if
                                            tag in case.split(self.delimiter)]),
                'start': self.slider_start,
                'end': self.slider_end
            })
            fetched_data = self.ch_client.select(sql, query_params=query_params)
            data.extend([[tag] + list(d) for d in fetched_data])
        return data

    def get_columns(self):
        """
        returns list of http codes and it's count
        """
        data = self.get_netcode_data()
        net_codes = sorted(list(set([c[1] for c in data])))
        columns_data = [
            {'weight': 'bold', 'align': 'left', 'title': u' ',
             'values': self.tags},
        ]
        for code in net_codes:
            column = {'align': 'right', 'title': str(code), 'values': []}
            for tag in self.tags:
                tag_val = 0
                i = 0
                while i < len(data):
                    if data[i][1] == code and data[i][0] == tag:
                        tag_val += data[i][2]
                    i += 1
                column['values'].append(tag_val)
            columns_data.append(column)
        logging.debug('Got net_codes count per tag for job %s %s', self.job, columns_data)
        return columns_data
