/***************************************************************************
**
**  This file is part of campbelltob3.
**
**  campbelltob3 is free software: you can redistribute it and/or modify
**  it under the terms of the GNU General Public License as published by
**  the Free Software Foundation, either version 3 of the License, or
**  (at your option) any later version.
**
**  campbelltob3 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 Foobar.  If not, see <http://www.gnu.org/licenses/>
**
**  See http://www.geopsy.org for more information.
**
**  Created: 2016-06-10
**  Copyright: 2016-2019
**    Marc Wathelet (ISTerre, Grenoble, France)
**
***************************************************************************/

#ifndef TOB3SCANNER_H
#define TOB3SCANNER_H

#include <GeopsyCore.h>

class Tob3Scanner : public DeviceCardScanner
{
  Q_OBJECT
public:
  Tob3Scanner(QObject * parent=nullptr);
  ~Tob3Scanner();

  bool setFileName(const QString& fileName);

  SparseTimeRange * range() {return &_range;}
  const SparseTimeRange * range() const {return &_range;}
  Mutex * rangeMutex() {return &_rangeMutex;}

  const DateTime& referenceTime() const {return _referenceTime;}

  SubSignalPool load(SignalDatabase * db,
                     const TimeRange& userRange,
                     double minLength, double maxLength);
signals:
  void headerParsed();
  void beginAddRange(int index);
  void endAddRange();
  void beginClearRange();
  void endClearRange();
protected:
  virtual void run();
  virtual QFile * stream(QIODevice::OpenModeFlag mode);
private:
  struct Record {
    quint32 seconds;
    quint32 subSeconds;
    quint32 recordNumber;
    quint32 validationStamp;
  };

  enum DataType {IEEE4L, IEEE4B, FP2};

  bool readAsciiHeader();
  static float csiFs2ToFloat(qint16 value);
  inline bool readFrameFast(QDataStream& s, Record *rec);
  inline void readFrame(QDataStream& s, int& index);
  int allocateBuffer(double duration);
  void deleteBuffer();
  double readFrame(SignalDatabase * db, const TimeRange &r);

  QString _fileName;
  QString _stationName, _modelName, _serialNumber;
  DataType * _dataTypes;
  int _dataFrameSize, _channelCount, _recordSize, _dataSize;
  quint32 _recordPerFrame;
  quint32 _intendedTablesize;
  quint32 _validationStamp;
  double _frameInterval;
  double _frameTimeResolution;
  double _samplingPeriod;
  DateTime _referenceTime;

  class offset
  {
  public:
    offset(double t, qint64 o) {_time=t; _value=o;}
    double key() const {return _time;}
    double _time;
    qint64 _value;
  };

  SortedVector<double, offset> _offsets;
  SparseTimeRange _range;
  Mutex _rangeMutex;

  double * _countPerVolt;
  double * _voltPerUnit;
  double ** _buffer;
};

#endif // TOB3SCANNER_H
