from django.http import HttpResponse
from django.http import HttpResponseServerError, HttpResponseBadRequest
from django.template import RequestContext  # noqa
from django.shortcuts import render_to_response
from django.core.cache import cache  # noqa
from django.contrib import auth  # noqa
from django.utils.html import escape

from .caches import sla_table
from .caches import update_all as update_all_caches

from .cluster import get_cluster_data as cluster
from .cluster.get_cluster_data import get_root  # noqa

from .helpers import service_ctypes  # noqa
from .helpers import is_sla_ctype

from . import people

import traceback  # noqa
import datetime  # noqa
import time
import json

from collections import OrderedDict


def monitor_gui(request):
    services, serv_ct, slots, errors = cluster.get_services()
    service = request.GET.get('service', '')
    ctype = request.GET.get('ctype', '')
    kind = request.GET.get('kind', '')
    dc = request.GET.get('dc', '')
    allserv = request.GET.get('allserv', '')
    norm = request.GET.get('normalize', '')
    for k in serv_ct.keys():
        serv_ct[k] = sorted(serv_ct[k])
    slas = {}
    warnings = {}
    try:
        for ct in serv_ct.keys():
            if is_sla_ctype(ct):
                slt = sla_table(ct, False, True)
                if slt['success']:
                    slas[ct] = slt['result'].copy()
                else:
                    warnings['on_sla_' + ct] = slt.get('error', 'unknown error')
    except Exception as e:
        warnings['on_sla'] = '%s' % e
    other_ctypes = [ct for ct in serv_ct if ct not in ('stable', 'stable_kv', 'stable_middle_kv', 'stable_knn',
                                                       'stable_hamster', 'prestable', 'testing',
                                                       'inactive', 'metaservices', 'stable_gemini')]
    return render_to_response('monitor_custom.html', {'services': services, 'serv_ct': serv_ct, 'other_ctypes': other_ctypes,
                                                      'service': service, 'ctype': ctype, 'kind': kind, 'dc': dc,
                                                      'allserv': allserv,
                                                      'slas': slas,
                                                      'normalize': norm,
                                                      'show_sla': True,
                                                      'warnings': warnings})


def ctypes(request):
    res = cluster.get_ctypes()
    if res.get('success'):
        ct_communals = ('stable', 'stable_kv', 'stable_middle_kv', 'stable_hamster', 'prestable', 'testing')
        ctypes_list = res['result'][:]
        ctypes_srt = [ct for ct in ct_communals if ct in ctypes_list]
        ctypes_srt.extend(sorted([ct for ct in ctypes_list if ct.startswith('stable') and ct not in ct_communals]))
        ctypes_srt.extend(sorted([ct for ct in ctypes_list if not ct.startswith('stable') and ct not in ct_communals]))
        res['result'] = ctypes_srt
    return HttpResponse(json.dumps(res))


def show_sla_table(request):
    ctype = request.GET.get('ctype')
    login = request.yauser.login if request.yauser.is_authenticated() else 'unknown'
    ctypes_res = cluster.get_ctypes()
    if not ctypes_res['success']:
        return HttpResponseServerError(json.dumps(ctypes_res))
    ctypes = ctypes_res['result']
    ctypes = [ct for ct in ctypes if is_sla_ctype(ct)]

    sla_res = {}
    if ctype:
        slas = sla_table(ctype, False)
        if not slas['success']:
            return HttpResponseBadRequest(json.dumps(slas))
        sla_res = slas['result']
        for serv, sdata in sla_res.items():
            sdata['owners'] = [ow.split('@')[0] for ow in sdata.get('owners') or []]
            sdata['responsibles'] = [r.split('@')[0] for r in sdata.get('responsibles') or []]
        sla_res = OrderedDict(sorted(sla_res.items()))
    return render_to_response('sla_table.html', {'data': sla_res,
                                                 'login': login,
                                                 'ctype': ctype,
                                                 'ctypes': ctypes})


def service_sla(request):
    ctype = request.GET.get('ctype')
    service = request.GET.get('service')
    if not ctype or not service:
        return HttpResponseBadRequest('ctype or service not set')
    if service in ('searchproxy', 'indexerproxy', 'deploy_manager'):
        return HttpResponseBadRequest('no sla for non-rtyserver service_type')
    res = cluster.get_service_sla(service, ctype)
    return HttpResponse(json.dumps(res))


