#pragma once

#include "AbstractMesh.h"

#include <string>
#include <unordered_map>

class Edge;
class AbstractFace;

using EdgePtr = std::unique_ptr<Edge>;
using AbstractFacePtr = std::unique_ptr<AbstractFace>;

using VecEdges = std::vector<EdgePtr>;
using VecFaces = std::vector<AbstractFacePtr>;

class FaceMesh : public AbstractMesh
{
public:
    FaceMesh() = default;

    ~FaceMesh();

    virtual std::unique_ptr<AbstractMesh> copy() const = 0;

    void populate(VecNodes& nodes, VecEdges& edges, VecFaces& faces);

    std::vector<std::size_t> getFaceNodeIds() const;

    std::vector<std::size_t> getEdgeNodeIds() const;

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

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

    void merge(std::unique_ptr<FaceMesh> mesh);

    const VecFaces& getFaces() const;

protected:
    void resetConnectivity();

    void resetIds();

    void replaceIfOverlapping(FaceMesh* mesh, Node* node) const;

    void replaceIfOverlapping(FaceMesh* mesh, Edge* edge) const;

    VecEdges mEdges;
    VecFaces mFaces;
};
