//----------------------------------------------------------------------------
///
/// \file   constructor.cpp
///
/// \brief  arena class for handling c++ constructors
///
/// \date   20180215
/// \author Maximilian Seesslen <mes@seesslen.net>
///
//----------------------------------------------------------------------------


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


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


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

#include <QFile>
#include <QJsonDocument>
#include <QDir>
#include <QDebug>

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

#include "constructor.h"
#include "formaterCpp.h"
#include "helpers.h"


//---Declaration---------------------------------------------------------------


bool CConstructorPool::loadFile(const QString &fileName)
{
   QFile file;
   bool sta=true;

   addPath( QFileInfo( fileName ).dir().path() );
   m_loadedFiles+=fileName;

   file.setFileName(fileName);
   if(!file.open(QIODevice::ReadOnly | QIODevice::Text))
   {
      qFatal( "Constructor file does not exist: %s", qPrintable(fileName));
   }
   sta=loadByteArray( file.readAll(), fileName );
   if( !sta )
   {
      qDebug() << "Parse Error in file " << fileName << ": " ;
   }
   file.close();

   return(sta);
}


bool CConstructorPool::loadByteArray(const QByteArray &array, const QString &fileName)
{
    QJsonDocument settdoc;
    QJsonObject jsonObject;
    QJsonParseError error;
    QStringList includes;
    bool sta=true;

    settdoc=QJsonDocument::fromJson(array, &error);
    if(error.error != QJsonParseError::ParseError::NoError )
    {
       qDebug() << "Parse Error in file " << fileName << ": " ;
       qDebug() << error.errorString() << " at offset " << error.offset;
       if(error.offset>40)
       {
          QString line=array.mid(error.offset-50, 100);
          qDebug() << "Line: " << line;
          qDebug() << "Line: " << QString("%1").arg('|', 50);
       }
       return(false);
    }
    jsonObject = settdoc.object();

    parseJson(jsonObject, includes);

    for( const auto &include: includes )
    {
       QDir dir;
       QString fileName=findPathFile( include );
       if(!fileName.isEmpty())
       {
         sta=loadFile( fileName );
       }
        else
       {
            qFatal("Can not include unknown board:%s", qPrintable( include ) );
       }
    }
    return(sta);
}


int CConstructorPool::parseJson(const QJsonObject &jsonObject, QStringList &includes)
{
   QString frameWork = jsonObject["framework"].toString();
   QJsonArray jsonArray = jsonObject["constructors"].toArray();
   includes=jsonArrayToStringList( jsonObject["include"].toArray() );
   if( ! frameWork.isEmpty() )
   {
      setFrameWork( frameWork );
   }
 
   for(const auto &value: jsonArray)
   {
      QJsonObject object=value.toObject();
      QString type = object["type"].toString();
      if( object["status"].toString() == "disabled" )
      {
         continue;
      }
      CConstructor constructor(type, object["arguments"].toArray());

      constructor.setClass(object["class"].toString());
      constructor.setIncludeHeader(object["header"].toString());
      constructor.setFrameWork( frameWork );

      /*
      QString implementation;
      QStringList implementationList=jsonArrayToStringList( object["implementation"].toArray() );
      for(QString line: implementationList)
      {
         implementation+=line;
         implementation+="\n";
      }
      if(! implementation.isEmpty() )
      {
         implementation+="\n";
      }
      constructor.setImplementation( implementation );
      */

      constructor.setJsonObject( object );

      addConstructor(constructor);
   }

   return(0);
}

const CConstructor *CConstructorPool::getConstructor(CPeripheryConstPtr periphery) const
{
   for(const auto &lconstructor: constructorList)
   {
      if(lconstructor.getType()==periphery->getPeripheryType())
         return(&lconstructor);
   }

   return(nullptr);
}

/*
QStringList CConstructor::getInitFunctions() const
{
   QStringList list;
   QString initFunction=getAttribute( "initFunction" );
   if( ! initFunction.isEmpty() )
   {
      list << initFunction;
   }
   QStringList initFunctions=getAttributeList( "initFunctions" );
   list << initFunctions;
   
   return(list);
}
*/

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