#!/usr/bin/env python3

################################################################################
#
# Copyright 2020 OpenHW Group
# Copyright 2020 Silicon Labs, Inc.
#
# Licensed under the Solderpad Hardware Licence, 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
# 
#     https://solderpad.org/licenses/
# 
# 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 language governing permissions and
# limitations under the License.
#
# SPDX-License-Identifier:Apache-2.0 WITH SHL-2.0
# 
################################################################################
#
# cfgyaml2make
#   Converts a build configuration YAML to make variables
#
# Author: Steve Richmond
#  email: steve.richmond@silabs.com
#
# Written with Python 3.5.1 on RHEL 7.7.  Your python mileage may vary.
#
################################################################################

import argparse
import os
import sys
import tempfile
import re
import pprint
import logging
import yaml

logging.basicConfig()
logger = logging.getLogger(os.path.basename(__file__))
logger.setLevel(logging.INFO)

TOPDIR = os.path.abspath(os.path.join(os.path.dirname(os.path.realpath(__file__)), '..'))
REQUIRED_KEYS = ('name', 'description',)
CFG_PATHS = (
             '<CV_CORE>/tests/cfg',
            )
try:
    DEFAULT_CORE=os.environ['CV_CORE']
except KeyError:
    DEFAULT_CORE=None

if (sys.version_info < (3,0,0)):
    print ('Requires python 3')
    exit(1)

def read_file(file):
    '''Read a YAML build specification'''

    matches = [os.path.join(TOPDIR, p, file) for p in CFG_PATHS 
                if os.path.exists(os.path.join(TOPDIR, p, file))]

    # It is a fatal error to find less than 1 or more than 1 match
    if len(matches) == 0:
        logger.fatal('Could not find {} in any cfg directories:'.format(file))
        for p in CFG_PATHS:
            logger.fatal(os.path.join(TOPDIR, p, file)) 
        os.sys.exit(2)

    if len(matches) >1 :
        logger.fatal('Found multiple matches for {} in directories:'.format(yaml))
        for p in CFG_PATHS:
            logger.fatal(os.path.join(TOPDIR, p, file))
        os.sys.exit(2)

    stream = open(matches[0], 'r')
    logger.debug('Reading cfg specification: {}'.format(matches[0]))
    # Newer PyYAMLs must specify explicit loader (policy) or will issue warnings
    # Older PyYAMLs will not support the Loader argument
    # So try the new way first, then catch to the old way
    try:
        cfg_spec = yaml.load(stream, Loader=yaml.FullLoader)
    except AttributeError:
        cfg_spec = yaml.load(stream)
    stream.close()

    # Validation
    for k in REQUIRED_KEYS:        
        if not k in cfg_spec:
            logger.fatal('Key [{}] was not found in cfg specification YAML:'.format(k))
            logger.fatal('-> : {}'.format(matches[0]))
            os.sys.exit(2)

    # Debug the YAML parsing
    pp = pprint.PrettyPrinter()
    logger.debug('Read YAML:')
    logger.debug(pp.pformat(cfg_spec))

    return cfg_spec

def emit_make(cfg_spec, prefix):
    '''Emit a hash from the YAML test specification into a makefile that can be included'''
    fh = tempfile.NamedTemporaryFile(mode='w', delete=False)
    for k,v in sorted(cfg_spec.items()):
        # Handle empty value (allowed)
        try:
            v_rstrip = v.rstrip()
        except AttributeError:
            v_rstrip = ''
        fh.write('{}{}={}\n'.format('' if not prefix else prefix.upper() + '_', k.upper(), v_rstrip))
    fh.close()

    return fh.name

################################################################################
# Command-line arguments

parser = argparse.ArgumentParser()
parser.add_argument('-d', '--debug', action='store_true', help='Display debug messages')
parser.add_argument('--yaml', help='Name of YAML build specification to find')
parser.add_argument('--core', default=DEFAULT_CORE, help='Default core to test')
parser.add_argument('--prefix', help='Prefix to add to make variables generated')
args = parser.parse_args()

if args.debug:
    logger.setLevel(level=logging.DEBUG)

# Validate 
if not args.core:
    logger.fatal('Must specify core with CV_CORE envrionment variable or --core')
    os.sys.exit(2)

if not args.yaml:
    logger.fatal('Must specify the YAML build specification with --yaml')
    os.sys.exit(2)

CFG_PATHS = [p.replace('<CV_CORE>', args.core.lower()) for p in CFG_PATHS]

cfg_spec = read_file(file=args.yaml)
temp_file = emit_make(cfg_spec=cfg_spec, prefix=args.prefix)

logger.debug('File written to {}'.format(temp_file))
print(temp_file)
