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

@author: noob
"""

from common.models import Component, KPI
from common.views import get_common
from common.util.decorators import log_time
from django.core.exceptions import ObjectDoesNotExist
from django.http import HttpResponse, HttpResponseServerError, HttpResponseRedirect, \
    HttpResponseNotFound
from django.shortcuts import render_to_response, render
from django.template import RequestContext
from django_yauth.decorators import yalogin_required
from itertools import chain
from json import dumps
from mainpage.views import ProjectsProcessor
from operator import attrgetter
from regression.views.kpi_plots import ImbalanceKpiPlot, QuantilesKpiPlot, TrailKpiPlot, \
    NetCodesKpiPlot, HTTPCodesKpiPlot, TimeDistKpiPlot, MonitoringKpiPlot
from regression.views.sla_processor import ProjectSLAProcessor
import logging

PLOT_TYPES_MAPPING = {
    'imbalance': ImbalanceKpiPlot,
    'job_trail': QuantilesKpiPlot,
    'trail': TrailKpiPlot,
    'trail_net': NetCodesKpiPlot,
    'trail_resp': HTTPCodesKpiPlot,
    'trail_time': TimeDistKpiPlot,
    'monitoring': MonitoringKpiPlot,
}


@yalogin_required
@log_time
def overview(request, project, component=''):
    """

    :param request: HTTP Request
    :param project: string - project value passed in request
    :param component: Component NUMBER
    """
    project = project.upper()
    user = request.yauser
    # for links in offlinepage meta | url(r'^(\w+)/(\d+)', 'regression.views.overview.overview')
    if component:
        component_obj = Component.objects.get(n=int(component))
        if component_obj.services:
            service = component_obj.services[0]
        else:
            service = ''
    else:
        service = request.GET.get('service', '')
    common_data = get_common(request)
    common_for_regression = get_common_for_regression(project, service)
    if not common_for_regression['project']:
        user_projects = ProjectsProcessor(user)
        return render(request, 'error.html',
                      {'common': common_data, 'error': 'no_regress_project', 'erroneous_project': project,
                       'projects': user_projects.user_active_projects})

    if not Component.objects.filter(tag=project).count():
        return render_to_response('error.html', {'common': common_data, 'error': 'no_components',
                                                 'project': project},
                                  RequestContext(request))
    return render_to_response('overview.html', {
        'user': user,
        'common': common_data,
        'project': project,
        'services': common_for_regression['services'],
        'failed_services': get_failed_services(project),
        'tab': service,
        'component': component,
    }, RequestContext(request))


@yalogin_required
def no_project(request):
    user = request.yauser
    common_data = get_common(request)
    if request.method == 'POST':
        project = request.POST['project']
        project = project.upper()
        try:
            return HttpResponseRedirect('/regress/{}'.format(project))
        except ObjectDoesNotExist:
            user_projects = ProjectsProcessor(user)
            return render(request, 'error.html',
                          {'common': common_data, 'error': 'no_regress_project', 'erroneous_project': project,
                           'projects': user_projects.user_active_projects}
                          )
    elif request.method == "GET":
        user_projects = ProjectsProcessor(user)
        return render(request, 'error.html', {'common': common_data, 'error': 'no_regress_project',
                                              'projects': user_projects.user_active_projects}
                      )


def get_common_for_regression(tag, service=''):
    """
    Common data for regression pages
    :param tag: DicData OBJECT
    :param service: str

    """
    if tag:
        components = get_components(tag, service=service)
        services = get_services(tag)
        return {"project": tag, "components": components, 'services': services}
    else:
        return {"project": tag}


def get_components(tag, service=None):
    """
    returns queryset of Component objects
    :param tag: str Component.tag
    :param service: str
    """
    try:
        components = Component.objects.filter(tag=tag)
        if service:
            components = [c for c in components if service in c.services]
        else:
            components = [c for c in components]
        components = sorted(components, key=attrgetter('name'))
        return components
    except ObjectDoesNotExist:
        return None
    except:
        logging.exception("Could not get components for project {} due to:".format(tag))
        return None


def get_services(tag):
    """
    returns set of services
    :param tag: DicData OBJECT
    """
    try:
        components = Component.objects.filter(tag=tag)
        services = [[s for s in component.services if s]
                    for component in components
                    if component.services]
        return sorted(set(chain(*services)))
    except:
        logging.exception("Could not get services for project {} due to:".format(tag))
        return []


@log_time
def get_failed_services(tag):
    """
    checks SLA for services
    :param tag: 
    """
    try:
        failed_services = ProjectSLAProcessor(tag).check()["failed_services"]
        return failed_services
    except:
        logging.exception("Could not get failed services for project {} due to:".format(tag))
        return []


def delete_component(request, tag):
    """

    :param request: HTTP request
    :param tag: 
    """
    component = request.GET.get('component', 0)
    try:
        if component:
            KPI.objects.filter(component_id=int(component)).delete()
            component_obj = Component.objects.get(n=int(component))
            for job in component_obj.jobs:
                job.component = 0
                job.save()
            component_obj.delete()
        else:
            pass
        return HttpResponse('')
    except:
        logging.exception("Could not delete component {} due to:".format(component))
        return HttpResponseServerError()


def kpi_data(request, kpi):
    """

    :param request: HTTP Request
    :param kpi: KPI NUMBER
    """
    try:
        kpi_obj = KPI.objects.get(n=kpi)
        job_limit = request.GET.get('job_limit', 30)
        if job_limit == '-1':
            job_limit = None
        preview = bool(request.GET.get('preview'))
        plot = PLOT_TYPES_MAPPING[kpi_obj.ktype.split('__')[0]](kpi_obj, job_limit=job_limit, preview=preview)
        data = plot.data
    except ObjectDoesNotExist:
        return HttpResponseNotFound()
    return HttpResponse(dumps(data), content_type='application/json')
