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

#include "MetaData.h"

namespace GeopsyCore {

  /*!
    \class MetaData MetaData.h
    \brief Abstract class to store optional values in Signal

    Derive this class for all types of optional data
  */

  /*!
    \fn QStringList subNames() const
    Returns the list of managed sub variables. This is the good place to initialize an
    internal QStringList of variable names. This list can be used in name(), baseName(),...
    This function is generally called only once upon MetaData registration.

    Never leave a TRACE in that function. This function is called by Meta data factory
    upon initialization. For some platforms, the TRACE facility might not be initialized yet.
  */

  void MetaData::writeProperties(XMLStream& s, const XMLSaveAttributes& attributes) const
  {
    TRACE;
    if(storeAsProperty()) {
      writeProperty(s, xml_tagName(), attributes, toString(0));
    }
  }

  /*!
    \fn MetaData::setIndex(int index)

    Sets internal index to \a index. It is used only when saving as XML,
    as a reference in Signal entities.

    \sa SharedMetaTable::setIndexes()
  */

  void MetaData::xml_writeLink(XMLStream& s) const
  {
    TRACE;
    XMLSaveAttributes att;
    att.add("index", QString::number(_sharedId));
    XMLClass::writeProperty(s, xml_tagName(), att);
  }

  bool MetaInteger::setData(int subId, const QString& index, const QVariant& val)
  {
    Q_UNUSED(subId)
    Q_UNUSED(index)
    bool ok;
    _value=val.toInt(&ok);
    return ok;
  }

  /*!
    Used by Signal::compare() to sort signal in viewers.
  */
  int MetaInteger::compare(int subId, const QString& index, const MetaData &o) const
  {
    Q_UNUSED(subId)
    Q_UNUSED(index)
    int v1=value();
    int v2=reinterpret_cast<const MetaInteger&>(o).value();
    if(v1<v2) return -1;
    else if(v1>v2) return 1;
    else return 0;
  }

  bool MetaDouble::setData(int subId, const QString& index, const QVariant& val)
  {
    Q_UNUSED(subId)
    Q_UNUSED(index)
    bool ok;
    _value=val.toDouble(&ok);
    return ok;
  }

  /*!
    Used by Signal::compare() to sort signal in viewers.
  */
  int MetaDouble::compare(int subId, const QString& index, const MetaData& o) const
  {
    Q_UNUSED(subId)
    Q_UNUSED(index)
    double v1=value();
    double v2=reinterpret_cast<const MetaDouble&>(o).value();
    if(v1<v2) return -1;
    else if(v1>v2) return 1;
    else return 0;
  }

  bool MetaArrayInteger::setData(int subId, const QString& index, const QVariant& val)
  {
    Q_UNUSED(subId)
    bool ok;
    int i=index.toInt(&ok);
    if(ok && i<count(0)) {
      setValue(i, val.toInt(&ok));
      return ok;
    } else {
      return false;
    }
  }

  /*!
    Used by Signal::compare() to sort signal in viewers.
  */
  int MetaArrayInteger::compare(int subId, const QString& index, const MetaData& o) const
  {
    Q_UNUSED(subId)
    int v1=value(index.toInt());
    int v2=reinterpret_cast<const MetaArrayInteger&>(o).value(index.toInt());
    if(v1<v2) return -1;
    else if(v1>v2) return 1;
    else return 0;
  }

  bool MetaArrayDouble::setData(int subId, const QString& index, const QVariant& val)
  {
    Q_UNUSED(subId)
    bool ok;
    int i=index.toInt(&ok);
    if(ok && i<count(0)) {
      setValue(i, val.toDouble(&ok));
      return ok;
    } else {
      return false;
    }
  }

  /*!
    Used by Signal::compare() to sort signal in viewers.
  */
  int MetaArrayDouble::compare(int subId, const QString& index, const MetaData& o) const
  {
    Q_UNUSED(subId)
    double v1=value(index.toInt());
    double v2=reinterpret_cast<const MetaArrayDouble&>(o).value(index.toInt());
    if(v1<v2) return -1;
    else if(v1>v2) return 1;
    else return 0;
  }

  bool MetaString::setData(int subId, const QString& index, const QVariant& val)
  {
    Q_UNUSED(subId)
    Q_UNUSED(index)
    _value=val.toString();
    return true;
  }

  /*!
    Used by Signal::compare() to sort signal in viewers.
  */
  int MetaString::compare(int subId, const QString& index, const MetaData &o) const
  {
    Q_UNUSED(subId)
    Q_UNUSED(index)
    const QString& v1=value();
    const QString& v2=reinterpret_cast<const MetaString&>(o).value();
    if(v1<v2) return -1;
    else if(v1>v2) return 1;
    else return 0;
  }

  QString MetaArrayInteger::toString(const QString& index) const
  {
    bool ok;
    int i=index.toInt(&ok);
    if(ok && i<count(0)) {
      return QString::number(value(i));
    } else {
      return QString();
    }
  }

  bool MetaArrayInteger::fromString(const QString& index, QString val)
  {
    bool ok;
    int i=index.toInt(&ok);
    if(ok && i<count(0)) {
      setValue(i, val.toInt(&ok));
      return ok;
    } else {
      return false;
    }
  }

  QString MetaArrayDouble::toString(const QString& index) const
  {
    bool ok;
    int i=index.toInt(&ok);
    if(ok && i<count(0)) {
      return QString::number(value(i), 'g', 20);
    } else {
      return QString();
    }
  }

  bool MetaArrayDouble::fromString(const QString& index, QString val)
  {
    bool ok;
    int i=index.toInt(&ok);
    if(ok && i<count(0)) {
      setValue(i, val.toDouble(&ok));
      return ok;
    } else {
      return false;
    }
  }

} // namespace GeopsyCore
