#ifndef DIVISION_ANALYSIS_PROCESSES_HPP
#define DIVISION_ANALYSIS_PROCESSES_HPP

#include <Process.hpp>
#include <DivisionAnalysisData.hpp>
#include <CellDivision.hpp>


namespace mgx {


 /**
   * \class FilterPlanes DivisionAnalysis.hpp <DivisionAnalysis.hpp>
   *
   * FilterPlanes
   * Displays planes of the Division analysis processes
   */
  class FilterPlanes : public Process
  {
    public:
      FilterPlanes(const Process& process) : Process(process)
      {
    setName("Mesh/Division Analysis/Display and Filter Planes");
    setDesc("Displays planes of the Division analysis processes");
    setIcon(QIcon(":/images/CellDivide.png"));

    addParm("Search on","Search on","All Planes", QStringList() << "All Planes" << "Filtered Planes");  // 0
    addParm("Filter","Filter","Min Area", QStringList() << "None" << "Min Area" << "Max Area" << "Min Angle to Actual" << "Max Angle to Actual" << "Min Volume Ratio" << "Max Volume Ratio" << "Random"); // 1
    addParm("Number of Planes","Number of Planes","3");  // 2
    addParm("Min Angle Between Planes","Min Angle Between Planes","10.0"); // 3
    addParm("Draw Planes","Draw Planes","Yes",booleanChoice()); // 4
    addParm("Reset Other Mesh","Reset Other Mesh","Yes",booleanChoice()); // 5
    addParm("Plane Size","Plane Size","10.0");  // 5
    addParm("Plane Scaling 2D","Plane Scaling 2D","0.92");  // 5
    addParm("Heat Map","Heat Map","Plane Area Rel Shortest", QStringList() << "None" << "Plane Area Abs" << "Normalized Area"<<"Plane Area Rel Shortest" << "Plane Area Rel Actual" << "Angle to Actual" << "Daughter Ratio" << "Distance Centroid");  // 0
    addParm("Display Actual Plane","Display Actual Plane","Yes", booleanChoice());  // 5
    addParm("Select Actual Planes","Select Actual Planes","Yes", booleanChoice());
    }

      bool run()
      {
        Mesh *m = currentMesh();
        Mesh *m2;
        if(currentMesh() == mesh(0))
          m2 = mesh(1);
        else
          m2 = mesh(0);
        return run(m, m2, parm("Search on"), parm("Filter"), parm("Number of Planes").toInt(), parm("Min Angle Between Planes").toDouble(), 
          stringToBool(parm("Draw Planes")), stringToBool(parm("Reset Other Mesh")), parm("Plane Size").toDouble(),
          stringToBool(parm("Display Actual Plane")),stringToBool(parm("Select Actual Planes")), parm("Heat Map"));
      }

      bool run(Mesh *m, Mesh *m2, QString planes, QString filter, int maxPlanes, double maxSimilarity, bool drawPlanes, bool resetMesh2, double planeSize,
        bool actual, bool selectActual, QString heatmap);

  };

 /**
   * \class FilterPlanes DivisionAnalysis.hpp <DivisionAnalysis.hpp>
   *
   * FilterPlanes
   * Displays planes of the Division analysis processes
   */
  class ResetDivPlaneData : public Process
  {
    public:
      ResetDivPlaneData(const Process& process) : Process(process)
      {
    setName("Mesh/Division Analysis/Reset Division Data");
    setDesc("Reset Division Data");
    setIcon(QIcon(":/images/CellDivide.png"));

    addParm("Actual Planes","Actual Planes","Yes", QStringList() << booleanChoice());
    addParm("Simulated Planes","Simulated Planes","Yes", QStringList() << booleanChoice());
    addParm("Filtered Planes","Filtered Planes","Yes", QStringList() << booleanChoice());
    }

      bool run()
      {
        Mesh *m = currentMesh();

        AttrMap<int, CellDivisionAttr>& actualPlane = m->attributes().attrMap<int, CellDivisionAttr>("Cell Division Actual Plane");
        AttrMap<int, CellDivisionAttr>& planeData = m->attributes().attrMap<int, CellDivisionAttr>("Cell Division Simulated Planes");
        AttrMap<int, CellDivisionAttr>& planeDataFiltered = m->attributes().attrMap<int, CellDivisionAttr>("Cell Division Simulated Planes Filtered");

        if(stringToBool(parm("Actual Planes"))) actualPlane.clear();
        if(stringToBool(parm("Simulated Planes"))) planeData.clear();
        if(stringToBool(parm("Filtered Planes"))) planeDataFiltered.clear();

        return true;
 
      }
  };



 /**
   * \class FlatDivisionPlane DivisionAnalysis.hpp <DivisionAnalysis.hpp>
   *
   * FlatDivisionPlane
   * Display a planar approximation plane of a wall between two cells
   */
   class ComputeDivPlaneAngles : public Process
  {
    public:
      ComputeDivPlaneAngles(const Process& process) : Process(process) 
      { 
    setName("Mesh/Division Analysis/Compute Division Plane Angles");
    setDesc("Compute angles between custom directions, actual division planes and optimal division planes. Returns a heat map and saves the result in an Attribute map named Angle.");
    setIcon(QIcon(":/images/CellDivide.png"));

    addParm("Plane","Plane", "Actual", QStringList() << "Actual" << "Shortest" << "Filtered Best" << "Filtered Worst");
    addParm("Direction","Direction", "Custom Dir X", QStringList() << "Custom Dir X" << "Custom Dir Y" << "Custom Dir Z" << "Actual");
      
     }

       bool run()
       {
         Mesh *m = currentMesh();
         Mesh *m2;
         if(currentMesh() == mesh(0))
           m2 = mesh(1);
         else
           m2 = mesh(0);
         return run(m, m2, parm("Plane"), parm("Direction"));
       }
       bool run(Mesh *m, Mesh *m2, QString plane1, QString plane2);

  };




double maxPlaneSimilarity(AttrMap<int, CellDivisionAttr>& cellDivs, CellDivisionAttr cda);
}
#endif
