//----------------------------------------------------------------------------
///
/// \file   main.cpp
///
/// \brief  main file for pinmux
///
/// \date   20180129
/// \author Maximilian Seesslen <mes@seesslen.net>
///
//----------------------------------------------------------------------------


//---Documentation------------------------------------------------------------


//---Includes -----------------------------------------------------------------


//---General--------------------------

#if defined ( CATCH2 )
#include <catch2/catch_test_macros.hpp>
#elif defined ( CATCH )
#include <catch/catch.hpp>
#else
#error "Either 'catch' or 'catch2' has to be installed"
#endif
#include <QDebug>

//--- Own ----------------------------

#include "../src/board.h"
#include "../src/app.h"
#include "../src/pinmux.h"
#include "writerPlatform.h"
#include "writerConfigHeader.h"
#include "writerDesc.h"
#include "formaterCpp.h"

#define TEST_ALL
#define STOP_ON_FAIL

//---Implementation------------------------------------------------------------


TEST_CASE( "Prefered", "[default]" ) {
   CPinmux pinmux;
   CApp app;
   CBoard board;

   SECTION( "Predefined prefered with fabricated periphery in prefered" )
   {
      const char *boardString=
      R"JSON(
      {
          "name": "myboard_prefered",
          "version": "1",
          "overloadingAttributes": [ "speedo" ],
          "peripheries": [
                  { "type": "GND", "name": "GND", "pin": "GND", "relation": "fabricate", "attributes": { "pseudo": "yes" } },
                  { "type": "AGND", "name": "AGND", "pin": "AGND", "relation": "fabricate", "attributes": { "pseudo": "yes" } },
                  { "type": "GPIO",   "periphery": "PA12", "pin": "D1", "irq": "EXTI9_5_IRQHandler" },
                  { "type": "GPIO",   "periphery": "PA11", "pin": "D0", "irq": "EXTI15_10_IRQHandler" },
                  { "type": "GPIO",   "periphery": "PA13", "pin": "D2", "irq": "EXTI9_5_IRQHandler" },
                  { "type": "GPIO",   "periphery": "PA14", "pin": "D2", "irq": "EXTI9_5_IRQHandler" },
                  {
                     "type": "SPI", "periphery": "SPI2.PA13", "irqs": "SPI_IRQHandler",
                     "consumes": [
                         { "periphery": "PA14",   "name": "TX", "mode": "skip" },
                         { "periphery": "PA13",   "name": "RX", "mode": "skip" },
                         { "type": "GND", "name": "A1" },
                         { "type": "GND", "name": "A1" }
                     ],
                     "attributes": {
                         "configBlock": "SPI2_PA14_PA13",
                         "speedo": "10Khz",
                         "implementation": "10Khz"
                     }
                  },
                  {
                     "type": "SPI", "periphery": "SPI1.PA11", "irqs": "SPI_IRQHandler",
                     "consumes": [
                         { "periphery": "PA12",   "name": "TX", "mode": "skip" },
                         { "periphery": "PA11",   "name": "RX", "mode": "skip" },
                         { "type": "GND", "name": "A1" },
                         { "type": "GND", "name": "A1" }
                     ],
                     "attributes": {
                         "configBlock": "SPI1_PA12_PA11",
                         "speedo": "10Khz",
                         "implementation": "10Khz"
                     }
                  }
         ],
         "constructors": [
                 {
                     "type": "SPI",
                     "arguments": [
                             { "type": "fixed", "value": "spiConfig_<attribute:configBlock>" },
                             { "type": "fixed", "value": "spiConfig_<attribute:speedo>" }
                     ]
                 },
                 {
                     "type": "GND",
                     "arguments": [
                         { "type": "GND", "name": "A1" },
                         { "type": "GND", "name": "A1" }
                     ]
                 }
         ],
         "final": "yes"
      }
      )JSON";

      app.clear();
      board.clear();
      app.setBoardId("myboard");
      board.loadByteArray( QByteArray(boardString), "intern_SPI" );
      app.loadByteArray(
               QByteArray(R"JSON(
               {
                   "name": "canio",
                   "periphery": [
                      { "type": "SPI", "name": "1",
                           "attributes": {
                               "speedo": "24Mhz"
                           },
                        "predefined":
                           { "myboard": "SPI1.PA11 PA12 PA11 GND GND" }
                      },
                      { "type": "AGND", "name": "1" },
                      { "type": "AGND", "name": "2" },
                      { "type": "AGND", "name": "3" }
                    ]
               }
      )JSON" ), "intern" );

      pinmux.setBoardApp(board, app);
      //pinmux.loadByteArray( QByteArray(boardString), "intern" );
      pinmux.resolveApp();
#if 0
      CFormaterCpp formater(*board.findPeripheryByPeripheryName( QString("SPI1.PA11") ), pinmux.getConstructorPool());
      qWarning() << "OUTPUT: " << formater.getPeripheralArgumentsString( pinmux );

      REQUIRE( formater.getPeripheralArgumentsString(pinmux )
               == "spiConfig_SPI1_PA12_PA11, spiConfig_24Mhz");
#endif
      CConstructorPool constructors;
      constructors.loadByteArray( QByteArray(boardString), "intern" );
      CWriterPlatform platform(pinmux, constructors, "");
      CPeripheryPtr ptr=board.findPeripheryByPeripheryName( QString("SPI1.PA11") );
      qWarning() << "OUTPUT: " << platform.getPeripheralArgumentsString( *ptr );

      REQUIRE( platform.getPeripheralArgumentsString( *ptr )
               == "spiConfig_SPI1_PA12_PA11, spiConfig_24Mhz");

      app.clear();
      board.clear();
      app.setBoardId("myboard");
      board.loadByteArray( QByteArray(boardString), "intern_SPI" );
      app.loadByteArray(
               QByteArray(R"JSON(
               {
                   "name": "canio",
                   "periphery": [
                      { "type": "SPI", "name": "1",
                           "attributes": {
                               "speedo": "24Mhz"
                           },
                        "predefined":
                           { "myboard": "SPI1.PA11 PA12 PA11 GND GND" }
                      },
                      { "type": "AGND", "name": "1" },
                      { "type": "AGND", "name": "2" },
                      { "type": "AGND", "name": "3" }
                    ]
               }
      )JSON" ), "intern" );

      pinmux.setBoardApp(board, app);
      int status=0;
      try
      {
         pinmux.resolveApp();
      }
      catch(...)
      {
         status=1;
      }

      // Unfortunately the current implementation can resolve wrong GPIOs
      //REQUIRE( status == 1 );
      REQUIRE( status == 0 );


      app.clear();
      board.clear();
      app.setBoardId("myboard");
      board.loadByteArray( QByteArray(R"JSON(
               {
                   "name": "myboard_prefered",
                   "version": "1",
                   "overloadingAttributes": [ "speedo" ],
                   "peripheries": [
                       {
                           "type": "WKUP", "periphery": "WKUP1", "name": "", "priority": "1",
                           "consumes": [
                              { "periphery": "INPUT_PA0", "name": "1" }
                           ]
                       },
                        { "type": "INPUT", "periphery": "INPUT_PA0", "name": "1",
                           "consumes": [  {
                                             "periphery": "PA0",   "name": "INPUT",
                                             "attributes": {
                                                 "useIrq": "yes"
                                             }
                                          },
                                          { "periphery": "EXTI0",   "name": "0" }
                                       ],
                           "attributes": {
                               "useIrq": "yes"
                           }
                        },
                        {
                           "type": "GPIO",   "periphery": "PA0",  "pin": "PA0/#10", "irqs": "EXTI0_1_IRQHandler"
                        },
                        {
                           "type": "EXTI", "periphery": "EXTI0", "name": "EXTI0", "mode": "shared"
                        }
                  ]
            }
                  )JSON"), "intern_SPI" );
      app.loadByteArray(
               QByteArray(R"JSON(
               {
                   "name": "wakei, wakei",
                   "periphery": [
                      {
                           "type": "WKUP", "name": "1",
                           "predefined": {
                              "myboard": "WKUP1 INPUT_PA0 PA0 EXTI0"
                           }
                      }
                    ]
               }
      )JSON" ), "intern" );

      pinmux.setBoardApp(board, app);
      status=0;
      try
      {
         pinmux.resolveApp();
      }
      catch(...)
      {
         status=1;
      }

      REQUIRE( status == 0 );

      if(!status)
      {
         CWriterDesc writerDesc( pinmux, "" );
         REQUIRE(
               writerDesc.predefined( *app.getReferenceList()[0].getPeripheryLink() )
                  ==
               "WKUP1 INPUT_PA0 PA0 EXTI0"
         );

      }
   }

}


//---fin-----------------------------------------------------------------------
