#!/usr/bin/env python
# -*- coding: utf-8 -*-
import os
import sys
# python 3 compatibility
try:
    import ConfigParser as configparser
except ImportError:
    import configparser

import sqlalchemy
import jinja2
import argparse
import logging
from logging.handlers import SysLogHandler


class NagiosGenerator(object):
    base_query = """
SELECT resources.title as title,
  GROUP_CONCAT(CONCAT(param_names.name, "\t", param_values.value)
    ORDER BY param_names.name ASC SEPARATOR "\n") AS service_content
FROM param_values
  JOIN param_names ON param_names.id = param_values.param_name_id
  JOIN resources ON param_values.resource_id = resources.id
WHERE param_names.name NOT IN ('ensure', 'target') AND resource_id IN
  (SELECT resource_id FROM param_values
    JOIN resources ON resource_id = resources.id
    JOIN param_names ON param_names.id = param_name_id
    WHERE restype = '%s' AND param_names.name = 'ensure' AND value = 'present')
GROUP BY resources.id ORDER BY resources.title ASC"""

    restype = {
        'services': 'Nagios_service',
        'hosts': 'Nagios_host',
        'hostextinfo': 'Nagios_hostextinfo'
    }

    restpl = {
        'services': """define service {
# --PUPPET_NAME-- {{ name }}
{% for line in data -%}
{%- if line[1] -%}
{{ "\t%-30s %s" % line }}
{%- endif %}
{% endfor %}
}
""",
        'hosts': """define host {
{% for line in data -%}
{{ "\t%-30s %s" % line }}
{% endfor %}
}
""",
        'hostextinfo': """define hostextinfo {
{% for line in data -%}
{{ "\t%-30s %s" % line }}
{% endfor %}
}
"""
    }

    def load_config(self, configfile):
        self.config = configparser.SafeConfigParser()
        self.config.read(configfile)
        self.dsn = "{}://{}:{}@{}:3306/puppet".format(
            self.config.get('master', 'dbadapter'),
            self.config.get('master', 'dbuser'),
            self.config.get('master', 'dbpassword'),
            self.config.get('master', 'dbserver')
        )

    def __init__(self, configfile, debug):
        self.log = logging.getLogger('naggen2')
        self.log.debug('Loading configfile %s', configfile)
        self.load_config(configfile)
        self.db_engine = sqlalchemy.create_engine(
            self.dsn,
            echo=debug
        )
        self.env = jinja2.Environment(
            loader=jinja2.DictLoader(self.restpl)
        )

    def _query(self, what):
        connection = self.db_engine.connect()
        connection.execute('set group_concat_max_len = @@max_allowed_packet')
        res = connection.execute(self.base_query % self.restype[what])
        connection.close()
        return res

    def render(self, what):
        if what not in self.restype:
            self.log.error('Exiting  - unsupported resource type %s', what)
            sys.exit(1)
        try:
            for entity in self._query(what):
                self.log.debug('Working on resource %s', entity['title'])
                content = [
                    tuple(i.split("\t"))
                    for i in entity['service_content'].split("\n")
                    if i]
                tpl = self.env.get_template(what)
                yield tpl.render(name=entity['title'], data=content)
        except Exception as e:
            self.log.exception(
                'Could not generate output for resource %s', what)
            sys.exit(30)


def main():
    parser = argparse.ArgumentParser()
    parser.add_argument('--type', '-t',
                        dest='type',
                        help="type of file to generate",
                        choices=['services', 'hosts', 'hostextinfo'])
    parser.add_argument(
        '--configfile', '-c', dest='configfile', default='/etc/puppet/puppet.conf')
    parser.add_argument('--debug', action='store_true', default=False)
    args = parser.parse_args()

    log_format='%(name)s: %(levelname)s - %(message)s'
    log = logging.getLogger('naggen2')

    if not args.debug:
        #if normal mode, log to syslog
        log.setLevel(logging.INFO)
        log.propagate = False
        handler = SysLogHandler(
                address='/dev/log',
                facility=SysLogHandler.LOG_LOCAL3)
        formatter = logging.Formatter(fmt=log_format)
        handler.setFormatter(formatter)
        log.addHandler(handler)
    else:
        #if debug mode, print to stderr
        logging.basicConfig(level=logging.DEBUG, format=log_format)

    log.info('Generating output for resource %s', args.type)
    n = NagiosGenerator(args.configfile, args.debug)
    for entity in n.render(args.type):
        print(entity)
    log.info('Run completed')

if __name__ == '__main__':
    main()
