#define BOOST_TEST_MODULE RegularSpaceGrid
#define BOOST_TEST_DYN_LINK
#include <iomanip>
#include <boost/test/unit_test.hpp>
#include "StOpt/core/grids/RegularSpaceGrid.h"
#include "StOpt/core/utils/constant.h"

using namespace std;
using namespace Eigen;

double accuracyEqual = 1e-10;

BOOST_AUTO_TEST_CASE(StOptRegularSpaceGrid)
{
    size_t nsteps = 1000;
    double step = 400.0 / (1.0 * nsteps);
    ArrayXd minimum(1);
    for (size_t iPoint = 0; iPoint <= nsteps; iPoint++)
    {
        minimum(0) = iPoint * step;
        if (minimum(0) > 135.0 && minimum(0) < 135.3)
            break;
    }
    //minimum(0) \approx 135.20000000000002;

    ArrayXd step_grid(1);
    step_grid(0) = (140. - minimum(0));
    ArrayXi nsteps_grid(1);
    nsteps_grid(0) = 1;
    StOpt::RegularSpaceGrid grid = StOpt::RegularSpaceGrid(minimum, step_grid, nsteps_grid);

    ArrayXd point(1);
    point(0) = 135.19999999999999;

    std::stringstream ss_minimum;
    ss_minimum << std::fixed << std::setprecision(15) << minimum(0);
    cout  << "minimum: " << ss_minimum.str();
    std::stringstream ss_point;
    ss_point << std::fixed << std::setprecision(15) << point(0);
    cout  << "point: " << ss_point.str();
    cout  << "grid.isInside(point): " << grid.isInside(point);
    if (grid.isInside(point))
    {
        ArrayXi result = grid.lowerPositionCoord(point); // Assertion fails.
        cout << "grid.lowerPositionCoord(point): " << result;
    }

     // get back 1D grids in each dimension
    vector<shared_ptr<ArrayXd>> vec1DGrids = grid.get1DGrids();
    for (size_t id =0; id < vec1DGrids.size(); ++id)
      cout << "1D grids " <<    *vec1DGrids[id] << endl ;
    shared_ptr<StOpt::GridIterator> iterGenGrid = grid.getGridIterator();
    int ip =0; 
    while (iterGenGrid->isValid())
    {
      ArrayXd point = iterGenGrid->getCoordinate();
      BOOST_CHECK_CLOSE(point(0), (*vec1DGrids[0])(ip), accuracyEqual);
      ip +=1;
      iterGenGrid->next();
   }
}
