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

#pragma once

#include <mrpt/config/CConfigFileBase.h>
#include <mrpt/img/color_maps.h>
#include <mrpt/obs/CObservation2DRangeScan.h>
#include <mrpt/obs/CObservation3DRangeScan.h>
#include <mrpt/obs/CObservationPointCloud.h>
#include <mrpt/obs/CObservationRotatingScan.h>
#include <mrpt/obs/CObservationVelodyneScan.h>
#include <mrpt/opengl/CPointCloudColoured.h>
#include <mrpt/opengl/CSetOfObjects.h>

namespace mrpt::obs
{
/** @name customizable_obs_viz_grp Customizable obstacle to 3D visualization API
 *  @{ */

/** Here we can customize the way observations will be rendered as 3D objects
 *  in obs_to_viz(), obs3Dscan_to_viz(), etc.
 *  \sa obs_to_viz(), obs3Dscan_to_viz()
 */
struct VisualizationParameters
{
  VisualizationParameters() = default;
  ~VisualizationParameters() = default;

  bool showAxis = true;
  double axisTickFrequency = 1.0;
  double axisLimits = 20.0;
  double axisTickTextSize = 0.075;
  bool colorFromRGBimage = true;
  int colorizeByAxis = 0;  // 0:x,1:y,2:z, anything else = none.
  bool invertColorMapping = false;
  mrpt::img::TColormap colorMap = mrpt::img::cmJET;
  double pointSize = 4.0;
  bool drawSensorPose = true;
  double sensorPoseScale = 0.3;
  bool onlyPointsWithColor = false;

  bool showSurfaceIn2Dscans = true;
  bool showPointsIn2Dscans = true;
  mrpt::img::TColor surface2DscansColor = {0x00, 0x00, 0xff, 0x80};  // RGBA
  mrpt::img::TColor points2DscansColor = {0xff, 0x00, 0xff, 0xff};   // RGBA

  void save_to_ini_file(
      mrpt::config::CConfigFileBase& cfg,
      const std::string& section = "ParametersView3DPoints") const;

  void load_from_ini_file(
      const mrpt::config::CConfigFileBase& cfg,
      const std::string& section = "ParametersView3DPoints");
};

/** Clears `out` and creates a visualization of the given observation,
 *  dispatching the call according to the actual observation class.
 *  \return true if type has known visualizer, false if it does not (then, `out`
 *          will be empty)
 *
 *  \note This and the accompanying functions are defined in namespace
 *        mrpt::obs, but you must link against mrpt::maps too to have their
 *        definitions.
 */
bool obs_to_viz(
    const mrpt::obs::CObservation::Ptr& obs,
    const VisualizationParameters& p,
    mrpt::opengl::CSetOfObjects& out);

/** Clears `out` and creates a visualization of the given sensory-frame,
 *  dispatching the call according to the actual observation classes inside the
 * SF.
 *
 *  \return true if type has known visualizer, false if it does not (then, `out`
 *          will be empty)
 *
 *  \note This and the accompanying functions are defined in namespace
 *        mrpt::obs, but you must link against mrpt::maps too to have their
 *        definitions.
 */
bool obs_to_viz(
    const mrpt::obs::CSensoryFrame& sf,
    const VisualizationParameters& p,
    mrpt::opengl::CSetOfObjects& out);

/// Clears `out` and creates a visualization of the given observation.
void obs3Dscan_to_viz(
    const mrpt::obs::CObservation3DRangeScan::Ptr& obs,
    const VisualizationParameters& p,
    mrpt::opengl::CSetOfObjects& out);

/// Clears `out` and creates a visualization of the given observation.
void obsVelodyne_to_viz(
    const mrpt::obs::CObservationVelodyneScan::Ptr& obs,
    const VisualizationParameters& p,
    mrpt::opengl::CSetOfObjects& out);

/// Clears `out` and creates a visualization of the given observation.
void obsPointCloud_to_viz(
    const mrpt::obs::CObservationPointCloud::Ptr& obs,
    const VisualizationParameters& p,
    mrpt::opengl::CSetOfObjects& out);

void obsRotatingScan_to_viz(
    const mrpt::obs::CObservationRotatingScan::Ptr& obs,
    const VisualizationParameters& p,
    mrpt::opengl::CSetOfObjects& out);

/// Clears `out` and creates a visualization of the given observation.
void obs2Dscan_to_viz(
    const mrpt::obs::CObservation2DRangeScan::Ptr& obs,
    const VisualizationParameters& p,
    mrpt::opengl::CSetOfObjects& out);

/// Recolorize a pointcloud according to the given parameters
void recolorize3Dpc(
    const mrpt::opengl::CPointCloudColoured::Ptr& pnts, const VisualizationParameters& p);

/** @} */

}  // namespace mrpt::obs
