#!/usr/bin/env python

import os
import sys
import argparse
import logging
import re
import traceback

logger = logging.getLogger()
logging.basicConfig()
level = logging.getLevelName(os.getenv('LOG_LEVEL', 'INFO'))
logger.setLevel(level)

parent_dir = os.path.abspath(os.path.dirname(__file__))
lib_dir = os.path.join(parent_dir, 'lib')
sys.path.insert(1, lib_dir)

import aws_parameter_store as parameter_store
import json


def main(paths, args):
    if args.single_param:
        if len(paths) != 1:
            usage()

        parameter_name = paths[0]

        parameters = parameter_store.get_parameters(key_names=[parameter_name], decrypt_smime_with_key=args.decrypt_asymetric_key)

        for parameter_name in parameters:
            print(parameters[parameter_name]['Value'])
            exit()

    elif args.template:
        [key_names, parameter_options] = parameter_store.get_key_names_from_template(args.template)
        parameters = parameter_store.get_parameters(key_names, strip_path=args.strip_path, decrypt_smime_with_key=args.decrypt_asymetric_key, parameter_options=parameter_options)
        formatter = parameter_store.get_formatter(args.format, args)

        result = parameter_store.get_template_subst(args.template, parameters, formatter)
        if args.newlines:
            result = result.replace("\\n", "\n")
        print(result)
        exit()

    else:

        if len(paths) < 1:
            usage()

        if args.recursive:
            parameters = parameter_store.get_parameter_tree(paths=paths, strip_path=args.strip_path, recursive=args.recursive, decrypt_smime_with_key=args.decrypt_asymetric_key)
        else:
            parameters = parameter_store.get_parameters(key_names=paths, strip_path=args.strip_path, decrypt_smime_with_key=args.decrypt_asymetric_key)

        logger.debug("parameters: {}".format(parameters))

        formatter = parameter_store.get_formatter(args.format, args)
        print("\n".join(formatter.get_parameter_list(parameters)))

        exit()


def usage(error=None):
    if error:
        logger.error("Error: {}".format(error))
    parser.parse_args(['-h'])
    exit()


parser = argparse.ArgumentParser(
    description='retrieve parameters from SSM Parameters Store',
    usage="\n" +
        "\tpython " + __file__ + " -h\n"
        "\tpython " + __file__ + " [OPTIONS] --single-param /path/param_name\n"
        "\tpython " + __file__ + " [OPTIONS] /path1/key1 /path2/key2 ...\n"
        "\tpython " + __file__ + " [OPTIONS] [--recursive] /path /path2 ...\n"
        "\tpython " + __file__ + " [OPTIONS] --template <file:/path-to-template|str:\"TEMPLATE\">\n"
)

parser.add_argument(
    '--region',
    help='AWS region',
    type=str
)

parser.add_argument(
    'paths',
    help='key paths',
    nargs='*',
    type=str
)

parser.add_argument(
    '--template',
    help='template',
    type=str
)

parser.add_argument(
    '--single-param',
    help='print single value to stdout',
    action='store_true'
)

parser.add_argument(
    '--recursive',
    help='get all parameters from paths',
    action='store_true'
)

parser.add_argument(
    '--strip-path',
    help='strip path from names',
    type=str,
    default=''
)

parser.add_argument(
    '--newlines',
    help = 'interpret \\n as newlines',
    action='store_true'
)

parser.add_argument(
    '--format',
    help='output format',
    choices=['Bash', 'Yaml', 'Python', 'PythonDict', 'PHPDefine', 'PHPArray', 'map'],
    default='BasicFormatter'
)

parser.add_argument(
    '--map-separator',
    help='separator string for map format',
    type=str,
    default=':'
)

parser.add_argument(
    '--var-name',
    help='variable name, i.e. for PythonDict format',
    type=str,
    default='parameter_dict'
)

parser.add_argument(
    '--decrypt-asymetric-key',
    help = 'decrypt parameter value with assymetric key (SMIME)'
)

try:
    args = parser.parse_args()

    parameter_store.init_ssm_client(region=args.region)

    operation_modes = 0
    if args.template:
        operation_modes += 1
        template = None
        match = re.search(r"^(file|str):(.*)", args.template)

        if match:
            if match.group(1) == "file":
                with open(match.group(2)) as t:
                    template = t.read()
            elif match.group(1) == "str":
                template=match.group(2)
            else:
                usage()
        else:
            usage()

        args.template = template

    if args.paths and len(args.paths) > 1:
        operation_modes += 1
    if args.single_param:
        operation_modes += 1

    if operation_modes > 1:
        usage("Choose one of modes of operation!")

    logger.debug("ARGS: {}".format(args))

    main(args.paths, args)
except Exception as e:
    logger.debug("{}".format(traceback.format_exc()))
    logger.error("Error: {}".format(e))
    exit(1)
