/***************************************************************************
**
**  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)
**
***************************************************************************/

#ifndef METADATAFACTORY_H
#define METADATAFACTORY_H

#include <QGpCoreTools.h>

#include "MetaData.h"
#include "MetaDataIndex.h"
#include "GeopsyCoreDLLExport.h"

namespace GeopsyCore {

  class MetaData;

#define READONLY_STANDARD_METADATA \
    case MetaDataFactory::ID: \
    case MetaDataFactory::NSamples: \
    case MetaDataFactory::Type: \
    case MetaDataFactory::FileNumber: \
    case MetaDataFactory::NumberInFile: \
    case MetaDataFactory::FileName: \
    case MetaDataFactory::FileFormat: \
    case MetaDataFactory::MaximumAmplitude: \
    case MetaDataFactory::AverageAmplitude: \
    case MetaDataFactory::IsOriginalFile: \
    case MetaDataFactory::Pointer: \
    case MetaDataFactory::SampleSize: \
    case MetaDataFactory::CountPerUnit: \
    case MetaDataFactory::UnitPerCount: \
    case MetaDataFactory::HeaderModified: \
    case MetaDataFactory::ShortFileName: \
    case MetaDataFactory::Dummy: \
    case MetaDataFactory::DataCount:

  #define REGISTER_METADATA(_className_) \
    const QString _className_::xml##_className_##Tag=#_className_; \
    _className_ _className_::_defaultValue; \
    int _className_::_id=-1; \
    XMLREGISTER_HEAD(MetaDataFactory, XMLClassCreator, _className_, _className_::xml##_className_##Tag) \
    XMLREGISTER_TAIL(_className_)

  #define SYNONYM_METADATA(_synName_, _tagName_) \
    XMLSYNONYM(MetaDataFactory, _synName_, _tagName_)

  class GEOPSYCORE_EXPORT MetaDataFactory : public XMLClassFactory
  {
  public:
    enum StandardData {
      ID=0,
      StartTime,
      SamplingPeriod,
      NSamples,
      ReceiverX,
      ReceiverY,
      ReceiverZ,
      UtmZone,
      Name,
      Type,
      FileNumber,
      NumberInFile,
      FileName,
      Duration,
      EndTime,
      Component,
      MaximumAmplitude,
      AverageAmplitude,
      IsOriginalFile,
      SamplingFrequency,
      Pointer,
      CountPerVolt,
      VoltPerCount,
      VoltPerUnit,
      UnitPerVolt,
      CountPerUnit,
      UnitPerCount,
      AmplitudeUnit,
      SampleSize,
      HeaderModified,
      ShortFileName,
      FileFormat,
      Dummy,
      DataCount // This item should be the last standard one (= number of data)
    };

    MetaDataFactory();

    MetaDataIndex index(const QString& name) const;
    QString name(const MetaDataIndex& index) const;
    QString baseName(const MetaDataIndex& index) const;
    QString title(const MetaDataIndex& index) const;
    bool isReadOnly(const MetaDataIndex& index) const;
    bool isStored(const MetaDataIndex& index) const;
    bool isArray(const MetaDataIndex& index) const;
    int count(const MetaDataIndex& index) const;

    inline MetaData * create(int id) const;
    inline MetaData * create(const QString& tag) const;

    QList<MetaDataIndex> registeredData() const;
    QStringList registeredNames() const;

    static void init();
    static MetaDataFactory * instance() {init(); return _self;}
    int registerClass(const QString& tag, XMLClassCreator * creator);

    void registerScriptTypes(QScriptEngine * engine) const;
    void addScriptProperties(SignalHeaderObject * sig) const;
  private:
    static QString standardName(StandardData id);

    QMap<QString, MetaDataIndex> _names;

    static MetaDataFactory * _self;
  };

  inline MetaData * MetaDataFactory::create(int id) const
  {
    return  static_cast<MetaData *>(XMLClassFactory::create(id));
  }

  inline MetaData * MetaDataFactory::create(const QString& tag) const
  {
    return  static_cast<MetaData *>(XMLClassFactory::create(tag));
  }

} // namespace GeopsyCore

#endif // METADATAFACTORY_H
