#include<iostream>

#include "MRMesh/MRMesh.h"
#include "MRMesh/MRMeshLoad.h"
#include "MRMesh/MRMeshSave.h"
#include "MRMesh/MRMeshDecimate.h"

struct MyTriMesh
{
    struct Point
    {
        double x, y, z;
    };
    using PointSet = std::vector<Point>;
    using TriangleIndices = std::array<int, 3>;
    using PrimitiveSet = std::vector<TriangleIndices>;

    PointSet        points;
    PrimitiveSet    faces;

    static MyTriMesh createTetrahedron(double r = 10)
    {
        MyTriMesh mesh
        {
            .points =
            {
                {0.0, 0.0, r},
                {0, -r, -r / 2},
                {sqrt(3) * r / 2, r / 2, -r / 2},
                {-sqrt(3) * r / 2, r / 2, -r / 2}
            },
            .faces = 
            {
                {0, 1, 2},
                {0, 1, 3},
                {0, 2, 3},
                {1, 2, 3}
            }
        };
        return mesh;
    }

    //[reference] MRMeshLoadObj.cpp fromSceneObjFile
    MR::Mesh toMRMesh() const
    {
        std::vector<MR::Vector3f> mr_points;
        MR::Triangulation mr_tris;

        for (const auto& p : points)
        {
            mr_points.emplace_back(MR::Vector3f(p.x, p.y, p.z));
        }

        for (const auto& face : faces)
        {
            MR::ThreeVertIds mr_tri{
                MR::VertId(face[0]),
                MR::VertId(face[1]),
                MR::VertId(face[2])
            };

            mr_tris.emplace_back(mr_tri);
        }

        return MR::Mesh::fromTrianglesDuplicatingNonManifoldVertices(
            MR::VertCoords(mr_points.begin(), mr_points.end()), 
            mr_tris);
    }
};

//遍历MR::Mesh的内容
// [reference] MRMeshSaveObj.cpp toObj
void print(const MR::Mesh& mesh)
{
    MR::VertId lastValidPoint = mesh.topology.lastValidVert();

    std::cout << "# points:" << std::endl;
    for (MR::VertId i{ 0 }; i <= lastValidPoint; ++i)
    {
        auto p = mesh.points[i];
        std::cout << "v " << p.x << " " << p.y << " " << p.z << std::endl;
    }

    std::cout << "# faces:" << std::endl;
    const float facesNum = float(mesh.topology.edgePerFace().size());
    size_t faceIndex = 0;
    for (const auto& e : mesh.topology.edgePerFace())
    {
        ++faceIndex;
        if (!e.valid())
        {
            continue;
        }

        // 三个顶点的索引,从0开始
        MR::VertId a, b, c;
        mesh.topology.getLeftTriVerts(e, a, b, c);
        assert(a.valid() && b.valid() && c.valid());

        //输出成Obj索引,检查是否正确
        // Obj索引从1开始
        std::cout << "f " << a + 1 << ' ' << b + 1 << ' ' << c + 1 << '\n';
    }
}

int main()
{
    std::string mrmesh_out_file = DATA_PATH "myMesh_to_mrMesh.obj";

    auto myMesh = MyTriMesh::createTetrahedron();

    auto mesh = myMesh.toMRMesh();
    MR::MeshSave::toAnySupportedFormat(mesh, mrmesh_out_file);

    print(mesh);
    return 0;
}