

from .formats import JugglerInput
from .token import get_token

import json
import urllib
try:
    import urllib2
except:
    import urllib.request as urllib2

JUGGLER_BASE = 'http://juggler-api.search.yandex.net:8998'
GOLEM_BASE = 'http://ro.admin.yandex-team.ru'
GOLEM_BASE_WRITE = 'http://golem.yandex-team.ru'
GOLEM_HOST_PREFIX = 'saas_gen_'

DEFAULT_FLAPS = {'stable_time': 60, 'critical_time': 300}


def alert_key_from_juggler_tags(tags):
    skey_tag = [t for t in tags if t.startswith('saas_skey_')]
    return skey_tag[0].replace('saas_skey_', '') if skey_tag else ''


def alert_ctype_from_juggler_tags(tags):
    ctype_tag = [t for t in tags if t.startswith('saas_ctype_')]
    return ctype_tag[0].replace('saas_ctype_', '') if ctype_tag else ''


def alert_service_from_juggler_tags(tags):
    serv_tag = [t for t in tags if t.startswith('saas_service_')]
    return serv_tag[0].replace('saas_service_', '') if serv_tag else ''


def alert_is_users_from_juggler_tags(tags):
    return 'saas_group_users' in tags


def urlopen(url, data=None, headers=None):
    request = urllib2.Request(url=url, data=data, headers=headers or {})
    return urllib2.urlopen(request, timeout=60)


def _juggler_rpc(path, query=None, payload=None,
                 api_host=JUGGLER_BASE, format='json',
                 auth_header='juggler', retries=2):
    query = query or {}
    query_args = tuple(query.items() if isinstance(query, dict) else query)
    query_args += (('do', 1),)
    encoded_query = urllib.parse.urlencode(query_args, True)
    url = '%s/api/%s' % (api_host, path)
    if payload is not None:
        url = '%s?%s' % (url, encoded_query)
        data = json.dumps(payload)
        headers = {'Content-Type': 'application/json'}
    else:
        data = encoded_query
        headers = {'Content-Type': 'application/x-www-form-urlencoded'}
    if auth_header:
        auth_token = get_token(auth_header)
        if not auth_token:
            raise Exception('cannot find token for juggler')
        headers['Authorization'] = 'OAuth ' + auth_token
    error = ''
    for i in range(retries):
        try:
            uo = urlopen(url, data=data.encode('ascii'), headers=headers)
            return {'success': True,
                    'answer': json.load(uo) if format == 'json' else uo.read().decode('utf-8')}
        except urllib2.HTTPError as exc:
            error = 'API call %s(%s) raised HTTP error %s: %s' % (path, dict(query_args), exc.code, exc.read() or exc.reason)
        except Exception as exc:
            error = 'API call %s(%s) raised Exception: %s' % (path, dict(query_args), exc)
    return {'success': False, 'error': error}


def golem_create(host, resps):
    res = _juggler_rpc('proxy/golem/create_host', {'host_name': host, 'resps_list': resps})
    if not res['success']:
        raise Exception(res['error'])
    return res


def golem_exists(host):
    res = _juggler_rpc('proxy/golem/host_exists', {'host_name': host})
    if not res['success']:
        raise Exception(res['error'])
    return res['answer'] is True


def golem_resps(host):
    res = _juggler_rpc('get_host_resp.sbml', {'host': host},
                       api_host=GOLEM_BASE, format='plain')
    if not res['success']:
        raise Exception(res['error'])
    resps = res['answer'].strip().split(',')
    return resps


def golem_set_resps(host, resps):
    if 'saas-robot' not in resps:
        raise Exception('saas-robot must be in resps for authentification purpose')
    res = _juggler_rpc('set_object_resps.sbml',
                       payload={'object': host, 'resps': resps},
                       api_host=GOLEM_BASE_WRITE, auth_header='golem')
    if not res['success']:
        raise Exception(res['error'])
    return res


def golem_do_all(host, resps):
    if not golem_exists(host):
        golem_create(host, resps)
        return
    resp_ex = golem_resps(host)
    if resp_ex != resps:
        golem_set_resps(host, resps)


def ctype_from_host(golem_host):
    if golem_host.startswith(GOLEM_HOST_PREFIX):
        return golem_host.split('_')[2]
    return 'unknown'


