#!/usr/bin/env python
# Copyright (c) 2019 - The Procedural Generation for Gazebo authors
# For information on the respective copyright owner see the NOTICE file
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
#     http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific
import os
import argparse
import yaml
from pcg_gazebo.parsers import parse_sdf, parse_urdf, parse_sdf_config, \
    convert_from_string, expand_nested_models
from pcg_gazebo.utils import load_yaml, process_jinja_template


if __name__ == '__main__':
    parser = argparse.ArgumentParser(description='Parse Jinja template')
    parser.add_argument(
        '--input-template', '-i', type=str,
        help='Input template file')
    parser.add_argument(
        '--param-file', '-f', type=str,
        help='YAML file with parameters to be rendered in the final output')
    parser.add_argument(
        '--output-filename', '-o', type=str,
        help='Output file to store the parsed file')
    parser.add_argument(
        '--include-dir', '-d', type=str,
        help='Input directory for template modules')
    parser.add_argument(
        '--param', '-p', action='append',
        help='Model parameter to be replaced in the template')
    parser.add_argument(
        '--sdf', action='store_true',
        help='Output template is a SDF file and will be verified')
    parser.add_argument(
        '--sdf-config', action='store_true',
        help='Output template is a SDF model configuration file and will be verified')
    parser.add_argument(
        '--urdf', action='store_true',
        help='Output template is an URDF file and will be verified')
    parser.add_argument(
        '--merge-nested-models', action='store_true',
        help='For SDF descriptions, merge nested models before generating final SDF, in case there are any')

    args = parser.parse_args()

    assert isinstance(args.input_template, str), \
        'Input template must be a valid string'

    print('Input template: {}'.format(args.input_template))

    if args.output_filename is None:
        print('No output filename provided, file output will be printed')
    else:
        print('Output filename: {}'.format(args.output_filename))

    if args.include_dir is not None and os.path.isdir(args.include_dir):
        include_dir = args.include_dir
        print('Directory for Jinja include files: {}'.format(args.include_dir))
    else:
        include_dir = None

    params = dict()
    if args.param_file is not None and os.path.isfile(args.param_file):
        print('Importing parameters from file: {}'.format(args.param_file))
        params = load_yaml(args.param_file)
        print('Parameters for Jinja template loaded')
        for tag in params:
            print('\t {}={}'.format(tag, params[tag]))

    if args.param:
        if len(args.param):
            for item in args.param:
                param = item.split('=')
                assert len(param) == 2, \
                    'Parameter must be provided as <param_name>=<param_value>'
                value = convert_from_string(param[1])
                params[param[0]] = \
                    value if value is not None else param[1].replace('\"', '')

    if len(params) > 0:
        print('Parameters:')
        for tag in sorted(params.keys()):
            print('\t - {}: {}'.format(tag, params[tag]))

    output_xml = process_jinja_template(args.input_template, parameters=params)
    output = None
    if args.sdf:
        # Parsing SDF file to verify its consistency
        output = parse_sdf(output_xml)

        if args.merge_nested_models:
            if output.xml_element_name == 'model' or \
                    (output.xml_element_name == 'sdf' and
                        output.models is not None and len(output.models) == 1):

                new_merged_model = expand_nested_models(output)

                if output.xml_element_name == 'model':
                    output = new_merged_model
                else:
                    output.models[0] = new_merged_model
    elif args.urdf:
        # Parsing URDF file to verify its consistency
        output = parse_urdf(output_xml)
    elif args.sdf_config:
        # Parsing SDF model configuration file to verify its consistency
        output = parse_sdf_config(output_xml)
    else:
        with open(args.output_filename, 'w+') as output_file:
            output_file.write(output_xml)

    if output is not None:
        if args.output_filename is not None:
            output.export_xml(args.output_filename)
        else:
            print(output)
    else:
        print('Error while processing {}'.format(args.input_template))
        exit(1)
