/***************************************************************************
**
**  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: 2009-08-26
**  Copyright: 2009-2019
**    Marc Wathelet
**    Marc Wathelet (LGIT, Grenoble, France)
**
***************************************************************************/

#include <QGpCoreTools.h>
#include "SACHeader.h"

namespace GeopsyCore {

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

  SAC binary format is very simple: 632 bytes of header followed by the data.
  For more informations see SAC online manual at
      http://www.iris.edu/manuals/sac/manual.html
*/

SignalFileFormat SACHeader::determineByteOrder(QString fileName)
{
  QFile f(fileName);
  if( !f.open(QIODevice::ReadOnly) ) {
    return SignalFileFormat::Unknown;
  }
  QDataStream s(&f);
  s.setByteOrder(QDataStream::LittleEndian);
  int version, iftype, leven;
  f.seek(76 * 4);
  s >> version;
  f.seek(85 * 4);
  s >> iftype;
  f.seek(105 * 4);
  s >> leven;
  if(version==6 && iftype==1 && leven)
    return SignalFileFormat::SacLittleEndian;
  f.seek(0); // reset to begin of file
  s.setByteOrder(QDataStream::BigEndian);
  f.seek(76 * 4);
  s >> version;
  f.seek(85 * 4);
  s >> iftype;
  f.seek(105 * 4);
  s >> leven;
  if(version==6 && iftype==1 && leven)
    return SignalFileFormat::SacBigEndian;
  return SignalFileFormat::Unknown;
}

SACHeader::SACHeader()
{
  TRACE;
  ASSERT(sizeof( float)==4);
  ASSERT(sizeof( SACHeader)==632);
  for(int i=0;i < 70;i++ ) floats.raw[ i ]=-12345.0;
  for(int i=0;i < 35;i++ ) ints.raw[ i ]=-12345;
  for(int i=0;i < 5;i++ ) bools.raw[ i ]=0;
  for(int i=0;i < 192;i++ ) chars.raw[ i ]=' ';
}

void SACHeader::read(QDataStream& s)
{
  TRACE;
  for(int i=0;i<70;i++) s >> floats.raw[i];
  for(int i=0;i<35;i++) s >> ints.raw[i];
  for(int i=0;i<5;i++) s >> bools.raw[i];
  s.readRawData(chars.raw, 192);
}

bool SACHeader::write(QDataStream& s)
{
  TRACE;
  qint64 offset=s.device()->pos();
  for(int i=0;i<70;i++) s << floats.raw[i];
  for(int i=0;i<35;i++) s << ints.raw[i];
  for(int i=0;i<5;i++) s << bools.raw[i];
  s.writeRawData(chars.raw, 192);
  return s.device()->pos()-offset==sizeof(float)*70+sizeof(qint32)*35+sizeof(quint32)*5+192;
}

DateTime SACHeader::startTime() const
{
  TRACE;
  if(ints.field.NZYEAR<=0 || ints.field.NZJDAY<=0) {
    return DateTime::null;
  } else {
    DateTime t(QDate(ints.field.NZYEAR, 1, 1), 0, 0.0);
    t.setTime(ints.field.NZHOUR, ints.field.NZMIN, ints.field.NZSEC);
    t.addDays(ints.field.NZJDAY-1);
    t.addSeconds(ints.field.NZMSEC*1e-3+Number::toDouble(floats.field.B));
    return t;
  }
}

} // namespace GeopsyCore
