/***************************************************************************
**
**  This file is part of matfiles.
**
**  This file may be distributed and/or modified under the terms of the
**  GNU General Public License version 2 or 3 as published by the Free
**  Software Foundation and appearing in the file LICENSE.GPL included
**  in the packaging of this file.
**
**  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 General Public License for
**  more details.
**
**  You should have received a copy of the GNU General Public License
**  along with this program. If not, see <http://www.gnu.org/licenses/>.
**
**  See http://www.geopsy.org for more information.
**
**  Created: 2013-11-21
**  Authors:
**    Marc Wathelet (ISTerre, Grenoble, France)
**
***************************************************************************/

#ifndef MATCONTEXT_H
#define MATCONTEXT_H

#ifndef GP_MATLAB_LIBS

#include <QGpCoreTools.h>

#include "MatArray.h"

class MatContext
{
public:
  MatContext();
  ~MatContext();

  void openMatrix();
  void closeMatrix();
  bool beginElement(int count);
  bool endElement();

  inline bool addInt8(qint8 val);
  inline bool addInt32(qint32 val);
  inline bool addUInt32(quint32 val);
  inline bool addDouble(double val);

  int arrayCount() const {return _arrays.count();}
  MatArray * array(int index) const {return _arrays.at(index);}
  MatArray * array(const QString& name) const;
private:
  MatArray * _current;
  enum State {Waiting, Flagging, Dimensioning, Naming, RealAdding, ImaginaryAdding, Done};
  State _state;
  int _realIndex, _imaginaryIndex, _dataCount;
  QVector<MatArray *> _arrays;
};

inline bool MatContext::addInt8(qint8 val)
{
  TRACE;
  ASSERT(_current);

  switch(_state) {
  case Naming:
    _current->addNameChar(val);
    break;
  case Waiting:
  case Flagging:
  case Dimensioning:
  case Done:
    App::log(tr("MatContext: unexpected INT8 in current state (%1)\n").arg(_state) );
    return false;
  case RealAdding:
  case ImaginaryAdding:
    break;
  }
  return true;
}

inline bool MatContext::addInt32(qint32 val)
{
  TRACE;
  ASSERT(_current);

  switch(_state) {
  case Dimensioning:
    _current->addDimension(val);
    break;
  case Waiting:
  case Flagging:
  case Naming:
  case Done:
    App::log(tr("MatContext: unexpected INT32 in current state (%1)\n").arg(_state) );
    return false;
  case RealAdding:
  case ImaginaryAdding:
    break;
  }
  return true;
}

inline bool MatContext::addUInt32(quint32 val)
{
  TRACE;
  ASSERT(_current);

  switch(_state) {
  case Flagging:
    _current->setFlags(val);
    break;
  case Waiting:
  case Dimensioning:
  case Naming:
  case Done:
    App::log(tr("MatContext: unexpected INT32 in current state (%1)\n").arg(_state) );
    return false;
  case RealAdding:
  case ImaginaryAdding:
    break;
  }
  return true;
}

inline bool MatContext::addDouble(double val)
{
  TRACE;

  switch(_state) {
  case Flagging:
  case Waiting:
  case Dimensioning:
  case Naming:
  case Done:
    App::log(tr("MatContext: unexpected DOUBLE in current state (%1)\n").arg(_state) );
    return false;
  case RealAdding:
    _current->setReal(_realIndex++, val);
    break;
  case ImaginaryAdding:
    _current->setImaginary(_imaginaryIndex++, val);
    break;
  }
  return true;
}

#endif // GP_MATLAB_LIBS

#endif // MATCONTEXT_H
