#!/usr/bin/python3 -O
# -*- coding: utf-8 -*-`
#
# vim: set ts=4 sw=4 sts=4 et :
'''
:maintainer:    Jason Mehring <nrgaway@gmail.com>
:maturity:      new
:depends:       none
:platform:      all

Dump a YAML configuration file to key = value pairs
'''

import argparse
import collections
import os
import sys
import yaml

from yaml.parser import ParserError
from yaml.reader import ReaderError

__version__ = '1.0.0'

# prefer C bindings over python when available
BaseLoader = getattr(yaml, 'CLoader', yaml.Loader)


def _ordered_load(stream,
                  Loader=BaseLoader,
                  object_pairs_hook=collections.OrderedDict):

    class OrderedLoader(Loader):
        pass

    def construct_mapping(loader, node):
        loader.flatten_mapping(node)
        return object_pairs_hook(loader.construct_pairs(node))

    OrderedLoader.add_constructor(
        yaml.resolver.BaseResolver.DEFAULT_MAPPING_TAG,
        construct_mapping)

    return yaml.load(stream, OrderedLoader)


def main(argv):
    parser = argparse.ArgumentParser(
            description='Convert YAML configuration file to Makefile')

    parser.add_argument('--prefix',
                        action='store',
                        default='MGMT_',
                        help='Prefix to prepend to key')

    parser.add_argument('--env',
                        action='store',
                        default=[],
                        nargs='*',
                        help='Also add selected ENV vars')

    parser.add_argument('--outfile',
                        type=argparse.FileType('w'),
                        default=sys.stdout,
                        help='Output file')

    parser.add_argument('infiles',
                        type=argparse.FileType('r'),
                        default=[sys.stdin],
                        nargs='*',
                        help='Path(s) to YAML config file(s)')

    config = collections.OrderedDict()
    environ = os.environ.copy()
    args = parser.parse_args()

    try:
        data = ''
        for infile in args.infiles:
            data += infile.read()
        data = _ordered_load(data, yaml.SafeLoader)
        if data:
            config.update(data)
    except (ParserError, ReaderError):
        sys.exit('Parser Error: {0}:'.format(infile))

    if args.env:
        for env in args.env:
            config[env] = environ.get(env, '')

    data = []
    width = 20 + len(args.prefix)

    for key, item in config.items():
        if isinstance(item, (list, dict)):
            continue

        # Don't add prefix to ENV vars
        if key not in args.env:
            key = '{0}{1}'.format(args.prefix, str(key).upper().replace('-', '_'))

        if item is None:
            item = ''
        else:
            item = str(item)
            item = item.replace('\n', '\\\n')

        data.append('{0:>{1}} ?= {2}'.format(key, width, item))

    try:
        for line in data:
            args.outfile.write(line + '\n')
    except (IOError) as e:
        sys.exit('IOError: {0}:'.format(args.outfile.name), e)

if __name__ == "__main__":
    main(sys.argv[1:])
