/***************************************************************************
**
**  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: 2006-03-22
**  Copyright: 2006-2019
**    Marc Wathelet
**    Marc Wathelet (LGIT, Grenoble, France)
**
***************************************************************************/

#include "XMLSignal.h"
#include "SignalDatabase.h"

namespace GeopsyCore {

/*!
  \class XMLSignal XMLSignal.h
  \brief XML interface for Signal

  Storage for signals in XML stream is either a reference to signal inside a database,
  or a full record of signal data (including samples). The first option is used only
  when the XML stream is created from a existing and not modified database (on a permanent
  storage).
*/

const QString XMLSignal::xmlSignalTag="Signal";

XMLSignal::XMLSignal()
{
  TRACE;
  _sig=0;
  _database=0;
  _id=0;
}

XMLSignal::XMLSignal(Signal * sig)
{
  TRACE;
  _sig=sig;
  _database=sig->database();
  _id=0;
}

void XMLSignal::xml_writeProperties(XML_WRITEPROPERTIES_ARGS) const
{
  TRACE;
  if(!_sig) return;
  if(_sig->file() && _sig->file()->format().id()!=SignalFileFormat::Temporary &&
       _sig->database()->exists() && !_sig->database()->isModified()) {
    writeProperty(s, "database", _sig->database()->name());
    writeProperty(s, "id", _sig->id());
  } else {
    _sig->xml_writeProperties(s, context);
    writeBinaryData(s, context);
  }
}

void XMLSignal::xml_writeBinaryData(XML_WRITEBINARYDATA_ARGS) const
{
  TRACE;
  Q_UNUSED(context)
  if(!_sig) return;
  if( !_sig->file() || !_sig->database()->exists() || _sig->database()->isModified()) {
    CONST_LOCK_SAMPLES(double, samples, _sig)
    s.writeRawData(( const char * ) samples, sizeof(double) * _sig->nSamples());
    UNLOCK_SAMPLES(_sig)
  }
}

bool XMLSignal::xml_setBinaryData(XML_SETBINARYDATA_ARGS)
{
  TRACE;
  Q_UNUSED(context)
  if(!_database) {
    if(_sig->nSamples()>0) {
      LOCK_SAMPLES(double, samples, _sig)
      s.readRawData((char *) samples, sizeof(double) * _sig->nSamples());
      UNLOCK_SAMPLES(_sig)
    }
  }
  return true;
}

XMLMember XMLSignal::xml_member(XML_MEMBER_ARGS)
{
  TRACE;
  Q_UNUSED(attributes)
  if(tag=="database") return XMLMember(0);
  else if(tag=="id") return XMLMember(1);
  else {
    if(!_sig) _sig=new Signal(GeopsyCoreEngine::instance()->defaultDatabase());
    return _sig->xml_member(tag, attributes, context)+4;
  }
}

bool XMLSignal::xml_setProperty(XML_SETPROPERTY_ARGS)
{
  TRACE;
  Q_UNUSED(attributes)
  switch (memberID) {
  case 0:
    _database=GeopsyCoreEngine::instance()->database(content.toString());
    if(_database) return true; else return false;
  case 1:
    _id=content.toInt();
    return true;
  default:
    if(_sig) {
      return _sig->xml_setProperty(memberID-4, tag, attributes, content, context);
    }
    return false;
  }
}

Signal * XMLSignal::signal() const
{
  TRACE;
  if(_database) {
    return _database->signal(_id);
  } else {
    return _sig;
  }
}


} // namespace GeopsyCore
