#include "topologyToVTK.h"
#include <thread>

#include <IVtkOCC_Shape.hxx>
#include <IVtkOCC_ShapeMesher.hxx>
#include <IVtkVTK_ShapeData.hxx>
#include <TopExp_Explorer.hxx>
#include <vtkPolyDataWriter.h>

json topologyToVTK::saveSolidAsVTK(TopoDS_Shape& shape, std::string dirPath, int counter)
{
    std::list<std::thread*> th_list; //TODO: Maybe we should have some maximum thread count?

    int faceId = 0;
    json vtkData = json::array();
    for (TopExp_Explorer ex(shape, TopAbs_FACE); ex.More(); ex.Next(), faceId++)
    {
        std::string faceName = std::string("Face_") + std::to_string(faceId);
        std::string facePath = dirPath + std::string("\\") + faceName + std::string(".vtk");
        std::thread* th = new std::thread(saveShapeAsVtk, ex.Current(), facePath);
        json faceJSON = { {"id", faceId}, /*{"isInternal", internalState},*/ {"name", faceName}, {"previewPath", facePath} };
        vtkData.push_back(faceJSON);
        th_list.push_back(th);
    }


    std::string solidName = std::string("Volume_") + std::to_string(counter + 1);
    std::string solidPath = dirPath + std::string("\\") + solidName + std::string(".vtk");
    std::thread* th =  new std::thread(saveShapeAsVtk, shape, solidPath);
    th_list.push_back(th);
    json domain = { {"id", counter},
                {"boundaries", vtkData},
                {"name", solidName},
                {"previewPath", solidPath} };

    for (auto it : th_list)
    {
        it->join();
        delete(it);
    }

    return domain;
}

void topologyToVTK::saveShapeAsVtk(TopoDS_Shape& shape, std::string filename)
{
    IVtkOCC_Shape::Handle aShapeImpl = new IVtkOCC_Shape(shape);
    if (!aShapeImpl.IsNull())
    {
        IVtkVTK_ShapeData::Handle aDataImpl = new IVtkVTK_ShapeData();
        IVtk_IShapeMesher::Handle aMesher = new IVtkOCC_ShapeMesher();
        aMesher->Build(aShapeImpl, aDataImpl);
        vtkSmartPointer< vtkPolyData > aPolyData = aDataImpl->getVtkPolyData();
        if (aPolyData)
        {
            vtkSmartPointer<vtkPolyDataWriter> PDWriter = vtkSmartPointer<vtkPolyDataWriter>::New();
            //logging::log(logging::DEBUG, filename);
            PDWriter->SetFileName(filename.c_str());
            PDWriter->SetFileTypeToASCII();
            PDWriter->SetInputData(aPolyData);
            PDWriter->Write();
        }
        else
        {
            //logging::log(logging::DEBUG, "aPolyData is null");
        }
    }
    else
    {
        //logging::log(logging::DEBUG, "aShapeImpl is null");
    }
}