#include "FMPointCloud.h"
#include "FM1PC.h"
#include <limits>

bool getParameters(int argc, char* argv[], std::string* ptsFile, double* lc_, double* distRef_){
  if(argc > 3){
    *ptsFile = argv[1];
    *lc_ = atof(argv[2]);
    *distRef_ = atof(argv[3]);
    //*nbNeib_ = atoi(argv[3]);
    return true;
  } else {
    *ptsFile = "";
    *lc_ = 0;
    *distRef_ = 0;
    //*nbNeib_ = 0;
    return false;
  }
}

int main(int argc, char* argv[]){

  std::string PCfile;
  double lc, distRef;
  // int nbNeib = 12; // carre
  // int nbNeib = 9;
  int nbNeib = 8;
  if(!getParameters(argc,argv,&PCfile,&lc,&distRef)){
    std::cerr << "Unable to read given parameters !" << std::endl;
    return 1;
  }
  
  // std::vector<npoint3> seeds{npoint3(-.5,-.5,0.),npoint3(.5,.5,0.)}; // "carre" case
  std::vector<npoint3> seeds{npoint3(1.,0.,0.),npoint3(-1,0.,5.)}; // "labysmooth" case
  
  // Point Cloud
  FM::FMPointCloud PC;
  PC.readFromMSH(PCfile);
  PC.buildTree();
  PC.buildGraph(nbNeib);
  //PC.trimOutsideAdj();
  // PC.applyNormCurvCylinder(npoint3(0,0,1),1.); // "labysmooth" case
  //PC.applyNormCurvPlane(npoint3(0.,0.,1),npoint3(1.,0.,0.)); // "carre" case
  
  // Distance field
  FM::FMPCField dataField(&PC);
  
  // Algo FM0
  // std::cout << "Create object" << std::endl;
  FM::FM1PC2LS algo(&PC,seeds[0],seeds[1]);
  // std::cout << "Generate fields..." << std::endl;
  algo.generateFields();
  // std::cout << "Field generated" << std::endl;
  
  // Results
  double dist1 = algo.getLength();
  // std::cout << " get lenght ok" << std::endl;
  double error = (dist1-distRef)/distRef;

  //algo.exportAllMSH();
  //std::cout << "dist 1 = "<< dist1 << std::endl;
  
  //algo.exportAllMSH(true);
  
  std::cout << PC.getNbrNodes();
  std::cout << setprecision(numeric_limits<double>::max_digits10);
  std::cout << " " << distRef/lc << " " << error << std::endl;

  //std::cout.flush();
  
  return 0;
}
