/***************************************************************************
**
**  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: 2011-05-16
**  Copyright: 2011-2019
**    Marc Wathelet (ISTerre, Grenoble, France)
**
***************************************************************************/

#ifndef ABSTRACTSIGNALGROUP_H
#define ABSTRACTSIGNALGROUP_H

#include <QGpCoreTools.h>

#include "GeopsyCoreDLLExport.h"
#include "TimeRange.h"

class QIcon;

namespace GeopsyCore {

  class Signal;
  class SignalDatabase;
  class SubSignalPool;
  class MasterSignalGroup;

  class GEOPSYCORE_EXPORT AbstractSignalGroup: public TreeContainer
  {
  public:
    AbstractSignalGroup(AbstractSignalGroup * parent=nullptr);
    virtual ~AbstractSignalGroup() {}

    virtual void setParent(AbstractSignalGroup * p);

    virtual QString name() const {return _name;}
    virtual void setName(const QString& n);
    QString pathName() const;

    QString comments() const {return _comments;}
    void setComments(const QString& c);

    int id() const {return _id;}
    void setId(int id);

    bool isModified() const;
    void setModified(bool m);

    const QString& script() const {return _script;}
    void setScript(const QString& s) {_script=s;}

    const TimeRange& timeRange() const {return _timeRange;}
    void setTimeRange(const TimeRange& r) {_timeRange=r;}

    const AbstractSignalGroup * find(QString name) const;
    const AbstractSignalGroup * find(int id) const;
    QList<const AbstractSignalGroup *> find(const QRegExp& name) const;
    AbstractSignalGroup * find(QString name);
    AbstractSignalGroup * find(int id);
    QList<AbstractSignalGroup *> find(const QRegExp& name);

    QList<const AbstractSignalGroup *> find(const Signal * sig) const;
    QList<const AbstractSignalGroup *> list() const;

    virtual bool readOnly() const {return false;}
    virtual bool readOnlyChildren() const {return false;}
    virtual bool stored() const {return true;}
    virtual int signalCount() const;
    virtual bool hasOwnSignal() const {return false;}
    bool contains(const Signal * sig) const;
    virtual bool directlyContains(const Signal * sig) const;
    virtual SubSignalPool subPool() const;

    virtual bool convertIds(const QHash<int, Signal *>& ids);

    virtual void removeSignal(Signal * sig);

    virtual const QIcon * icon() const;
    void printList(QString prefix) const;

    static inline bool lessThan(AbstractSignalGroup * g1, AbstractSignalGroup * g2);

    const MasterSignalGroup * master() const;
    MasterSignalGroup * master();
    AbstractSignalGroup * parent() {return static_cast<AbstractSignalGroup *>(TreeContainer::parent());}
    const AbstractSignalGroup * parent() const {return static_cast<const AbstractSignalGroup *>(TreeContainer::parent());}
    AbstractSignalGroup * childAt(int index) {return static_cast<AbstractSignalGroup *>(TreeContainer::childAt(index));}
  protected:
    virtual void xml_writeProperties(XML_WRITEPROPERTIES_ARGS) const;
    void xml_writeChildren(XML_WRITECHILDREN_ARGS) const;
    virtual XMLMember xml_member(XML_MEMBER_ARGS);
    virtual bool xml_setProperty(XML_SETPROPERTY_ARGS);
    virtual void xml_polishChild(XML_POLISHCHILD_ARGS);

    virtual void reportParentAboutToBeChanged(AbstractSignalGroup * g, AbstractSignalGroup * newParent) const;
    virtual void reportParentChanged(AbstractSignalGroup * g, AbstractSignalGroup * oldParent) const;
    virtual void reportDataChanged(AbstractSignalGroup * g) const;

    int countId(int id, int& newId) const;
  private:
    void groupPath(QString& name, QString& subName) const;
    QString pathNameHelper() const;
    bool isSameMaster(const AbstractSignalGroup * o) const;
    void resetModified();
    void find(QList<const AbstractSignalGroup *>& groups, const Signal * sig) const;

    QString _name;
    QString _comments;
    int _id;
    bool _modified;
    TimeRange _timeRange;
    QString _script;
  };

  inline bool AbstractSignalGroup::lessThan(AbstractSignalGroup * g1, AbstractSignalGroup * g2)
  {
    TRACE;
    return g1->name()<g2->name();
  }

} // namespace GeopsyCore

#endif // ABSTRACTSIGNALGROUP_H
