# Copyright 2024 Volvo Car Corporation
# Licensed under Apache 2.0.

# -*- coding: utf-8 -*-
"""Module containing classes for generating core API dummy code for Bosch and Denso suppliers.

These files are needed for building test SW before the supplier has
updated the core with all the needed core id definitions.
"""

import os

from powertrain_build import build_defs
from powertrain_build.problem_logger import ProblemLogger
from powertrain_build.types import get_ec_type
from powertrain_build.unit_configs import CodeGenerators


class CoreDummy(ProblemLogger):
    """A class for core API dummy file generation."""

    def __init__(self, core_cfg, unit_cfg):
        """Initialize with core API configuration.

        Args:
            core_cfg (Core): Configuration object
        """
        super().__init__()
        self._core_cfg = core_cfg
        self._unit_cfg = unit_cfg
        self._uint16_type = self._get_uint_16_type()
        self.fh_c = None
        self.fh_h = None

    def _get_uint_16_type(self):
        if CodeGenerators.target_link in self._unit_cfg.code_generators:
            return 'UInt16'
        return get_ec_type('UInt16')

    def _gen_rb_header(self, file_name):
        """Generate the RB start of the c and h files for the dummy core definition files.

        Args:
            file_name : The RB header file
        """
        self.fh_c.write('/* Autogenerated core id dummy file */\n\n')
        self.fh_c.write(f'#include "{file_name}"\n\n')
        self.fh_c.write(f'#include "{build_defs.CVC_CODE_START}"\n\n')
        self.fh_c.write('#ifndef VcEvDummy_ID\n')
        self.fh_c.write('  #define VcEvDummy_ID 1\n')
        self.fh_c.write('#endif /* VcEvDummy_ID */\n')
        self.fh_c.write('#ifndef VcEvDummy_DEBMODE\n')
        self.fh_c.write('  #define VcEvDummy_DEBMODE 0\n')
        self.fh_c.write('#endif /* VcEvDummy_DEBMODE */\n')
        self.fh_c.write('#ifndef VcFiDummy_ID\n')
        self.fh_c.write('  #define VcFiDummy_ID 1\n')
        self.fh_c.write('#endif /* VcFiDummy_ID */\n')
        self.fh_c.write('#ifndef Vc06Dummy_ID\n')
        self.fh_c.write('  #define Vc06Dummy_ID 1\n')
        self.fh_c.write('#endif /* Vc06Dummy_ID */\n')
        self.fh_c.write('#ifndef Vc09Dummy_ID\n')
        self.fh_c.write('  #define Vc09Dummy_ID 1\n')
        self.fh_c.write('#endif /* Vc09Dummy_ID */\n')
        self.fh_c.write('#ifndef VcRvDummy_ID\n')
        self.fh_c.write('  #define VcRvDummy_ID 1\n')
        self.fh_c.write('#endif /* VcRvDummy_ID */\n\n')

        def_name = file_name.replace('.', '_').upper()
        self.fh_h.write('/* Autogenerated core id dummy file */\n\n')
        self.fh_h.write(f'#ifndef {def_name}\n')
        self.fh_h.write(f'#define {def_name}\n')
        self.fh_h.write('#include "vcc_rb_core.h"\n')
        self.fh_h.write(self._unit_cfg.base_types_headers)

    def _gen_rb_event_dummies(self):
        """Generate RB dummy event declarations."""
        for id_, comment in self._core_cfg.get('EventIDs', {}).items():
            self.fh_h.write(f'#ifndef {id_}\n')
            self.fh_h.write(f'   /* {comment} */\n')
            self.fh_h.write(f'   extern const DSM_DFCType DFC_{id_} ;\n')
            self.fh_h.write(f'   #define {id_} (((DFC_{id_}.debmode) << 12u) | '
                            f'(DFC_{id_}.id))\n')
            self.fh_h.write(f'   #define {id_}_Dummy\n')
            self.fh_h.write('#endif\n\n')

            self.fh_c.write(f'#ifdef {id_}_Dummy\n')
            self.fh_c.write(f'   /* {comment} */\n')
            self.fh_c.write(f'   const DSM_DFCType DFC_{id_} = '
                            '{VcEvDummy_ID, VcEvDummy_DEBMODE};\n')
            self.fh_c.write(f'   #warning "CoreID: {id_} is not defined in '
                            'the supplier SW"\n')
            self.fh_c.write('#endif\n\n')

    def _gen_rb_fid_dummies(self):
        """Generate RB dummy function id declarations."""
        for id_, comment in self._core_cfg.get('FunctionIDs', {}).items():
            self.fh_h.write(f'#ifndef {id_}\n')
            self.fh_h.write(f'   /* {comment} */\n')
            self.fh_h.write(f'   extern const DSM_FIdType FId_{id_} ;\n')
            self.fh_h.write(f'   #define {id_} (FId_{id_}.id)\n')
            self.fh_h.write(f'   #define {id_}_Dummy\n')
            self.fh_h.write('#endif\n\n')

            self.fh_c.write(f'#ifdef {id_}_Dummy\n')
            self.fh_c.write(f'   /* {comment} */\n')
            self.fh_c.write(f'   const DSM_FIdType FId_{id_} = {{VcFiDummy_ID}};\n')
            self.fh_c.write(f'   #warning "CoreID: {id_} is not defined in the supplier SW"\n')
            self.fh_c.write('#endif\n\n')

    def _gen_rb_iumpr_dummies(self):
        """Generate RB dummy IUMPR declarations."""
        for id_, comment in self._core_cfg.get('IUMPR', {}).items():
            self.fh_h.write(f'#ifndef {id_}\n')
            self.fh_h.write(f'   /* {comment} */\n')
            self.fh_h.write(f'   extern const DSM_FIdType FId_{id_} ;\n')
            self.fh_h.write(f'   #define {id_} (FId_{id_}.id)\n')
            self.fh_h.write(f'   #define {id_}_Dummy\n')
            self.fh_h.write('#endif\n\n')

            self.fh_c.write(f'#ifdef {id_}_Dummy\n')
            self.fh_c.write(f'   /* {comment} */\n')
            self.fh_c.write(f'   const DSM_FIdType FId_{id_} = {{Vc09Dummy_ID}};\n')
            self.fh_c.write(f'   #warning "CoreID: {id_} is not defined in the supplier SW"\n')
            self.fh_c.write('#endif\n\n')

    def _gen_rb_mode06_dummies(self):
        """Generate RB dummy mode$06 declarations."""
        for id_, comment in self._core_cfg.get('Mode$06', {}).items():
            self.fh_h.write(f'#ifndef {id_}\n')
            self.fh_h.write(f'   /* {comment[0]}, UAS {comment[1]} */\n')
            self.fh_h.write(f'   extern const DSM_DTRType DTR_{id_};\n')
            self.fh_h.write(f'   #define {id_} (DTR_{id_}.id)\n')
            self.fh_h.write(f'   #define {id_}_Dummy\n')
            self.fh_h.write('#endif\n\n')

            self.fh_c.write(f'#ifdef {id_}_Dummy\n')
            self.fh_c.write(f'   /* {comment[0]}, UAS {comment[1]} */\n')
            self.fh_c.write(f'   const DSM_DTRType DTR_{id_} = {{Vc06Dummy_ID}};\n')
            self.fh_c.write(f'#warning "CoreID: {id_} is not defined in the supplier SW"\n')
            self.fh_c.write('#endif\n\n')

    def _gen_rb_rnk_dummies(self):
        """Generate RB dummy ranking declarations."""
        for id_, comment in self._core_cfg.get('Ranking', {}).items():
            self.fh_h.write(f'#ifndef {id_}\n')
            self.fh_h.write(f'   /* {comment} */\n')
            self.fh_h.write(f'   extern const {self._uint16_type} DSMAppl_RnkValStorg_RnkId_{id_};\n')
            self.fh_h.write(f'   #define {id_} DSMAppl_RnkValStorg_RnkId_{id_}\n')
            self.fh_h.write(f'   #define {id_}_Dummy\n')
            self.fh_h.write('#endif\n\n')

            self.fh_c.write(f'#ifdef {id_}_Dummy\n')
            self.fh_c.write(f'   /* {comment} */\n')
            self.fh_c.write(f'   const {self._uint16_type} DSMAppl_RnkValStorg_RnkId_{id_} = '
                            'VcRvDummy_ID;\n')
            self.fh_c.write(f'   #warning "CoreID: {id_} is not defined in the supplier SW"\n')
            self.fh_c.write('#endif\n\n')

    def _gen_rb_end(self, file_name):
        """Generate RB footer of c and h files for dummy core definition files."""
        def_name = file_name.replace('.', '_').upper()

        self.fh_h.write(f'#endif /* {def_name} */\n')
        self.fh_h.write('/*-------------------------------------'
                        '---------------------------------------*\\\n')
        self.fh_h.write('  END OF FILE\n')
        self.fh_h.write('\\*-------------------------------------'
                        '---------------------------------------*/\n')

        self.fh_c.write(f'#include "{build_defs.CVC_CODE_END}"\n')
        self.fh_c.write('/*--------------------------------------'
                        '--------------------------------------*\\\n')
        self.fh_c.write('  END OF FILE\n')
        self.fh_c.write('\\*--------------------------------------'
                        '--------------------------------------*/\n')

    def generate_rb_core_dummy_files(self, file_name):
        """Generate core API dummy files for Bosch projects."""
        cname = file_name + '.c'
        hname = file_name + '.h'
        with open(cname, 'w', encoding="utf-8") as self.fh_c:
            with open(hname, 'w', encoding="utf-8") as self.fh_h:
                _, f_name = os.path.split(hname)
                self._gen_rb_header(f_name)
                self._gen_rb_event_dummies()
                self._gen_rb_fid_dummies()
                self._gen_rb_iumpr_dummies()
                self._gen_rb_mode06_dummies()
                self._gen_rb_rnk_dummies()
                self._gen_rb_end(f_name)

    def _gen_dg2_header(self, file_name):
        """Generate Denso Gen2/3 header of c and h files for dummy core definition files."""
        self.fh_c.write('/* Autogenerated core id dummy file */\n\n')
        self.fh_c.write(f'#include "{file_name}"\n')
        self.fh_c.write(self._unit_cfg.base_types_headers)
        self.fh_c.write(f'#include "{build_defs.CVC_CODE_START}"\n\n')
        self.fh_c.write('#define Vc06Undef 1\n')
        self.fh_c.write('#define Vc09Undef 1\n')
        self.fh_c.write('#define VcRvUndef 1\n\n')
        self.fh_h.write('/* Autogenerated core id dummy file */\n\n')
        def_name = file_name.replace('.', '_').upper()
        self.fh_h.write(f'#ifndef {def_name}\n')
        self.fh_h.write(f'#define {def_name}\n')
        self.fh_h.write('\n#include "VcCoreSupplierAbstraction.h"\n\n')
        self.fh_h.write('/* Check if denso make env. has defined the AUTOSAR declarations\n')
        self.fh_h.write('   if not, do dummy declaration to be able to build a dummy I/F in\n')
        self.fh_h.write('   an old make environment */\n')
        self.fh_h.write('#ifndef FUNC\n')
        self.fh_h.write('  #define FUNC(rettype, memclass) rettype /* from Compiler.h */\n')
        self.fh_h.write('  #define P2VAR(ptrtype, memclass, ptrclass) ptrtype * '
                        '/* from Compiler.h */\n')
        self.fh_h.write('  typedef unsigned char Std_ReturnType; /* from Std_Types.h */\n')
        self.fh_h.write('  typedef unsigned char Dem_EventStatusType;\n')
        self.fh_h.write('  typedef unsigned char boolean;\n')
        self.fh_h.write('  #define AUTOMATIC\n')
        self.fh_h.write('  #define RTE_APPL_DATA\n')
        self.fh_h.write('  #define RTE_CODE /* from Compiler_cfg.h */\n')
        self.fh_h.write(f'#endif /* {def_name} */\n\n')
        self.fh_h.write(f'#include "{build_defs.CVC_CODE_START}"\n')

    def _gen_dg2_event_dummies(self):
        """Generate the Denso Gen2+ dummy event declarations."""
        for id_, comment in self._core_cfg.get('EventIDs', {}).items():
            # Compare with core0/app/OBDFW/bdcore/Rte_Diag.h
            self.fh_h.write(f'#ifndef Rte_Call_Event_{id_}_SetEventStatus\n')
            self.fh_h.write(f'   /* {comment} */\n')
            self.fh_h.write('   extern FUNC(Std_ReturnType, RTE_CODE) '
                            f'Rte_Call_Diag_Event_{id_}_SetEventStatus '
                            '(Dem_EventStatusType EventStatus);\n')
            self.fh_h.write('#endif\n\n')

            self.fh_c.write(f'#ifndef Rte_Call_Event_{id_}_SetEventStatus\n')
            self.fh_c.write(f'   /* {comment} */\n')
            self.fh_c.write('   FUNC(Std_ReturnType, RTE_CODE) '
                            f'Rte_Call_Diag_Event_{id_}_SetEventStatus '
                            '(Dem_EventStatusType EventStatus) { return 0;}\n')
            self.fh_c.write('#endif\n\n')
            # Generate Dem_SetEventDisabled dummmies
            self.fh_h.write(f'#ifndef Rte_Call_Event_{id_}_SetEventDisabled\n')
            self.fh_h.write(f'   /* {comment} */\n')
            self.fh_h.write('   extern FUNC(Std_ReturnType, RTE_CODE) '
                            f'Rte_Call_Diag_Event_{id_}_SetEventDisabled (void);\n')
            self.fh_h.write('#endif\n\n')

            self.fh_c.write(f'#ifndef Rte_Call_Event_{id_}_SetEventDisabled\n')
            self.fh_c.write(f'   /* {comment} */\n')
            self.fh_c.write('   FUNC(Std_ReturnType, RTE_CODE) '
                            f'Rte_Call_Diag_Event_{id_}_SetEventDisabled '
                            '(void) { return 0;}\n')
            self.fh_c.write('#endif\n\n')

    def _gen_dg2_fid_dummies(self):
        """Generate the Denso Gen2+ dummy function id declarations."""
        for id_, comment in self._core_cfg.get('FunctionIDs', {}).items():
            self.fh_h.write(f'#ifndef Rte_Call_FI_{id_}_GetFunctionPermission\n')
            self.fh_h.write(f'   /* {comment} */\n')
            self.fh_h.write('   extern FUNC(Std_ReturnType, RTE_CODE) '
                            f'Rte_Call_Diag_FI_{id_}_GetFunctionPermission '
                            '(P2VAR(boolean, AUTOMATIC, RTE_APPL_DATA) Permission);\n')
            self.fh_h.write('#endif\n\n')

            self.fh_c.write(f'#ifndef Rte_Call_FI_{id_}_GetFunctionPermission\n')
            self.fh_c.write(f'   /* {comment} */\n')
            self.fh_c.write('   FUNC(Std_ReturnType, RTE_CODE) '
                            f'Rte_Call_Diag_FI_{id_}_GetFunctionPermission '
                            '(P2VAR(boolean, AUTOMATIC, RTE_APPL_DATA) Permission) '
                            '{ *Permission = 1; return 0;}\n')
            self.fh_c.write('#endif\n\n')

    def _gen_dg2_iumpr_dummies(self):
        """Generate the Denso Gen2+ dummy IUMPR declarations."""
        for id_, comment in self._core_cfg.get('IUMPR', {}).items():
            self.fh_h.write(f'#ifndef IUMID_{id_}\n')
            self.fh_h.write(f'   /* {comment} */\n')
            self.fh_h.write(f'   #define IUMID_{id_} cIUMID_{id_}\n')
            self.fh_h.write(f'   #define {id_}_DUMMY\n')
            self.fh_h.write(f'   extern const {self._uint16_type} cIUMID_{id_};\n')
            self.fh_h.write('#endif\n\n')
            self.fh_c.write(f'#ifdef {id_}_DUMMY\n')
            self.fh_c.write(f'   /* {comment} */\n')
            self.fh_c.write(f'   const {self._uint16_type} cIUMID_{id_} = Vc09Undef;\n')
            self.fh_c.write('#endif\n\n')

    def _gen_dg2_mode06_dummies(self):
        """Generate the Denso Gen2+ dummy mode$06 declarations."""
        for id_, comment in self._core_cfg.get('Mode$06', {}).items():
            self.fh_h.write(f'#ifndef TR_{id_}\n')
            self.fh_h.write(f'   /* {comment[0]}, UAS {comment[1]} */\n')
            self.fh_h.write(f'   #define TR_{id_} cTR_{id_}\n')
            self.fh_h.write(f'   #define {id_}_DUMMY\n')
            self.fh_h.write(f'   extern const {self._uint16_type} cTR_{id_};\n')
            self.fh_h.write('#endif\n\n')
            self.fh_c.write(f'#ifdef {id_}_DUMMY\n')
            self.fh_c.write(f'   /* {comment[0]}, UAS {comment[1]} */\n')
            self.fh_c.write(f'   const {self._uint16_type} cTR_{id_} = Vc06Undef;\n')
            self.fh_c.write('#endif\n\n')

    def _gen_dg2_rnk_dummies(self):
        """Generate the Denso Gen2+ dummy ranking declarations."""
        for id_, comment in self._core_cfg.get('Ranking', {}).items():
            self.fh_h.write(f'#ifndef RVID_{id_}\n')
            self.fh_h.write(f'   /* {comment} */\n')
            self.fh_h.write(f'   #define RVID_{id_} cRVID_{id_}\n')
            self.fh_h.write(f'   #define {id_}_DUMMY\n')
            self.fh_h.write(f'   extern const {self._uint16_type} cRVID_{id_};\n')
            self.fh_h.write('#endif\n\n')
            self.fh_c.write(f'#ifdef {id_}_DUMMY\n')
            self.fh_c.write(f'   /* {comment} */\n')
            self.fh_c.write(f'   const {self._uint16_type} cRVID_{id_} = VcRvUndef;\n')
            self.fh_c.write('#endif\n\n')

    def _gen_dg2_end(self, file_name):
        """Generate Denso Gen2+ footer of c and h files for dummy core definition files."""
        def_name = file_name.replace('.', '_').upper()
        self.fh_h.write(f'#include "{build_defs.CVC_CODE_END}"\n')
        self.fh_h.write(f'#endif /* {def_name} */\n')
        self.fh_h.write('/*------------------------------------------'
                        '----------------------------------*\\\n')
        self.fh_h.write('  END OF FILE\n')
        self.fh_h.write('\\*-----------------------------------------'
                        '-----------------------------------*/\n')
        self.fh_c.write(f'#include "{build_defs.CVC_CODE_END}"\n')
        self.fh_c.write('/*------------------------------------------'
                        '----------------------------------*\\\n')
        self.fh_c.write('  END OF FILE\n')
        self.fh_c.write('\\*-----------------------------------------'
                        '-----------------------------------*/\n')

    def generate_dg2_core_dummy_files(self, file_name):
        """Generate the core API dummy files for Denso gen2+ projects."""
        cname = file_name + '.c'
        hname = file_name + '.h'
        with open(cname, 'w', encoding="utf-8") as self.fh_c:
            with open(hname, 'w', encoding="utf-8") as self.fh_h:
                _, f_name = os.path.split(hname)
                self._gen_dg2_header(f_name)
                self._gen_dg2_event_dummies()
                self._gen_dg2_fid_dummies()
                self._gen_dg2_iumpr_dummies()
                self._gen_dg2_mode06_dummies()
                self._gen_dg2_rnk_dummies()
                self._gen_dg2_end(f_name)