def set_sla(request):
    ctype = request.GET.get('ctype')
    service = request.GET.get('service')
    if not ctype or not service:
        return HttpResponseBadRequest('ctype or service not set')
    login = request.yauser.login if request.yauser.is_authenticated() else 'nologin'
    is_developer = people.is_saas_developer(login)
    if not is_developer:
        return HttpResponseBadRequest(
            json.dumps({'success': False, 'error': 'login ' + login + ' is not saas developer'}))
    try:
        fields = json.loads(request.body)
    except Exception as e:
        return HttpResponse(json.dumps({'success': False, 'error': '%s' % e, 'data': escape(request.body)}))
    res = cluster.set_sla(service, ctype, fields, login, is_patch=False)
    return HttpResponse(json.dumps(res))


def secret_keys(request):
    service = request.GET.get('service')
    if service in ('searchproxy', 'indexerproxy', 'deploy_manager'):
        return HttpResponseBadRequest('no secret_key for non-rtyserver service_type')
    res = cluster.secret_key(service)
    return HttpResponse(json.dumps(res))


def service_cluster_settings(request):
    service = request.GET.get('service')
    ctype = request.GET.get('ctype')
    service_type = request.GET.get('service_type', 'rtyserver')
    if service in ('searchproxy', 'indexerproxy', 'deploy_manager'):
        return HttpResponseBadRequest('no settings for non-rtyserver service_type')
    res = cluster.get_cluster_map(service, ctype, service_type)
    return HttpResponse(json.dumps(res))


def edit_service_cluster_settings(request):
    service = request.GET.get('service')
    ctype = request.GET.get('ctype')
    service_type = request.GET.get('service_type')
    service_info = request.GET.get('service_info')
    if service in ('searchproxy', 'indexerproxy', 'deploy_manager'):
        return HttpResponseBadRequest('no edit settings for non-rtyserver service_type')
    res = cluster.edit_cluster_map(service, ctype, service_type, service_info)
    return HttpResponse(json.dumps(res))


def update_caches(request):
    ctypes_res = cluster.get_ctypes()
    if not ctypes_res['success']:
        return HttpResponseServerError(json.dumps(ctypes_res))
    ctypes = ctypes_res['result']
    ctypes = [ct for ct in ctypes]
    res = update_all_caches(ctypes)
    return HttpResponse(json.dumps(res))


def service_cluster_info(request):
    service = request.GET.get('service')
    ctype = request.GET.get('ctype')
    is_rtyserver = service not in ('searchproxy', 'indexerproxy', 'deploy_manager')
    data = {'time': [int(time.time())]}
    if request.GET.get('format', '') == 'json':
        return HttpResponse(json.dumps(data))
    login = request.yauser.login if request.yauser.is_authenticated() else 'nologin'
    is_developer = people.is_saas_developer(login)
    return render_to_response('service_cluster_table.html', {'data': data, 'is_rty': is_rtyserver,
                                                             'service': service, 'ctype': ctype,
                                                             'login': login, 'is_root': is_developer})


def polynom_convertion(request):
    service = request.GET.get('service', '')
    do = request.GET.get('do')
    if do:
        action = request.GET.get('action', '')
        dm_addr = request.GET.get('dm')
        content = request.body.strip()
        if not action or not service:
            return HttpResponseBadRequest('service or action not set')
        res = cluster.fml_convert(service, action, content, dm_addr=dm_addr)
        if res['success']:
            return HttpResponse(res['ans'])
        else:
            return HttpResponseBadRequest(json.dumps(res))
    return render_to_response('polynom_converter.html', {'service': service})


def nanny_info(request):
    ctype = request.GET.get('ctype')
    service_type = request.GET.get('service_type') or 'rtyserver'
    res = cluster.get_nanny_files(ctype, service_type)
    if not res['success']:
        return HttpResponseBadRequest(json.dumps(res))
    res['ans']['services'] = sorted([{'service': s, 'data': d} for s, d in res['ans']['services'].items()], key=lambda x: x['service'])
    return render_to_response('files_info.html', {'data': res['ans'],
                                                  'ctype': ctype, 'service_type': service_type})


