/***************************************************************************
**
**  This file is part of GeopsyCore.
**
**  GeopsyCore 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.
**
**  GeopsyCore 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: 2010-03-20
**  Copyright: 2010-2019
**    Marc Wathelet (LGIT, Grenoble, France)
**
***************************************************************************/

#ifndef PASSCALSEGYHEADER_H
#define PASSCALSEGYHEADER_H

#include <QGpCoreTools.h>

#include "SignalFileFormat.h"
#include "GeoSignal.h"
#include "GeopsyCoreDLLExport.h"

namespace GeopsyCore {

#pragma pack(1)     /* set alignment to 1 byte boundary */

class GEOPSYCORE_EXPORT PasscalSegYHeader
{
  TRANSLATIONS("PasscalSegYHeader")
public:
  PasscalSegYHeader();

  void read(QDataStream& s);
  void write(QDataStream& s) const;

  static SignalFileFormat determineByteOrder(QString fileName, int verbosity);

  int sampleSize() const {return field.dataFormat==0 ? 2 : 4;}
  double samplingPeriod() const {return field.sampleInterval16==1 ? 1e-6*field.sampleInterval32 : 1e-6*field.sampleInterval16;}
  int nSamples() const {return field.sampleNumber16==32767 ? field.sampleNumber32 : field.sampleNumber16;}
  DateTime startTime() const;
  DateTime timePick() const;
  Signal::Components component() const;

  union {
    struct {
      qint32 raw0[7];     // 1-28
      qint16 raw1[4];     // 29-36
      qint32 raw2[8];     // 37-68
      qint16 raw3[2];     // 69-72
      qint32 raw4[4];     // 73-88
      qint16 raw5[46];    // 89-180
      char raw6[18];      // 181-198
      qint16 raw7;        // 199-200
      qint32 raw8;        // 201-204
      qint16 raw9[8];     // 205-220
      float raw10;        // 221-224
      qint16 raw11[2];    // 225-228
      qint32 raw12[3];    // 229-240
    } raw;
    struct {
      qint32 traceNumberInFile;              // 1-4
      qint32 traceNumberInReel;              // 5-8 same as above
      qint32 eventNumber;                    // 9-12 event number
      qint32 channelNumber;                  // 13-16 1 or 4 for Vertical, 2 or 5 North, 3 or 6 for East
      qint32 ignored0[3];                    // 17-28
      qint16 traceIndentificationCode;       // 29-30 seismic data=1
      qint16 ignored1[3];                    // 31-36
      qint32 ignored2[8];                    // 37-68
      qint16 elevationScale;                 // 69-70 scale=1
      qint16 coordinateScale;                // 71-72 scale=1
      qint32 ignored3[4];                    // 73-88
      qint16 coordinateUnit;                 // 89-90 =2 (Lat/Long)
      qint16 ignored4[6];                    // 91-102
      qint16 totalStaticCorrectionLow;       // 103-104 in milliseconds added to start time (lower 2 bytes) ???
      qint16 ignored5[5];                    // 105-114
      quint16 sampleNumber16;                // 115-116 Number of samples in this trace (if 32767, see sampleNumber32)
      quint16 sampleInterval16;              // 117-118 Sampling interval in microseconds (if 1, see sampleInterval32)
      qint16 gainType;                       // 119-120 Gain Type: 1=Fixed Gain
      qint16 gainConstant;                   // 121-122 Gain of amplifier
      qint16 ignored6[17];                   // 123-156
      qint16 year;                           // 157-158 year of trace
      qint16 day;                            // 159-160 day of year at Start of trace
      qint16 hour;                           // 161-162 hour at Start of trace
      qint16 minute;                         // 163-164 minute at Start of trace
      qint16 second;                         // 165-166 second at Start of trace
      qint16 timeBase;                       // 167-168 Time basis code: 2=GMT
      qint16 ignored7[6];                    // 169-180
      char stationName[6];                   // 181-186
      char sensorSerial[8];                  // 187-194
      char channelName[4];                   // 195-198
      qint16 totalStaticCorrectionHigh;      // 199-200 in milliseconds added to start time (higher 2 bytes) ???
      qint32 sampleInterval32;               // 201-204 Sample interval in MICROSECS as a 32 bit
      qint16 dataFormat;                     // 205-206 Data Format flag: 0=16 bit, 1=32 bit integer
      qint16 milliseconds;                   // 207-208 milliseconds of Start of trace
      qint16 triggerYear;                    // 209-210 year of Trigger time
      qint16 triggerDay;                     // 211-212 day of year at Trigger time
      qint16 triggerHour;                    // 213-214 hour at Trigger time
      qint16 triggerMinute;                  // 215-216 minute at Trigger time
      qint16 triggerSecond;                  // 217-218 second at Trigger time
      qint16 triggerMilliseconds;            // 219-220 milliseconds at Trigger time
      float scaleFactor;                     // 221-224 Scale factor: true amplitude=value*scaleFactor/gainConstant
      quint16 instrumentSerialNumber;        // 225-226 Instrument serial number
      qint16 ignored8;                       // 227-228
      qint32 sampleNumber32;                 // 229-232 Number of Samples as a 32 bit integer (when sampleLength==32767)
      qint32 maximumAmplitude;               // 233-236 Maximum value in Counts
      qint32 minimumAmplitude;               // 237-240 Minimum value in Counts
    } field;
  };
private:
  static bool canReadAll(QDataStream& s, qint64 fileSize);
};

#pragma pack()   // restore original alignment

} // namespace GeopsyCore

#endif // PASSCALSEGYHEADER_H
