/**
 * C++ fast marching on point cloud Library
 * Copyright (c) 2000-2026 Eric Bechet <eric at bechet dot ca>
 * 
 * This file is part of the C++ Mesh Generation Library.
 *  See the NOTICE & LICENSE files for conditions.
 * 
 * Version 2.0 (March 2025)
 */

 #ifndef FM1PC_H
 #define FM1PC_H
 
 #include "FMPCAlgo.h"

 #include <thread>
 
 namespace FM
 {
 
 class FM1PC : public FMPCAlgo12
 {
   protected :

   /* PROPAGATION FUNCTIONS */

   double computeDataTrig(int& idx1, int& idx2, npoint3& pt3, npoint3& fTrav, double* xi=nullptr);

  //  double computeDataMain(int &idx1, int &idx2, int &idx3, npoint3 &grad, npoint3 *&norm) override;

  //  void estimateError(resultComputation& result);

   void estimateError(std::vector<resultComputation>& results);

   public :

   /// @brief Build FM0 solver
   /// @param PC_ Point cloud
   /// @param data_ Data field (to fill)
   /// @param correctCurv Enable correction for the surface curvature
   FM1PC(FMPointCloud* PC_, FMPCField* data_, bool correctCurv = false) : FMPCAlgo12(PC_,data_,correctCurv) {
      // fixing node already computed
      FMPCAlgo::preFixData(data_,0);
      data_->setOrder(1);
   }

  //  void categorizeTriangle(int& idx3, int& idx1,std::vector<int>& idxs, std::vector<int>& inside, std::vector<int>& outside) override;

   void categorizeTriangle(int& idx3, int& idx1, std::vector<int>& idxs, std::vector<std::pair<double,int>>& candidates) override;

   resultComputation computeTriangles(int& idx1, int& idx3, std::vector<int>& sndPoints) override;

   bool isFMpossible(int& idx1, int& idx2, int& idx3) override;

   bool updatable(int idx1, int idx3) override;

   /* INTERPOLATION FUNCTION */

   //double interpolate(npoint3& pt){ return FMPCAlgo12::interpolate(pt); }

   /// @brief Function interpoling point from data using FM0 computation
   /// @param pt Point where interpolate distance
   /// @return Distance interpolated
   //double interpolate(npoint3& pt, npoint3& grad) override;

   double computeInterpolation(int& idx1, int& idx2, npoint3& pt, npoint3& grad) override;
 
 }; // class FM1PC (1LS)


/**
 * 
 * FM1PC 2 LEVEL SET (FM1PC2LS)
 * 
 */

 class FM1PC2LS {

  protected :

  FMPCField* fields[4] = {};

  FM1PC* algos[2] = {};

  npoint3 seeds[2];

  FMPointCloud* PC;

  public :

  FM1PC2LS(FMPointCloud* PC_, const npoint3& pt1, const npoint3& pt2);

  ~FM1PC2LS();

  /* FIELDS FUNCTIONS */

  void generateFields()
  { generateMainFields(); generateSecondaryFields();}

  void generateMainFields();

  void generateSecondaryFields();

  /* COMPUTATION FUNCTIONS */

  void findMiddlePoint(npoint3& midPoint);

  double getLength();

  /* EXPORT FUNCTIONS */

  void exportAllMSH(bool addGrad = false) const;

  void exportSecondaryMSH(std::string file="secondaryFields.msh") const;

  void exportAllCSV() const;

 }; // class FM1PC2LS
 
 }
 
 #endif // FM1PC_H