"""
Copyright 2023 Cypress Semiconductor Corporation (an Infineon company)
or an affiliate of Cypress Semiconductor Corporation. All rights reserved.

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 language governing permissions and
limitations under the License.
"""


import sys
import json
import click

def load_json(file_path):
    """
    Loads JSON from file.
    """

    data_json = None

    try:
        with open(file_path, encoding="utf-8") as file:
            data_json = json.load(file)

    except FileNotFoundError:
        print(f'\nERROR: Cannot find {file_path}')
        sys.exit(1)

    return data_json


class FieldsValidator:
    """
        Validation of required fields and their cross-dependencies.
    """

    @staticmethod
    def validate(feature_json, properties_json):
        """
            Check 'target' and properties of a platform.
        """
        p_target = properties_json.get('target')
        if p_target is None:
            raise AttributeError('Field "target" must be present in platform_properties.json')

        f_target = feature_json.get('target')
        if f_target is None:
            raise AttributeError('Field "target" must be present in a feature_config.json')

        if f_target not in p_target:
            raise AttributeError('Target in feature config is not correct.'
                                    ' It must be among the target list of platform_properties.json')

        f_security_setup = feature_json.get('security_setup')
        p_security_setup = properties_json.get('security_setup')

        if f_security_setup:

            if p_security_setup is None:
                print("\nThis platform doesn't have any 'secure_setup' features")
                sys.exit(1)

            if f_security_setup.get('hw_rollback_prot'):
                if p_security_setup.get('hw_rollback_prot') is None:
                    print("\nThis platform doesn't have HW anti roll-back counter")
                    sys.exit(1)

            if f_security_setup.get('hw_crypto_acceleration'):
                if p_security_setup.get('hw_crypto_acceleration') is None:
                    print("\nThe platform doesn't support HW crypto acceleration")
                    sys.exit(1)

            if f_security_setup.get('validate_upgrade').get('value') is False:
                if f_security_setup.get('validate_boot').get('value'):
                    print("\nERROR: Boot slot validation cannot be enabled if upgrade "\
                                "slot validation is disabled")
                    sys.exit(1)


class FeatureProcessor:

    """
        The general handler of all needed fields and filling the new mk-file.
    """

    settings_dict = {
        'validate_boot'             :   'MCUBOOT_SKIP_BOOT_VALIDATION',
        'validate_upgrade'          :   'MCUBOOT_SKIP_UPGRADE_VALIDATION',
        'dependency_check'          :   'MCUBOOT_DEPENDENCY_CHECK',
        'serial_logging'            :   'MCUBOOT_LOG_LEVEL',
        'watch_dog_timer'           :   'USE_WDT',
        'hw_rollback_prot'          :   'USE_HW_ROLLBACK_PROT',
        'hw_crypto_acceleration'    :   "USE_CRYPTO_HW",
        'sw_downgrade_prev'         :   'USE_SW_DOWNGRADE_PREV',
        'ram_app_staging'           :   'USE_STAGE_RAM_APPS',
        'xip'                       :   'USE_XIP',
        'image_encryption'          :   'ENC_IMG',
        'fault_injection_hardening' :   'FIH_PROFILE_LEVEL',
        'combine_hex'               :   'COMBINE_HEX',
        'hw_key'                    :   'USE_HW_KEY'
    }

    debug_level_dict = {
        'off'       :   '_OFF',
        'error'     :   '_ERROR',
        'warning'   :   '_WARNING',
        'info'      :   '_INFO',
        'debug'     :   '_DEBUG'
    }

    fih_level_dict = {
        'off'       :   'OFF',
        'low'       :   'LOW',
        'medium'    :   'MEDIUM',
        'high'      :   'HIGH'
    }

    def __init__(self, output_name):
        self.out_f = output_name

    @staticmethod
    def generate_header_guard():
        """
            Print header line at the begining of a mk-file
        """
        guard_lines = ('# AUTO-GENERATED FILE, DO NOT EDIT.'
                        ' ALL CHANGES WILL BE LOST! #\n\n')

        return guard_lines

    @staticmethod
    def insert_res(val_to_check) -> str:
        """
            Simlpe check result and return the string with value.
        """
        return f' := {1 if val_to_check else 0}\n'

    @staticmethod
    def insert_inverted_res(val_to_check) -> str:
        """
            Simlpe check result and return the string with inverted value.
        """
        return f' := {0 if val_to_check else 1}\n'

    def __prnt_dict_primitive_key(self, dict_feature_config, settings_dict_key, f_out):
        """
            Print kyes of 'feature_config' with bool type of 'value'
        """
        val = dict_feature_config.get(settings_dict_key).get('value')

        if isinstance(val, bool):

            # invert because variable use 'skip' command
            need_invertion = set(("validate_boot", "validate_upgrade"))

            f_out.write(self.settings_dict[settings_dict_key])

            if settings_dict_key not in need_invertion:
                f_out.write(FeatureProcessor.insert_res(val))
            else:
                f_out.write(FeatureProcessor.insert_inverted_res(val))


    def __gen_fih_level(self, fih_value):
        """
            Print only FIH_
        """
        res = f"{self.settings_dict['fault_injection_hardening']} ?= "\
              f"{self.fih_level_dict[fih_value]}\n"

        return res

    def __gen_debug_level(self, logging_value):
        """
            Print only MCUBOOT_LOG_LEVEL
        """
        param_txt = self.settings_dict['serial_logging']
        res_str = f"{param_txt} ?= {param_txt}{self.debug_level_dict[logging_value]}\n"

        return res_str


    def __handle_dictionary(self, f_dict, f_out):
        """
            Handle any dictionary of 'feature_config'
        """
        dont_print_list = set(("validation_key", "version", "description", "target"))

        for k in f_dict:

            if k not in dont_print_list:
                self.__prnt_dict_primitive_key(f_dict, k, f_out)

            if k == 'fault_injection_hardening':
                f_out.write(self.__gen_fih_level(f_dict.get(k).get("value")))

            if k == 'serial_logging':
                f_out.write(self.__gen_debug_level(f_dict.get(k).get("value")))


    def make_file_generate(self, feature_json):
        """
            Processing all keys and creation of a mk-file
        """

        with open(self.out_f, "w", encoding='UTF-8') as f_out:
            f_out.write(FeatureProcessor.generate_header_guard())

            f_security_setup_dict = feature_json.get('security_setup')

            # handling of 'security_setup' section
            if f_security_setup_dict:
                self.__handle_dictionary(f_security_setup_dict, f_out)

            self.__handle_dictionary(feature_json, f_out)


@click.group()
def cli():
    """
        Feature config parser to run from CLI
    """

@cli.command()
@click.option('-f', '--feature_config', required=True,
              help='feature configuration file path')
@click.option('-p', '--platform_properties', required=True,
              help='platform properties file path')
@click.option('-n', '--output_name', required=True,
              help='the name of the make file that will be generated')


def run(feature_config, platform_properties, output_name):
    """
        The main CLI command to run mk-file generation
    """

    feature_config_json = load_json(feature_config)
    platform_properties_json = load_json(platform_properties)

    FieldsValidator.validate(feature_config_json, platform_properties_json)

    fprocessor = FeatureProcessor(output_name)
    fprocessor.make_file_generate(feature_config_json)


if __name__ == '__main__':
    cli()
