#!/usr/bin/env python3

import argparse
import base64
import jinja2
import json
import os
import subprocess
import shutil
import sys

version = '0.3.1'
varargs = []

class appendvarargs(argparse.Action):
    def __call__(self, parser, args, values, option_string=None):
    	varargs.append((option_string, values))

parser = argparse.ArgumentParser(description='Jinja2 Template Transformer Utility v' + version)
parser.add_argument('-t', '--template', type=str, metavar='path',      help='jinja2 template path (default: stdin)', default='-')
parser.add_argument('-o', '--output',   type=str, metavar='path',      help='output path (default: stdout)',         default='-')
parser.add_argument('-j', '--add-json', type=str, metavar='path',      help='add json data',      action=appendvarargs)
parser.add_argument('-y', '--add-yaml', type=str, metavar='path',      help='add yaml data',      action=appendvarargs)
parser.add_argument('-k', '--add-kv',   type=str, metavar='key=value', help='add key=value pair', action=appendvarargs)
parser.add_argument('-f', '--add-file', type=str, metavar='key=path',  help='add key=path text',  action=appendvarargs)
parser.add_argument('-v', '--version',  help='display version and exit', action='store_true')
args = parser.parse_args()

if args.version:
    print(version)
    sys.exit(0)

out_path = '/dev/stdout' if args.output   == '-' else args.output
tpl_path = '/dev/stdin'  if args.template == '-' else args.template

data = {}
data['__global__'] = data

def merge(a, b, path=None):
    path = [] if path is None else path
    for key in b:
        if isinstance(a.get(key), dict) and isinstance(b.get(key), dict):
            merge(a[key], b[key], path + [key])
            continue
        a[key] = b[key]
    return a

for arg, value in varargs:
	if arg == '--add-yaml':
		import yaml
		with open(value, 'r') as f:
			data = merge(data, yaml.load(f))
	elif arg == '--add-json':
		import json
		with open(value, 'r') as f:
			data = merge(data, json.load(f))
	elif arg == '--add-kv':
		key, value = value.split('=', 1)
		data[key] = value
	elif arg == '--add-file':
		key, path = value.split('=', 1)
		with open(path, 'r') as f:
			data[key] = f.read()
	else:
		parser.error('invalid argument: ' + arg)

env = jinja2.Environment(loader=jinja2.FileSystemLoader(os.path.dirname(args.template)))
env.filters['b64encode'] = lambda x: base64.b64encode(x.encode('utf-8')).decode('utf-8')
env.filters['json'] = lambda x: json.dumps(x)

data['_exec'] = subprocess.check_output

with open(tpl_path, 'r') as f:
    template = env.from_string(f.read())

with open(out_path, 'w') as f:
	template.stream(data).dump(f)