def generate_check(service, ctype, skey, golovans, users, flaps=None, is_user=False):
    ji = JugglerInput()
    ji.GolemHost = GOLEM_HOST_PREFIX + ctype + '_' + service
    if is_user:
        ji.GolemHost += '_users'
    ji.JugglerId = 'saas_' + ctype + '_' + service + '_' + skey
    ji.Flaps = flaps or DEFAULT_FLAPS
    ji.GolovanIds = golovans
    ji.JugglerTags = ['saas_service_' + service,
                      'saas_ctype_' + ctype,
                      'saas_skey_' + skey,
                      'saas_autogen']
    group_j_tag = 'saas_group_users' if is_user else 'saas_group_dev'
    ji.JugglerTags.append(group_j_tag)
    ji.Users = users
    ji.RingTimes = {'time_start': '10:00', 'time_end': '23:00'}
    return ji


def set_check(juggler_input):
    golem_do_all(juggler_input.GolemHost, juggler_input.Users)
    res = _juggler_rpc('checks/add_or_update', payload=juggler_input.to_json())
    return res


def set_flap(g_host, juggler_id, flaps):
    data = {'host_name': g_host, 'service_name': juggler_id}
    data.update(flaps)
    res = _juggler_rpc('checks/set_flap', data)
    return res


def set_notify(g_host, juggler_id, template_name, options):
    data = {'host_name': g_host, 'service_name': juggler_id, 'template_name': template_name}
    data.update({'template_kwargs': json.dumps(options)})
    res = _juggler_rpc('checks/set_notify', data)
    return res


def remove_check(g_host='', juggler_id='', tags=''):
    data = {}
    if g_host:
        data['host_name'] = g_host
    if juggler_id:
        data['service_name'] = juggler_id
    if tags:
        if isinstance(tags, str):
            tags = [tags, ]
        data['tag_name'] = ' . '.join(tags)
    res = _juggler_rpc('checks/remove_check', data)
    return res


def extract_golovan_names(data):
    names = []
    for golem_host, gh_data in data.items():
        for juggler_id, jid_data in gh_data.items():
            for gs in jid_data['children']:
                names.append(gs['service'])
    return names


def extract_flaps(jid_data):
    return {'stable_time': jid_data.get('stable_time', 0),
            'critical_time': jid_data.get('critical_time', 0),
            'boost_time': jid_data.get('boost_time', 0)}


def extract_phone_times(jid_data):
    golem_notif = [nt for nt in jid_data['notifications']
                   if nt['template_name'] == 'phone_escalation']
    if not golem_notif:
        return {}
    g_tmpl = golem_notif[0]['template_kwargs']
    if 'time_start' in g_tmpl and 'time_end' in g_tmpl:
        return {'time_start': g_tmpl['time_start'], 'time_end': g_tmpl['time_end']}
    return {}


def extract_phone_users(jid_data):
    golem_notif = [nt for nt in jid_data['notifications']
                   if nt['template_name'] == 'phone_escalation']
    if not golem_notif:
        return {}
    g_tmpl = golem_notif[0]['template_kwargs']
    if 'logins' in g_tmpl:
        return g_tmpl['logins']
    return []


def fill_golem_resps(data):
    for golem_host, gh_data in data.items():
        try:
            resps = golem_resps(golem_host)
        except Exception as e:
            return {'success': False, 'error': '%s' % e, 'err_golem_host': golem_host}
        for juggler_id, jid_data in gh_data.items():
            jid_data['golem_resps'] = resps
    return {'success': True, 'data': data}


def get_all_checks():
    res = _juggler_rpc('checks/checks', {'tag_name': 'saas_autogen'}, auth_header=False)
    return res


def checks_by_ctype_service(input_checks=None, use_input=False):
    if not input_checks and not use_input:
        checks_res = get_all_checks()
        if not checks_res['success']:
            return checks_res
        checks = checks_res['answer']
    else:
        checks = input_checks
    res = {}
    for g_host, gh_data in checks.items():
        for juggler_id, jid_data in gh_data.items():
            tags = jid_data['tags']
            ctype = alert_ctype_from_juggler_tags(tags)
            res[ctype] = res.get(ctype, {})
            service = alert_service_from_juggler_tags(tags)
            res[ctype][service] = res[ctype].get(service, {})
            skey = alert_key_from_juggler_tags(tags)
            res[ctype][service][skey] = res[ctype][service].get(skey, [])
            res[ctype][service][skey].append({'juggler_id': juggler_id, 'data': jid_data})
    return {'success': True, 'checks': res}
