from ConfigParser import ConfigParser
import imp
import json
import os
import uuid

from dogapi import dog_http_api as datadog

ROOT = os.path.dirname(__file__)

aggregation_key = uuid.uuid4().hex

parser = ConfigParser()
parser.read(os.path.join(ROOT, 'datadog.ini'))

def section(name):
    return dict(parser.items(name))

config = section('api')
datadog.api_key = config['api_key']
datadog.application_key = config['application_key']
if 'timeout' in config:
    datadog.timeout = int(config['timeout'])

events = section('events')
hooks = None
if 'hooks' in events:
    hooks_path = os.path.join(ROOT, events['hooks'])
    if os.path.isfile(hooks_path):
        with open(hooks_path) as f:
            hooks_name = os.path.basename(events['hooks'])
            parts = hooks_name.rpartition('.')
            module_name, suffix = (parts[0], '.'+parts[2]) if '.' in hooks_name else (module_name, '')
            hooks = imp.load_module(module_name, f, hooks_name, ('.py', 'r', imp.PY_SOURCE))

def event(title, tag, alert_type, text='', host=None):
    if hooks is None or hooks.enabled():
        tags = ['ansible:%s' % tag]
        if host is not None:
            if hasattr(hooks, 'get_host'):
                host = hooks.get_host(host)
            tags.append('host:%s' % host)
        datadog.event(
            title=title,
            text=text,
            tags=tags,
            alert_type=alert_type,
            aggregation_key=aggregation_key,
            source_type_name='ansible')

def pretty_print(data):
    return json.dumps(data, sort_keys=True, indent=4)

# TODO get priority, alert type via config/hooks
# TODO suppress events via config
# TODO events for rest of callbacks

class CallbackModule(object):
    def runner_on_failed(self, host, res, ignore_errors=False):
        # TODO don't swallow
        if not ignore_errors:
            event(
                title='Ansible task failed: %s' % res['invocation']['module_name'],
                text=pretty_print(res),
                host=host,
                alert_type='error',
                tag='failed')

    def runner_on_ok(self, host, res):
        changed = 'changed' if res.pop('changed', False) else 'ok'
        event(
            title='Ansible task %s: %s' % (changed, res['invocation']['module_name']),
            text=pretty_print(res),
            host=host,
            alert_type='info',
            tag=changed)

    def runner_on_error(self, host, msg):
        event(
            title='Ansible task errored',
            text=msg,
            host=host,
            alert_type='error',
            tag='errored')

    def runner_on_skipped(self, host, item=None):
        event(
            title='Ansible task skipped',
            text="Item: '%s'" % item,
            host=host,
            alert_type='info',
            tag='skipped')

    def runner_on_unreachable(self, host, res):
        event(
            title='Ansible task host unreachable: %s' % host,
            text=pretty_print(res),
            host=host,
            alert_type='error',
            tag='unreachable')

    def runner_on_no_hosts(self):
        pass

    def runner_on_async_poll(self, host, res, jid, clock):
        pass

    def runner_on_async_ok(self, host, res, jid):
        pass

    def runner_on_async_failed(self, host, res, jid):
        pass

    def playbook_on_start(self):
        event(
            title="Ansible playbook started",
            alert_type='info',
            tag='playbook_start')

    def playbook_on_notify(self, host, handler):
        pass

    def playbook_on_no_hosts_matched(self):
        pass

    def playbook_on_no_hosts_remaining(self):
        pass

    def playbook_on_task_start(self, name, is_conditional, skipped):
        if not skipped:
            event(
                title="Ansible task started%s: '%s'" % (' (conditional)' if is_conditional else '', name),
                alert_type='info',
                tag='task_start')

    def playbook_on_vars_prompt(self, varname, private=True, prompt=None, encrypt=None, confirm=False, salt_size=None, salt=None, default=None):
        pass

    def playbook_on_setup(self):
        pass

    def playbook_on_import_for_host(self, host, imported_file):
        pass

    def playbook_on_not_import_for_host(self, host, missing_file):
        pass

    def playbook_on_play_start(self, pattern):
        event(
            title="Ansible play started: '%s'" % pattern,
            alert_type='info',
            tag='play_start')

    def playbook_on_stats(self, stats):
        event(
            title="Ansible play complete",
            text="""total: {0}
ok: {1}
changed: {2}
unreachable: {3}
failed: {4}
skipped: {5}""".format(stats.processed, stats.ok, stats.changed, stats.dark, stats.failures, stats.skipped),
            alert_type='info',
            tag='play_complete')