/* +------------------------------------------------------------------------+
   |                     Mobile Robot Programming Toolkit (MRPT)            |
   |                          https://www.mrpt.org/                         |
   |                                                                        |
   | Copyright (c) 2005-2023, Individual contributors, see AUTHORS file     |
   | See: https://www.mrpt.org/Authors - All rights reserved.               |
   | Released under BSD License. See: https://www.mrpt.org/License          |
   +------------------------------------------------------------------------+ */

#include <mrpt/config/CConfigFile.h>
#include <mrpt/maps/COccupancyGridMap2D.h>
#include <mrpt/maps/CSimplePointsMap.h>
#include <mrpt/obs/CObservation2DRangeScan.h>
#include <mrpt/poses/CPose2D.h>
#include <mrpt/system/CTicTac.h>
#include <mrpt/system/filesystem.h>
#include <mrpt/system/os.h>

#include <iostream>

using namespace mrpt;
using namespace mrpt::system;
using namespace mrpt::obs;
using namespace mrpt::maps;
using namespace mrpt::poses;
using namespace std;

#include <mrpt/examples_config.h>
string myDataDir(
	MRPT_EXAMPLES_BASE_DIRECTORY +
	string("maps_gridmap_likelihood_characterization/"));

// Default .ini file:
string iniFile(myDataDir + string("config_likelihood.ini"));

// ------------------------------------------------------
//				theMainThing
// ------------------------------------------------------
void theMainThing()
{
	COccupancyGridMap2D gridMap;
	CObservation2DRangeScan obsScan;
	CTicTac tictac;

	// Load the grid map from file
	// ----------------------------------------------
	obsScan.aperture = M_2PIf;

	ASSERT_(mrpt::system::fileExists(iniFile));
	mrpt::config::CConfigFile cfgFile(iniFile);

	string bmp = cfgFile.read_string("Params", "bitmap_file", "", true);
	float res =
		cfgFile.read_float("Params", "evaluation_grid_resolution", 0.1f, true);

	float evalgrid_x_min = 0, evalgrid_x_max = 0;
	float evalgrid_y_min = 0, evalgrid_y_max = 0;

	MRPT_LOAD_CONFIG_VAR_NO_DEFAULT(evalgrid_x_min, float, cfgFile, "Params");
	MRPT_LOAD_CONFIG_VAR_NO_DEFAULT(evalgrid_x_max, float, cfgFile, "Params");
	MRPT_LOAD_CONFIG_VAR_NO_DEFAULT(evalgrid_y_min, float, cfgFile, "Params");
	MRPT_LOAD_CONFIG_VAR_NO_DEFAULT(evalgrid_y_max, float, cfgFile, "Params");

	int type_experiment = 0;
	MRPT_LOAD_CONFIG_VAR_NO_DEFAULT(type_experiment, int, cfgFile, "Params");

	// Gridmap:
	string GRIDMAP_FILE(myDataDir + bmp);

	gridMap.loadFromBitmapFile(GRIDMAP_FILE, 0.05f);
	gridMap.saveAsBitmapFile("./out_gridmap.png");

	if (type_experiment == 0)
	{
		// Simulate scan:
		// ----------------------------------------------
		obsScan.aperture = M_PIf;
		obsScan.maxRange = 80.0f;
		obsScan.rightToLeft = true;
		gridMap.laserScanSimulator(obsScan, CPose2D(0, 0, 0), 0.5f, 180);
	}
	else
	{
		// Lik. of each 2D  position
		// ------------------------------------
		obsScan.aperture = 0;
		obsScan.maxRange = 80.0f;
		obsScan.rightToLeft = true;
		obsScan.resizeScanAndAssign(1, 0.0, true);
	}

	// Set options:
	// ----------------------------------------------
	gridMap.likelihoodOptions.loadFromConfigFile(cfgFile, "LikelihoodOptions");
	gridMap.likelihoodOptions.dumpToConsole();

	// Perform simulation:
	// ----------------------------------------------
	printf("Performing simulation (saving to out_lik.txt)...");

	FILE* f = os::fopen("out_lik.txt", "wt");
	ASSERT_(f);

	CSimplePointsMap pointsMap;
	pointsMap.clear();
	pointsMap.insertPoint(0, 0);

	tictac.Tic();

	float phi = (float)0.0_deg;

	auto nullPose = CPose3D(0, 0, 0, phi, 0, 0);

	for (float y = evalgrid_y_min; y < evalgrid_y_max; y += res)
	{
		for (float x = evalgrid_x_min; x < evalgrid_x_max; x += res)
		{
			nullPose.x(x);
			nullPose.y(y);
			fprintf(
				f, "%e ",
				gridMap.computeObservationLikelihood(obsScan, nullPose));
		}  // for y
		fprintf(f, "\n");
	}  // for x

	printf("Done!\n");

	printf("Time:%fms\n", 1000.0f * tictac.Tac());

	os::fclose(f);
}

int main()
{
	try
	{
		theMainThing();

		return 0;
	}
	catch (const std::exception& e)
	{
		std::cout << "MRPT exception:\n" << e.what() << std::endl;
		return -1;
	}
	catch (...)
	{
		printf("Runtime exception!!");
		return -1;
	}
}
