/***************************************************************************
**
**  This file is part of QGpCoreTools.
**
**  This library is free software; you can redistribute it and/or
**  modify it under the terms of the GNU Lesser General Public
**  License as published by the Free Software Foundation; either
**  version 2.1 of the License, or (at your option) any later version.
**
**  This file is distributed in the hope that it will be useful, but WITHOUT
**  ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
**  FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
**  License for more details.
**
**  You should have received a copy of the GNU Lesser General Public
**  License along with this library; if not, write to the Free Software
**  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
**
**  See http://www.geopsy.org for more information.
**
**  Created: 2007-04-10
**  Copyright: 2007-2019
**    Marc Wathelet
**    Marc Wathelet (LGIT, Grenoble, France)
**
***************************************************************************/

#include "ExpressionString.h"
#include "ExpressionParser.h"
#include "CoreApplication.h"
#include "MemoryChecker.h"

namespace QGpCoreTools {

/*!
  \class ExpressionString ExpressionString.h
  \brief Brief description of class still missing

  String containing header formulas between {Return=...}
*/

void ExpressionString::clear()
{
  TRACE;
  for(QList<ExpressionActions>::iterator ite=_engines.begin();ite!=_engines.end();ite++ ) {
    qDeleteAll(*ite);
  }
  _engines.clear();
}

bool ExpressionString::setPattern(QString pattern, ExpressionContext * context)
{
  TRACE;
  _pattern="";
  const QChar * startExpression=0;
  const QChar * startString=pattern.data();
  const QChar * ptr=startString;
  while(true) {
    switch (ptr->unicode()) {
    case 0x0000:   // '\0'
      if(startString) {
        StringSection(startString, ptr).appendTo(_pattern);
      } else if(startExpression) {
        App::log(tr("Unmatched '{' before reaching the end of buffer\n") );
        return false;
      }
      return true;
    case 0x007B:  // '{'
      StringSection(startString, ptr).appendTo(_pattern);
      startExpression=ptr+1;
      startString=0;
      break;
    case 0x007D:  // '}'
      {
        ExpressionParser p;
        ExpressionActions e=p.parse(StringSection(startExpression, ptr).toString(), context);
        if(e.isEmpty()) {
          return false;
        }
        _pattern += "%"+QString::number(_engines.count());
        _engines.append(e);
      }
      startExpression=0;
      startString=ptr+1;
      break;
    case 0x0022:   // '"'
      if(startExpression) {
        if(!skipString(ptr)) return false;
      }
      break;
    default:
      break;
    }
    ptr++;
  }
}

QString ExpressionString::value( )
{
  TRACE;
  QString s=_pattern;
  for(QList<ExpressionActions>::iterator ite=_engines.begin();ite!=_engines.end();ite++ ) {
    ExpressionActions& a=*ite;
    for(ExpressionActions::iterator ita=a.begin();ita!=a.end();++ita) {
      (*ita)->value();
    }
    s=s.arg(a.context()->variableValue("Return").toString());
  }
  return s;
}

bool ExpressionString::skipString(const QChar *& ptr)
{
  TRACE;
  while(true) {
    switch (ptr->unicode()) {
    case 0x0000:
      App::log(tr("Unmatched \" before reaching the end of buffer\n"));
      return false;
    case 0x005C:   // '\\'
      ptr++;
      break;
    case 0x0022:   // '"'
      return true;
    }
    ptr++;
  }
}

} // namespace QGpCoreTools
