/**
 * 
 * Test FM1 (FMMPC order 1) on plane case with planar wavefront
 * 
 */

#include "FMPointCloud.h"
#include "FMPCField.h"
#include "FM1PC.h"

#include <limits>

// read parameters given to exe
// 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]);
//     return true;
//   } else {
//     *ptsFile = "";
//     *lc_ = 0;
//     *distRef_ = 0;
//     return false;
//   }
// }

// read parameters given to exe
bool getParameters(int argc, char* argv[], std::string* ptsFile, double* lc_){
  if(argc > 2){
    *ptsFile = argv[1];
    *lc_ = atof(argv[2]);
    return true;
  } else {
    *ptsFile = "";
    *lc_ = 0;
    return false;
  }
}

double expectedValue(double x, double y, double z){
  return 2;
}

int main(int argc, char* argv[]){
    // 0. some algo param
    // const int nbNeib = 9; // nb neighbours for graph
    const int nbNeib = 13;
    const npoint3 pt1(-1,-1,0); //1st point on wavefront (WF)
    //const npoint3 pt2(-1,1,0); //2nd point on WF
    const npoint3 normWF(1.,0,0); // normal of WF


    std::string PCfile;
    double lc;
    double distRef = 2.;
    // 1. get data
    if(!getParameters(argc,argv,&PCfile,&lc)){
        std::cerr << "Unable to read given parameters !" << std::endl;
        return 1;
    }
    
    std::cout << "Create PC..." << std::endl;
    
    FM::FMPointCloud PC;
    PC.readFromMSH(PCfile);
    
    std::cout << "MSH file read. " << PC.getNbrNodes() << " nodes found." << std::endl;

    // 2. build graph
    std::cout << " Building graph" << std::endl;
    PC.buildTree();
    PC.buildGraph(nbNeib);
    //PC.applyNormCurvPlane(npoint3(0,0,1),npoint3(1,0,0));
    
    // 3. Distance field
    std::cout << "Create distance field..." << std::endl;
    FM::FMPCField dataField(&PC);

    // 4. FM
    std::cout << "Calling FM1..." << std::endl;
    FM::FM1PC algoFM1(&PC,&dataField);
    
    // for debug only :
    //algoFM1.printLog();
    
    algoFM1.initiateFM(pt1,normWF);
    algoFM1.propagateFM();
    
    
    // 4. write results
    
    // for debug only :
    //dataField.exportMSH("",true);
    //dataField.exportCSV();
    
    // test results
    double meanError = abs(dataField.meanErrorLine(npoint3(1,1,0),npoint3(1,-1,0),expectedValue,lc));
    std::cout << setprecision(numeric_limits<double>::max_digits10);
    std::cout << "== Mean error along edge : " << meanError << " (must <= 1e-16 to pass test)." << std::endl;
    
    if(meanError <= 1e-13){
        return 0;
    } else {
        return 1;
    }
}