def enter_service(request):
    services, serv_ct, slots, errors = cluster.get_services()
    if request.GET.get('format', '') == 'json':
        if errors:
            return HttpResponseBadRequest(json.dumps({'success': False, 'errors': errors}))
        return HttpResponse(json.dumps({'success': True, 'result': serv_ct}))
    serv_inact = serv_ct.get('inactive')
    login = request.yauser.login if request.yauser.is_authenticated() else 'unauthorized'

    all_ctypes = [ct for ct in serv_ct.keys() if ct not in ['metaservices', 'inactive', 'maps']]
    sla_ctypes = [ct for ct in serv_ct.keys() if is_sla_ctype(ct)]
    get_mine = request.GET.get('my')
    if get_mine:
        sla_login = request.GET.get('test_login', '') if 'test_login' in request.GET else login
        if request.yauser.is_authenticated():
            slas = {}
            for ct in sla_ctypes:
                ctres = sla_table(ct, False)
                if not ctres['success']:
                    return HttpResponseBadRequest(json.dumps(ctres))
                slas[ct] = ctres['result'].copy()
            services = people.my_services(slas, sla_login)
            serv_inact = []
        else:
            errors['login_my'] = 'using "my services" with not authenticated user'

    def get_ctype(serv):
        for ct in ('stable', 'stable_kv', 'stable_middle_kv', 'stable_maps', 'stable_maps_kv',
                   'prestable', 'prestable_maps',
                   'testing'):
            if serv in serv_ct.get(ct, []):
                return ct
        return ''

    def get_ctypes(serv):
        res = []
        for ct, sct in serv_ct.items():
            if ct.startswith('stable') and serv in sct:
                res.append(ct)
        for ct, sct in serv_ct.items():
            if ct.startswith('prestable') and serv in sct:
                res.append(ct)
        for ct, sct in serv_ct.items():
            if ct != 'metaservices' and ct not in res and serv in sct:
                res.append(ct)
        return res
    services_show = [{'service': serv,
                      'ctypes': get_ctypes(serv),
                      'is_meta': serv in serv_ct.get('metaservices', [])}
                     for serv in services]
    return render_to_response('enter_service.html', {'services': services_show, 'slots': slots,
                                                     'serv_inact' : serv_inact,
                                                     'all_ctypes': all_ctypes, 'sla_ctypes': sla_ctypes,
                                                     'user': login,
                                                     'my': get_mine,
                                                     'errors': errors})


def service_info(request):
    service = request.GET.get('service')
    ctype = request.GET.get('ctype')
    if not service:
        return HttpResponseBadRequest(json.dumps({'error': 'service not specified'}))
    login = request.yauser.login if request.yauser.is_authenticated() else 'nologin'
    is_developer = people.is_saas_developer(login)
    is_rtyserver = service not in ('searchproxy', 'indexerproxy', 'deploy_manager')
    storage_data = {'path': 'configs/' + service, 'is_frame': True}
    return render_to_response('service_info.html', {'service': service, 'ctype': ctype,
                                                    'storage': storage_data,
                                                    'is_root': is_developer, 'is_rty': is_rtyserver})


def post_impl(request, dm_url):
    dm_url += '?' + request.GET.urlencode()
    content = ''

    if request.method == 'POST':
        content = request.body
    ans, errors = cluster.send_post(dm_url, content)
    # errors['method'] = request.method
    errors['content-length'] = len(content)

    if len(ans) > 0 and len(errors) == 1:
        return HttpResponse(ans)
    return HttpResponse(ans + ' ' + str(errors))


def deploy_page(request):
    service = request.GET.get('service')
    ctype = request.GET.get('ctype')
    login = request.yauser.login if request.yauser.is_authenticated() else 'nologin'
    is_developer = people.is_saas_developer(login)
    is_rtyserver = service not in ('searchproxy', 'indexerproxy', 'deploy_manager')

    return render_to_response('deploy.html', {'service': service, 'ctype': ctype,
                                              'is_rty': is_rtyserver,
                                              'is_root': is_developer})


def ping(request):
    return HttpResponse("ping: ok")
