#!/usr/bin/python3

import argparse
import yaml
import os
from jinja2 import FileSystemLoader, Environment
import jenkins
import logging


class LoaderMeta(type):

    def __new__(metacls, __name__, __bases__, __dict__):
        """Add include constructer to class."""

        # register the include constructor on the class
        cls = super().__new__(metacls, __name__, __bases__, __dict__)
        cls.add_constructor('!include', cls.construct_include)

        return cls


class Loader(yaml.Loader, metaclass=LoaderMeta):
    """YAML Loader with `!include` constructor."""

    def __init__(self, stream):
        """Initialise Loader."""

        try:
            self._root = os.path.split(stream.name)[0]
        except AttributeError:
            self._root = os.path.curdir

        super().__init__(stream)

    def construct_include(self, node):
        if isinstance(node, yaml.ScalarNode):
            return self.extractFile(self.construct_scalar(node))

        elif isinstance(node, yaml.SequenceNode):
            result = []
            for filename in self.construct_sequence(node):
                result += self.extractFile(filename)
            return result

        elif isinstance(node, yaml.MappingNode):
            result = {}
            for k,v in self.construct_mapping(node).iteritems():
                result[k] = self.extractFile(v)
            return result

        else:
            print("Error:: unrecognised node type in !include statement")
            raise yaml.constructor.ConstructorError


    def extractFile(self, filename):
        filepath = os.path.join(self._root, filename)
        with open(filepath, 'r') as f:
            return yaml.load(f, Loader=Loader)


def jinja2_from_template(directory, template_name, data, dryrun=False):
    loader = FileSystemLoader(directory)
    env = Environment(loader=loader)
    template = env.get_template(template_name)
    return template.render(hosts=data, dryrun=dryrun)


def get_parser():
    parser = argparse.ArgumentParser()
    parser.add_argument('-u', '--username', type=str,
                        default=os.environ.get('JJB_USER'),
                        help='Username for Jenkins server')
    parser.add_argument('-p', '--password', type=str,
                        default=os.environ.get('JJB_PASSWORD'),
                        help='Password for Jenkins server')
    parser.add_argument('-s', '--server', type=str,
                        default='http://localhost:8080',
                        help='Jenkins server URL. e.g. http://localhost:8080')
    parser.add_argument('-i', '--inventory', type=str, default='hosts',
                        help='specify inventory host path')
    parser.add_argument('-l', '--loglevel', default='INFO',
                        help="Setting logging level, default: %(default)s")
    parser.add_argument('--dryrun', action='store_true',
                        help='Do not publish to Jenkins')
    parser.add_argument('--local', action='store_true',
                        help='Create tmp file only, to be used with dryrun.')
    return parser


if __name__ == '__main__':
    parser = get_parser()
    args = parser.parse_args()
    logging.basicConfig(level=args.loglevel)
    with open(args.inventory, 'r') as f:
        data = yaml.load(f, Loader=Loader)
    logging.debug(data)
    template_output = jinja2_from_template(
                      './templates',
                      'configure-yadocker-cloud.groovy.j2', data)

    if not args.local:
        server = jenkins.Jenkins(args.server, username=args.username,
                             password=args.password)
    if args.dryrun:
        with open('/tmp/configure-yadocker-cloud.groovy', 'w') as fw:
            fw.write(template_output)
        template_output = jinja2_from_template(
                          './templates',
                          'configure-yadocker-cloud.groovy.j2', data, args.dryrun)
        if not args.local:
            publishdry = server.run_script(template_output)
            if 'error' in publishdry:
                logging.info(publishdry)
                exit(1)
            logging.info(publishdry)
        else:
            logging.info('Template file created at \
                    /tmp/configure-yadocker-cloud.groovy')
    else:
        publish = server.run_script(template_output)
        logging.info(publish)
