#pragma once

#include "Point.h"
#include "Transform.h"

#include <unordered_map>
#include <string>
#include <vector>

class Node
{
public:

    enum class State
    {
        HEALTHY,
        DIRTY
    };

    Node(const Point& p, std::size_t index = 0);

    static std::unique_ptr<Node> Create(const Point& p, std::size_t index = 0);

    ~Node();

    void apply(const Transform& transform);

    void associateEdge(std::size_t edgeId);

    void associateFace(std::size_t faceId);

    void addVectorAttribute(const std::string& tag, const std::vector<double>& values);

    void clearConnectivity();

    std::size_t getIndex() const;

    std::size_t getNumConnectedEdges() const;

    std::size_t getNumConnectedFaces() const;

    std::size_t getConnectedEdgeId(std::size_t idx) const;

    std::size_t getConnectedFaceId(std::size_t idx) const;

    State getState() const;

    const Point& getPoint() const;

    std::vector<double> getVectorAttribute(const std::string& tag) const;

    bool isCoincident(Node* node) const;

    void setState(State state);

    void setIndex(std::size_t idx);

    void updateIndex(std::size_t index);

private:
    std::unordered_map<std::string, std::vector<double> > mVectorAttributes;
    std::size_t mIndex{0};
    Point mPoint;

    std::vector<std::size_t> mAssociatedEdgeIds;
    std::vector<std::size_t> mAssociatedFaceIds;

    State mState{State::HEALTHY};
};
