/***************************************************************************
**
**  This file is part of TapePositioningSystem.
**
**  TapePositioningSystem 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.
**
**  TapePositioningSystem 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: 2012-11-16
**  Copyright: 2012-2019
**    Marc Wathelet (ISTerre, Grenoble, France)
**
***************************************************************************/

#ifndef CLUSTER_H
#define CLUSTER_H

#include <QGpCoreMath.h>

#include "TapePositioningSystemDLLExport.h"

namespace TapePositioningSystem {

  class Node;
  class Anchorage;

  class TAPEPOSITIONINGSYSTEM_EXPORT Cluster
  {
  public:
    Cluster();
    Cluster(const Cluster& o);
    ~Cluster() {}

    bool operator==(const Cluster& o) const;
    bool operator<(const Cluster& o) const;

    enum Type {None, Quad, StrongQuad, WeakQuad};

    Type type() const {return _type;}
    QString name() const;
    double distance(Node * node1, Node * node2) const;
    Point2D coordinates(Node * node) const {return _nodes[node];}

    void setOrigin(Node * node);
    bool setQuad(QList<Node *> nodes, double maxStddev=0.0);
    bool setCoordinateSystem(Node * origin, Node * north, Node * eastward);

    Anchorage * anchorage(const Cluster& quad) const;
    bool add(const Cluster& quad, const Anchorage *anchorage, double maxStddev=0.0);

    bool isRobustQuad(double stddev) const;
    bool checkDistances(double maxStddev) const;

    QList<Node *> nodes() const {return _nodes.keys();}
    int count() const {return _nodes.count();}
    QMap<Node *, Point2D>::const_iterator find(Node * node) const {return _nodes.find(node);}
    QMap<Node *, Point2D>::const_iterator end() const {return _nodes.end();}
    bool contains(Node * node) const {return _nodes.contains(node);}

    static bool lessThan(const Cluster * c1, const Cluster * c2) {return *c1<*c2;}
    static bool equal(const Cluster * c1, const Cluster * c2) {return *c1==*c2;}
  private:
    bool calculateStrongQuad(QList<Node *> nodes, double maxStddev);
    bool calculateWeakQuad(Node * fullLinkNode, QList<Node *> nodes);
    static bool isRobustTriangle(const Point2D& a, const Point2D& b, const Point2D& c, double stddev);

    Type _type;
    Node * _origin;
    QMap<Node *, Point2D> _nodes;
  };

} // namespace TapePositioningSystem

#endif // CLUSTER_H
