/***************************************************************************
**
**  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: 2007-10-20
**  Copyright: 2007-2019
**    Marc Wathelet
**    Marc Wathelet (LGIT, Grenoble, France)
**
***************************************************************************/

#include <QGpCoreTools.h>
#include <mseed.h>

#include "MiniSeedVolume.h"
#include "MiniSeedTrace.h"

namespace GeopsyCore {

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

  Represents a Mini Seed volume.
  This class is used only while reading a new file.
*/

MiniSeedVolume::~MiniSeedVolume()
{
  TRACE;
  qDeleteAll(*this);
}

void MiniSeedVolume::nonAsciiPathError(QString fileName)
{
  TRACE;
  Message::warning(MSG_ID, tr("Loading Miniseed"),
                   tr("File path contains non-ASCII characters. This is a current limitation of IRIS MiniSeed library. "
                      "Move your file to a directory path with ASCII characters only.\n%1")
                   .arg(fileName), Message::cancel(), true);
}

/*!
  Parse a Mini seed volume and fill its internal list of MiniSeedTrace pointers
*/
bool MiniSeedVolume::read(QString name)
{
  TRACE;
  LibMSeed::MSRecord * msr=nullptr;
  int msErr=0;
  off_t currentPos=0;
  /* Read next seed record with
      int reclen=-1            Use automatic record length (usually read from Blockette 1000)
      off_t *fpos=currentPos   Store all position of records in file
      int *last =nullptr            Don't care about last record, just wait for MS_ENDOFFILE
      flag skipnotdata=1       Skip all invalid data chunks
      flag dataflag=0          Do not unpack values
      flag verbose=0           Be not verbose
  */
  // TODO: look for another way with UNICODE support for file names, tried with utf-8, but it does not work either.
  if(QString(name.toLatin1())!=name) {
    nonAsciiPathError(name);
    return false;
  }
  while((msErr=ms_readmsr(&msr, name.toLatin1().data(), -1, &currentPos, nullptr, 1, 0, 0))==MS_NOERROR) {
    MiniSeedTrace * sig=findTrace(msr);
    if(!sig) {
      sig=new MiniSeedTrace(msr);
      append(sig);
    }
    sig->addRecord(msr, currentPos);
  }
  ms_readmsr (&msr, nullptr, 0, nullptr, nullptr, 0, 0, 0);
  if(msErr!=MS_ENDOFFILE) {
    errorMessage(name, tr("Loading Miniseed"), msErr);
    return false;
  }
  // Check continuity of traces and split non-continuous traces
  for(int i=0; i<count(); i++) {
    MiniSeedTrace * sig=at(i);
    while(true) {
      sig=sig->split();
      if(sig) {
        i++;
        insert(i, sig);
      } else {
        break;
      }
    }
  }
  return true;
}

MiniSeedTrace * MiniSeedVolume::findTrace(LibMSeed::MSRecord * msr)
{
  TRACE;
  for(int i=count()-1; i>=0; i--) {
    if(at(i)->belongsTo(msr) ) return at(i);
  }
  return nullptr;
}

bool MiniSeedVolume::isValid(QString fileName)
{
  TRACE;
  LibMSeed::MSRecord *msr=nullptr;
  int msErr=ms_readmsr (&msr, fileName.toLatin1().data(), -1, nullptr, nullptr, 1, 0, 0);
  ms_readmsr (&msr, nullptr, -1, nullptr, nullptr, 1, 0, 0);
  return msErr==MS_NOERROR;
}

void MiniSeedVolume::errorMessage(QString fileName, QString title, int errorCode)
{
  TRACE;
  QString msg=errorString(errorCode);
  if(!msg.isEmpty()) {
    Message::warning(MSG_ID, title, msg.arg(fileName), Message::cancel(), true);
  }
}

void MiniSeedVolume::errorLog(QString fileName, QString title, int errorCode)
{
  TRACE;
  QString msg=errorString(errorCode);
  if( !msg.isEmpty()) {
    App::log(title+":"+msg.arg(fileName)+"\n");
  }
}

QString MiniSeedVolume::errorString(int errorCode)
{
  TRACE;
  switch(errorCode) {
  case MS_NOERROR:
    return QString();
  case MS_NOTSEED:
    return tr("%1 is not a seed volume");
  case MS_WRONGLENGTH:
    return tr("%1, wrong data length");
  case MS_OUTOFRANGE:
    return tr("%1, record length out of range");
  case MS_UNKNOWNFORMAT:
    return tr("%1, unknown data encoding");
  case MS_STBADCOMPFLAG:
    return tr("%1, Steim, invalid compression flag(s)");
  case MS_GENERROR:
    return tr("%1, generic unspecified error");
  case MS_ENDOFFILE:
    return tr("%1, end of file");
  default:
    return tr("%1, unknown error");
  }
}

} // namespace GeopsyCore
