from saas_deploy.cluster.get_cluster_data import get_conf as get_conf_raw
from saas_deploy.cluster.alerts_commands import get_alerts_conf as get_conf
from saas_deploy.cluster.get_cluster_data import get_default_alerts_conf
from saas_deploy.cluster.get_cluster_data import set_alerts_conf as set_conf

from django.core.cache import cache

from collections import OrderedDict
import copy
import json

DIS_KEY = 'disable_notify'
CALL_KEY = 'must_call'


def SIGNALS():
    signals = cache.get('sigkeys-list')
    if signals:
        return signals
    txt_signals, err = get_conf_raw('', 'alert_keys.json')
    signals = json.loads(txt_signals)
    if err:
        raise Exception("cannot get sigkeys, %s" % err)
    if 'keys' not in signals or not signals['keys']:
        raise Exception('empty sigkeys list, %s' % signals)
    cache.set('sigkeys-list', signals['keys'], 120)
    return signals['keys']


def alert_keys_from_conf(conf, list_all=False, is_meta=False):
    if 'all_signals' in conf:
        keys = conf['all_signals']
    else:
        keys = (conf.get('default_signals') or []) + (conf.get('add_signals') or [])
    if list_all:
        keys.extend([k for k in conf.get('data', [])])
    if is_meta:
        keys = [k for k in keys if not SIGNALS().get(k, {}).get('exclude_meta')]
    return list(set(keys))


def flaps_from_conf(conf, sigkey):
    flaps = conf['data'].get(sigkey, {}).get('flaps')
    if not flaps:
        flaps = conf.get('default_flaps')
    return flaps


def ring_times_from_conf(conf, sigkey):
    has_own_times = 'phone_times' in conf['data'].get(sigkey, {})
    if not has_own_times:
        times = conf.get('default_phone_times')
        return times
    times = conf['data'].get(sigkey, {})['phone_times']
    if not times:
        return {}
    return times


def is_users_from_conf(conf, sigkey):
    return conf['data'].get(sigkey, {}).get('is_users', False)


def logins_from_conf(conf, is_user=False, sigkey=''):
    if sigkey:
        is_user = is_users_from_conf(conf, sigkey)
    users = []
    if is_user:
        users = conf.get('user_resps') or []
    if not users:
        users = conf.get('default_resps') or []
    if 'saas-robot' not in users:
        users.append('saas-robot')
    return users


def should_have_golem(conf, sigkey):
    if CALL_KEY in conf:
        return conf[CALL_KEY]
    if sigkey and CALL_KEY in conf.get('data', {}).get(sigkey):
        return conf['data'][sigkey][CALL_KEY]
    return not is_users_from_conf(conf, sigkey)


def should_have_juggler(conf, sigkey):
    if conf.get(DIS_KEY):
        return False
    if sigkey and conf.get('data', {}).get(sigkey).get(DIS_KEY):
        return False
    return True


def join_conf(defalt, sconf):
    conf = copy.deepcopy(defalt)
    for key, val in sconf.items():
        if key != 'data':
            conf[key] = val
        else:
            conf['data'] = conf.get('data', {})
            for skey, sdata in val.items():
                conf['data'][skey] = conf['data'].get(skey, {})
                conf['data'][skey].update(sdata)
    return conf


def sorted_conf(conf):
    od = OrderedDict(sorted(conf.items(), key=lambda x: x[0].replace('data', 'z')))
    if 'data' in conf:
        od['data'] = OrderedDict(sorted(conf['data'].items()))
    return od


def get_alerts_conf(service, ctype):
    if service in ('default', 'defaults', 'common'):
        res = get_default_alerts_conf()
        if res['success']:
            res['conf_parts'] = {'service_conf': res['conf']}
        return res

    res = get_conf(service, ctype)
    return res


def patch_conf_field(alert_key, conf, full_conf, subject, fields,
                     do_add=False, is_sla_only=False, is_default=False):
    if subject == 'limits':
        subject_new = {'warn': fields['warn'],
                       'crit': fields['crit']}
        if fields.get('avgsec'):
            subject_new['avgsec'] = fields['avgsec']
    elif subject == 'flaps':
        subject_new = {'critical_time': fields['critical_time'],
                       'stable_time': fields['stable_time'],
                       'boost_time': fields['boost_time']}
    elif subject == 'phone_times':
        if fields:
            subject_new = {'time_start': fields['time_start'],
                           'time_end': fields['time_end']}
        else:
            subject_new = {}
    elif subject == DIS_KEY:
        subject_new = fields
    elif subject == 'is_users':
        subject_new = fields
    else:
        subject_new = ''
    if alert_key in alert_keys_from_conf(full_conf):
        if alert_key in full_conf.get('data', {}):
            if subject == 'limits' and full_conf['data'][alert_key].get(subject, {}) == subject_new:
                return {'success': True, 'result': 'fields not changed, nothing to patch'}
            if subject == 'flaps' and flaps_from_conf(full_conf, alert_key) == subject_new:
                return {'success': True, 'result': 'fields not changed, nothing to patch'}
            if subject == 'phone_times' and full_conf['data'][alert_key].get(subject, {}) == subject_new:
                return {'success': True, 'result': 'fields not changed, nothing to patch'}
            if subject == DIS_KEY and full_conf['data'][alert_key].get(subject, 0) == fields:
                return {'success': True, 'result': 'fields not changed, nothing to patch'}
            if subject == 'is_users' and full_conf['data'][alert_key].get(subject, 0) == fields:
                return {'success': True, 'result': 'fields not changed, nothing to patch'}

    if alert_key not in full_conf.get('all_signals', []) and not is_default:
        conf['add_signals'] = conf.get('add_signals', []) + [alert_key, ]
    if is_default and do_add and not is_sla_only and alert_key not in conf.get('default_signals', []):
        conf['default_signals'] = conf.get('default_signals', [])
        conf['default_signals'].append(alert_key)
    if is_default and is_sla_only and alert_key not in (conf.get('if_sla_signals') or []):
        conf['if_sla_signals'] = conf.get('if_sla_signals') or []
        conf['if_sla_signals'].append(alert_key)

    if 'data' not in conf:
        conf['data'] = {}
    if alert_key not in conf['data']:
        conf['data'][alert_key] = {}
    conf['data'][alert_key][subject] = subject_new
    return {'success': True, 'changed': True}


def patch_conf(service, alert_key, fields, do_add=False, is_sla_only=False, login='unknown'):
    conf = get_alerts_conf(service, '')
    if not conf['success']:
        return conf
    full_conf = conf['conf']
    conf = conf['conf_parts']['service_conf']
    changed = False
    p_res = {}
    for subject, field in fields.items():
        p_res = patch_conf_field(alert_key,
                                 conf, full_conf,
                                 subject, field,
                                 do_add, is_sla_only,
                                 is_default=(service == 'defaults'))
        if not p_res.get('success'):
            return p_res
        if p_res.get('changed'):
            changed = True
    if not changed:
        return p_res
    send_res = set_conf(service, sorted_conf(conf), login)
    return send_res


def patch_conf_common(service, fields, subject, login):
    conf = get_alerts_conf(service, '')
    if not conf['success']:
        return conf
    # full_conf = conf['conf']
    conf = conf['conf_parts']['service_conf']
    if subject == DIS_KEY:
        if conf.get(DIS_KEY) == fields:
            return {'success': True, 'result': 'nothing to change'}
        conf[DIS_KEY] = fields
        send_res = set_conf(service, sorted_conf(conf), login)
        return send_res
    else:
        return {'success': False, 'error': 'unknown subject for common section'}
