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

#include "SharedMetaData.h"
#include "MetaData.h"
#include "GeoSignal.h"
#include "MetaDataMap.h"
#include "MetaDataFactory.h"

namespace GeopsyCore {

  /*!
    \class SharedMetaData SharedMetaData.h
    \brief Meta data repository at the database level

    During save and restore this structure is used for the storage of temporary
    shared meta data.
  */

  const QString SharedMetaData::xmlSharedMetaDataTag="SharedMetaData";

  SharedMetaData::SharedMetaData(const SharedMetaData& o)
  : XMLClass(), QVector<MetaData *>()
  {
    TRACE;
    for(const_iterator it=o.begin(); it!=o.end(); it++) {
      add(*it);
    }
  }

  void SharedMetaData::add(Signal * sig)
  {
    TRACE;
    const SortedVector<int, MetaData>& m=sig->metaDataMap().vector();
    int n=m.count();
    for(int i=0; i<n; i++) {
      MetaData * d=m.at(i);
      if(d->referenceCount()>1) {
        add(d);
      }
    }
  }

  void SharedMetaData::xml_writeLinks(XMLStream& s) const
  {
    TRACE;
    for(const_iterator it=begin(); it!=end(); it++) {
      (*it)->xml_writeLink(s);
    }
  }

  void SharedMetaData::setIds()
  {
    TRACE;
    int n=count();
    for(int i=0; i<n; i++) {
      (*this)[i]->setSharedId(i);
    }
  }

  void SharedMetaData::xml_writeProperties(XML_WRITEPROPERTIES_ARGS) const
  {
    TRACE;
    Q_UNUSED(context)
    static const QString indexAtt="sharedId";
    XMLSaveAttributes att;
    QString& index=att.add(indexAtt);
    int n=count();
    for(int i=0; i<n; i++) {
      const MetaData * d=at(i);
      if(d->isStored() && d->storeAsProperty()) {
        index=QString::number(i);
        d->writeProperties(s, att);
      }
    }
  }

  void SharedMetaData::xml_writeChildren(XML_WRITECHILDREN_ARGS) const
  {
    TRACE;
    static const QString indexAtt="sharedId";
    XMLSaveAttributes att;
    QString& index=att.add(indexAtt);
    int n=count();
    for(int i=0; i<n; i++) {
      const MetaData * d=at(i);
      if(d->isStored() && !d->storeAsProperty()) {
        index=QString::number(i);
        d->xml_save(s, context, att);
      }
    }
  }

  XMLMember SharedMetaData::xml_member(XML_MEMBER_ARGS)
  {
    Q_UNUSED(context)
    MetaData * d=MetaDataFactory::instance()->create(tag.toString());
    if(d) {
      static const QString indexAtt="sharedId";
      XMLRestoreAttributeIterator it=attributes.find(indexAtt);
      if(it==attributes.end()) {
        App::log(tr("Missing attribute 'sharedId' for shared meta data %1.\n").arg(tag.toString()) );
        delete d;
        return XMLMember(XMLMember::Unknown);
      }
      _lastId=it.value().toInt();
      if(_lastId>=count()) {
        resize(_lastId+1);
      }
      if((*this)[_lastId]) {
        App::log(tr("Shared meta data id %1 already exists.\n").arg(_lastId) );
        delete d;
        return XMLMember(XMLMember::Unknown);
      }
      (*this)[_lastId]=d;
      if(!d->storeAsProperty()) {
        return XMLMember(d);
      } else {
        return XMLMember(0);
      }
    } else {
      App::log(tr("Unknown MetaData %1\n").arg(tag.toString()) );
      return XMLMember(XMLMember::Unknown);
    }
  }

  bool SharedMetaData::xml_setProperty(XML_SETPROPERTY_ARGS)
  {
    Q_UNUSED(tag)
    Q_UNUSED(context)
    if(memberID==0) {
      MetaData * d=(*this)[_lastId];
      static const QString tmp("index");
      XMLRestoreAttributeIterator it=attributes.find(tmp);
      if(it!=attributes.end()) {
        d->fromString(it.value().toString(), content.toString());
      } else {
        d->fromString(0, content.toString());
      }
      return true;
    } else {
      return false;
    }
  }

} // namespace GeopsyCore
