#!/usr/bin/env python

import os
import sys
import argparse
import json
import urllib2
import sleekxmpp

if sys.version_info < (3, 0):
    from sleekxmpp.util.misc_ops import setdefaultencoding
    setdefaultencoding('utf8')
else:
    raw_input = input


class MUCBot(sleekxmpp.ClientXMPP):

    def __init__(self, jid, password, room, nick, message):
        sleekxmpp.ClientXMPP.__init__(self, jid, password)
        self.room = room
        self.nick = nick
        self.msg = message
        self.add_event_handler("session_start", self.start)

    def start(self, event):
        self.get_roster()
        self.send_presence()
        self.plugin['xep_0045'].joinMUC(self.room, self.nick, wait=True)
        self.send_message(mto=self.room, mbody=self.msg, mtype='groupchat')
        self.disconnect(wait=True)


def send_chat_message(message):
    xmpp = MUCBot('{{ jabber_id }}', '{{ jabber_pwd }}', '{{ jabber_room }}', 'Nagios', message)
    xmpp.registerPlugin('xep_0030')
    xmpp.registerPlugin('xep_0045')
    xmpp.registerPlugin('xep_0199')

    if xmpp.connect():
        xmpp.process(block=True)
    else:
        pass


def archive_host_alert(args):
    bug = {'issue': {'project_id': 14, 'tracker_id': 1, 'category_id': 48, 'priority_id': 4}}
    bug['issue']['subject'] = "** %s Host Alert: %s is %s **" % (args.notification_type, args.hostname, args.state)
    bug['issue']['description'] = """***** Nagios *****

Notification Type: %s
Host: %s
State: %s
Address: %s
Info: %s

Date/Time: %s
""" % (args.notification_type, args.hostname, args.state, args.host_address, args.info, args.date)

    headers = {'Content-type': 'application/json', 'X-Redmine-API-Key': '{{ redmine_api_key }}'}
    request = urllib2.Request('https://support.forgeservicelab.fi/issues.json', json.dumps(bug), headers)
    response = json.loads(urllib2.urlopen(request).read())

    tmpfile = open('/usr/local/nagios/var/redmine.bugs/%s' % args.hostname.replace(' ', '-'), 'a')
    tmpfile.write('%s\n' % response['issue']['id'])
    tmpfile.close()

    send_chat_message(bug['issue']['subject'])


def archive_service_alert(args):
    bug = {'issue': {'project_id': 14, 'tracker_id': 1, 'category_id': 48}}
    bug['issue']['subject'] = "** %s Service Alert: %s/%s is %s **" % (args.notification_type, args.host_alias,
                                                                       args.service, args.state)
    bug['issue']['description'] = """***** Nagios *****

Notification Type: %s

Service: %s
Host: %s
Address: %s
State: %s

Date/Time: %s

Additional Info:
""" % (args.notification_type, args.service, args.host_alias, args.host_address, args.state, args.date)

    infolines = args.info.split(r'\n')
    bug['issue']['description'] += infolines[0] + '\n\n'
    if len(infolines[1:]):
        for item in infolines[1].split():
            bug['issue']['description'] += '| %s ' % item
        bug['issue']['description'] += '|\n| --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- |\n'
        for line in infolines[2:]:
            if len(line.split()):
                for item in line.split():
                    bug['issue']['description'] += '| %s ' % item
                bug['issue']['description'] += '|\n'

    if (args.state == 'CRITICAL'):
        bug['issue']['priority_id'] = 4
    elif (args.state == 'WARNING'):
        bug['issue']['priority_id'] = 2
    else:
        bug['issue']['priority_id'] = 1

    headers = {'Content-type': 'application/json', 'X-Redmine-API-Key': '{{ redmine_api_key }}'}
    request = urllib2.Request('https://support.forgeservicelab.fi/issues.json', json.dumps(bug), headers)
    response = json.loads(urllib2.urlopen(request).read())

    tmpfile = open('/usr/local/nagios/var/redmine.bugs/%s_%s' %
                   (args.host_alias.replace(' ', '-'), args.service.replace(' ', '-')), 'a')
    tmpfile.write('%s\n' % response['issue']['id'])
    tmpfile.close()

    send_chat_message(bug['issue']['subject'])


def find_open_issues(hostname, service):
    issues = []
    try:
        path = '/usr/local/nagios/var/redmine.bugs/%s' % (hostname.replace(' ', '-') if service is None
                                                          else '%s_%s' % (hostname.replace(' ', '-'),
                                                                          service.replace(' ', '-')))
        tmpfile = open(path, 'r')
        issues = tmpfile.readlines()
        tmpfile.close()
        if len(issues):
            os.remove(path)
    except IOError:
        pass
    return [issue.strip() for issue in issues]


def clear_alert(hostname, service):
    data = {'issue': {'status_id': 5}}
    if service is None:
        data['issue']['notes'] = 'Host recovered'
    else:
        data['issue']['notes'] = 'Service recovered'
    headers = {'Content-type': 'application/json', 'X-Redmine-API-Key': '{{ redmine_api_key }}'}
    opener = urllib2.build_opener(urllib2.HTTPHandler)
    for issue in find_open_issues(hostname, service):
        request = urllib2.Request('https://support.forgeservicelab.fi/issues/%s.json' %
                                  issue, json.dumps(data), headers)
        request.get_method = lambda: 'PUT'
        opener.open(request)

        send_chat_message('Issue #%s closed: %s' % (issue, data['issue']['notes']))


def process_host(args):
    if (args.state == 'DOWN'):
        archive_host_alert(args)
    else:
        clear_alert(args.hostname, None)


def process_service(args):
    if not (args.state == 'OK'):
        archive_service_alert(args)
    else:
        clear_alert(args.host_alias, args.service)

if __name__ == '__main__':
    PARSER = argparse.ArgumentParser()

    PARSER.add_argument('-n', '--notification_type')
    PARSER.add_argument('-H', '--hostname')
    PARSER.add_argument('-S', '--service')
    PARSER.add_argument('-a', '--host_alias')
    PARSER.add_argument('-u', '--host_address')
    PARSER.add_argument('-s', '--state')
    PARSER.add_argument('-i', '--info')
    PARSER.add_argument('-d', '--date')

    ARGUMENTS = PARSER.parse_args()

    if not (ARGUMENTS.service):
        process_host(ARGUMENTS)
    else:
        process_service(ARGUMENTS)

    if (len(sys.argv) == 1):
        print sys.argv[0] + ':  Could not parse arguments'
        exit(-1)
