/*
 * Copyright 2016 Freescale Semiconductor
 * Copyright 2016-2017 NXP
 * To be used with KEx Tools. See Software License Agreement of KEx Tools.
 */

// This object generate content of H file. The content is affected by generating C file.
var ClockConfigH = {
  // Output writer
  writer: null,
  
  // Status "is extern clock_arm_pll_config_t generated". generate() initialize to false. C file generating script can set to true.
  isArmPllConfigExtern: new Object(),
  // Status "is extern clock_usb1_pll_config_t generated". generate() initialize to false. C file generating script can set to true.
  isUsb1PllConfigExtern: new Object(),
  // Status "is extern clock_usb2_pll_config_t generated". generate() initialize to false. C file generating script can set to true.
  isUsb2PllConfigExtern: new Object(),
  // Status "is extern clock_sys_pll_config_t generated". generate() initialize to false. C file generating script can set to true.
  isSysPllConfigExtern: new Object(),
  // Status "is extern clock_audio_pll_config_t generated". generate() initialize to false. C file generating script can set to true.
  isAudioPllConfigExtern: new Object(),
  // Status "is extern clock_video_config_t generated". generate() initialize to false. C file generating script can set to true.
  isVideoPllConfigExtern: new Object(),
  // Status "is extern clock_enet_pll_config_t generated". generate() initialize to false. C file generating script can set to true.
  isEnetPllConfigExtern: new Object(),
  
  // references on define block instances for "common" and for each configuration
  defineBlockH: new Object(),
  // references on define block positions for "common" and for each configuration
  defineBlockHPosition: new Object(),
  // references on extern clock_arm_pll_config_t places for each configuration
  armPllConfigExternPosition: new Object(),
  // references on extern clock_usb1_pll_config_t places for each configuration
  usb1PllConfigExternPosition: new Object(),
  // references on extern clock_usb2_pll_config_t places for each configuration
  usb2PllConfigExternPosition: new Object(),
  // references on extern clock_sys_pll_config_t places for each configuration
  sysPllConfigExternPosition: new Object(),
  // references on extern clock_audio_pll_config_t places for each configuration
  audioPllConfigExternPosition: new Object(),
   // references on extern clock_video_config_t places for each configuration
  videoPllConfigExternPosition: new Object(),
  // references on extern clock_enet_pll_config_t places for each configuration
  enetPllConfigExternPosition: new Object(),
  
  // generate h file content and create insertions for definitions
  generate: function(writer) {
    // safe output writer
    this.writer = writer;
    // HWriter.write(CommonHeaderText());
    // HWriter.write("");
    HWriter.writeLines([
    "#ifndef _CLOCK_CONFIG_H_",
    "#define _CLOCK_CONFIG_H_",
    "",
    "#include \"fsl_common.h\"",
    "",
    ]);
    // Common definitions
    this.defineBlockHPosition["common"] = HWriter.write(null); 
    HWriter.writeLines(OutputUtils.getDefinitionIntro(), this.defineBlockHPosition["common"]);
    this.defineBlockH["common"] = new DefineBlock(); 
    var theSame = HwAbstr.isSettingSameInAllConfigurations("XTALOSC24M.OSC.outFreq", "osc", "asInteger");
    if (theSame != null && theSame) {
      var values = HwAbstr.getSettingValuesForAllConfigurations("XTALOSC24M.OSC.outFreq", "osc", "asInteger");
      this.defineBlockH["common"].addDefine("BOARD_XTAL0_CLK_HZ", values[0], "Board xtal0 frequency in Hz");
    }
    HWriter.write("#define BOARD_XTAL32K_CLK_HZ                          32768U  /*!< Board xtal32k frequency in Hz */");
    HWriter.writeLines([
    '/*******************************************************************************',
    ' ************************ BOARD_InitBootClocks function ************************',
    ' ******************************************************************************/',
    '',
    '#if defined(__cplusplus)',
    'extern "C" {',
    '#endif /* __cplusplus*/',
    '',
    '/*!',
    ' * @brief This function executes default configuration of clocks.',
    ' *',
    ' */',
    'void BOARD_InitBootClocks(void);',
    '',
    '#if defined(__cplusplus)',
    '}',
    '#endif /* __cplusplus*/',
    '']);

    // generate the header part for each configuration 
    for (var cfgIndex = 0; cfgIndex < Gen.configs.length; cfgIndex++) {
      var cfg = Gen.configs[cfgIndex];
      var configID = Gen.getConfigID(cfg);
      var configName = cfg.getName();
      // clear status "is extern clock_arm_pll_config_t generated"
      this.isArmPllConfigExtern[configID] = false;
      // clear status "is extern clock_usb1_pll_config_t generated"
      this.isUsb1PllConfigExtern[configID] = false;
      // clear status "is extern clock_usb2_pll_config_t generated"
      this.isUsb2PllConfigExtern[configID] = false;
      // clear status "is extern clock_sys_pll_config_t generated"
      this.isSysPllConfigExtern[configID] = false;
      // clear status "is extern clock_audio_pll_config_t generated"
      this.isAudioPllConfigExtern[configID] = false;
      // clear status "is extern clock_video_config_t generated"
      this.isVideoPllConfigExtern[configID] = false;
      // clear status "is extern clock_enet_pll_config_t generated"
      this.isEnetPllConfigExtern[configID] = false;

      // write configuration introduction
      HWriter.writeLines(OutputUtils.getConfigurationIntro(cfg));
      // write definition introduction
      HWriter.writeLines(OutputUtils.getDefinitionIntro(cfg));

      this.defineBlockHPosition[configID] = HWriter.write(null); 
      // create block instance of #defines 
      this.defineBlockH[configID] = new DefineBlock();
      SDKMapper.setHWriterDefineContainer = this.defineBlockH[configID];   
      tmp = SDKMapper.getFieldValue(cfg, "coreClock");
      if (tmp != null) {
        this.defineBlockH[configID].addDefine(configID.toUpperCase() + "_CORE_CLOCK", tmp.value, tmp.description);
      }

      // allocate place for extern clock_arm_pll_config_t 
      this.armPllConfigExternPosition[configID] = HWriter.write(null);
      // allocate place for extern clock_usb1_pll_config_t 
      this.usb1PllConfigExternPosition[configID] = HWriter.write(null);
      // allocate place for extern clock_usb2_pll_config_t 
      this.usb2PllConfigExternPosition[configID] = HWriter.write(null);
      // allocate place for extern clock_sys_pll_config_t 
      this.sysPllConfigExternPosition[configID] = HWriter.write(null);
      // allocate place for extern clock_audio_pll_config_t 
      this.audioPllConfigExternPosition[configID] = HWriter.write(null);      
      // allocate place for extern clock_video_config_t 
      this.videoPllConfigExternPosition[configID] = HWriter.write(null);
      // allocate place for extern clock_enet_pll_config_t 
      this.enetPllConfigExternPosition[configID] = HWriter.write(null);	  
      HWriter.line("");  

      // write api introduction
      HWriter.writeLines(OutputUtils.getApiIntro(cfg));
      HWriter.writeLines([
      "#if defined(__cplusplus)",
      "extern \"C\" {",
      "#endif /* __cplusplus*/"]);
      HWriter.write("");
      HWriter.writeLines([
      "/*!",
      " * @brief This function executes configuration of clocks.",
      " *",
      " */"]);
      HWriter.write("void " + Gen.getConfigID(Gen.configs[cfgIndex]) + "(void);");
      HWriter.writeLines([
      "",
      "#if defined(__cplusplus)",
      "}",
      "#endif /* __cplusplus*/",
      "",
      ]);
    }
    HWriter.writeLines([
    "#endif /* _CLOCK_CONFIG_H_ */",
    "",
    ]);
  },
  
  // complete h file content, e.g. definition insertion
  complete: function(){
    // write common define block
    HWriter.writeLines(this.defineBlockH["common"].getDefineBlock().concat(""), this.defineBlockHPosition["common"]);
    for (var cfgIndex = 0; cfgIndex < Gen.configs.length; cfgIndex++) {
      var cfg = Gen.configs[cfgIndex];
      var configID = Gen.getConfigID(cfg);
      var configName = cfg.getName();
      // write common define block
      HWriter.writeLines(this.defineBlockH[configID].getDefineBlock().concat(""), this.defineBlockHPosition[configID]);

      // extern clock_arm_pll_config_t
      if (this.isArmPllConfigExtern[configID]) {
        HWriter.writeLines([
        "/*! @brief Arm PLL set for " + configName + " configuration.",
        " */",
        ], this.armPllConfigExternPosition[configID]);
        HWriter.write("extern const clock_arm_pll_config_t g_armPllConfig_" + configID + ";", this.armPllConfigExternPosition[configID]);
      }

      // extern clock_usb1_pll_config_t
      if (this.isUsb1PllConfigExtern[configID]) {
        HWriter.writeLines([
        "/*! @brief Usb1 PLL set for " + configName + " configuration.",
        " */"
        ], this.usb1PllConfigExternPosition[configID]);
        HWriter.write("extern const clock_usb_pll_config_t g_usb1PllConfig_" + configID + ";", this.usb1PllConfigExternPosition[configID]);
      }

      // extern clock_usb2_pll_config_t
      if (this.isUsb2PllConfigExtern[configID]) {
        HWriter.writeLines([
        "/*! @brief Usb2 PLL set for " + configName + " configuration.",
        " */"
        ], this.usb2PllConfigExternPosition[configID]);
        HWriter.write("extern const clock_usb_pll_config_t g_usb2PllConfig_" + configID + ";", this.usb2PllConfigExternPosition[configID]);
      }

      // extern clock_sys_pll_config_t
      if (this.isSysPllConfigExtern[configID]) {
        HWriter.writeLines([
        "/*! @brief Sys PLL for " + configName + " configuration.",
        " */"
        ], this.sysPllConfigExternPosition[configID]);
        HWriter.write("extern const clock_sys_pll_config_t g_sysPllConfig_" + configID + ";", this.sysPllConfigExternPosition[configID]);
      }

      // extern clock_audio_pll_config_t
      if (this.isAudioPllConfigExtern[configID]) {
        HWriter.writeLines([
        "/*! @brief Audio PLL set for " + configName + " configuration.",
        " */"
        ], this.audioPllConfigExternPosition[configID]);
        HWriter.write("extern const clock_audio_pll_config_t g_audioPllConfig" + configID + ";", this.audioPllConfigExternPosition[configID]);
      }

      // extern clock_video_pll_config_t
      if (this.isVideoPllConfigExtern[configID]) {
        HWriter.writeLines([
        "/*! @brief Video PLL set for " + configName + " configuration.",
        " */"
        ], this.videoPllConfigExternPosition[configID]);
        HWriter.write("extern const clock_video_pll_config_t g_videoPllConfig" + configID + ";", this.videoPllConfigExternPosition[configID]);
      }

      // extern clock_enet_pll_config_t
      if (this.isEnetPllConfigExtern[configID]) {
        HWriter.writeLines([
        "/*! @brief Enet PLL set for " + configName + " configuration.",
        " */"
        ], this.enetPllConfigExternPosition[configID]);
        HWriter.write("extern const clock_enet_pll_config_t g_enetPllConfig" + configID + ";", this.enetPllConfigExternPosition[configID]);
      }
    }
  },
}
