/* +------------------------------------------------------------------------+
   |                     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/CLoadableOptions.h>
#include <mrpt/math/TPoint3D.h>
#include <mrpt/obs/obs_frwds.h>
#include <mrpt/serialization/CSerializable.h>

namespace mrpt::maps
{
/** Parameters for the determination of matchings between point clouds, etc. \sa
 * CMetricMap::determineMatching2D, CMetricMap::determineMatching3D */
struct TMatchingParams
{
  /** Maximum linear distance between two points to be paired (meters) */
  float maxDistForCorrespondence{0.50f};
  /** Allowed "angular error" (in radians): this permits larger pairing
   * threshold distances to more distant points. */
  float maxAngularDistForCorrespondence{.0f};
  /** If set to true (default), only the closest correspondence will be
   * returned. If false all are returned. */
  bool onlyKeepTheClosest{true};
  /** Additional consistency filter: "onlyKeepTheClosest" allows one
   * correspondence for each "local map" point, but many of them may have as
   * corresponding pair the same "global point", which this flag avoids. */
  bool onlyUniqueRobust{false};
  /** (Default=1) Only consider 1 out of this number of points from the
   * "other" map. */
  size_t decimation_other_map_points{1};
  /** Index of the first point in the "other" map to start checking for
   * correspondences (Default=0) */
  size_t offset_other_map_points{0};
  /** The point used to calculate angular distances: e.g. the coordinates of
   * the sensor for a 2D laser scanner. */
  mrpt::math::TPoint3D angularDistPivotPoint{0, 0, 0};

  /** Ctor: default values */
  TMatchingParams() = default;
};

/** Additional results from the determination of matchings between point clouds,
 * etc., apart from the pairings themselves \sa CMetricMap::determineMatching2D,
 * CMetricMap::determineMatching3D */
struct TMatchingExtraResults
{
  /** The ratio [0,1] of points in otherMap with at least one correspondence.
   */
  float correspondencesRatio{0};
  /** The sum of all matched points squared distances.If undesired, set to
   * nullptr, as default. */
  float sumSqrDist{0};

  TMatchingExtraResults() = default;
};

/** Parameters for CMetricMap::compute3DMatchingRatio() */
struct TMatchingRatioParams
{
  /** (Default: 0.10f) The minimum distance between 2 non-probabilistic map
   * elements for counting them as a correspondence. */
  float maxDistForCorr{0.10f};
  /** (Default: 2.0f) The minimum Mahalanobis distance between 2 probabilistic
   * map elements for counting them as a correspondence. */
  float maxMahaDistForCorr{2.0f};

  TMatchingRatioParams() = default;
};

/** Common params to all maps derived from mrpt::maps::CMetricMap  */
class TMapGenericParams :
    public mrpt::config::CLoadableOptions,
    public mrpt::serialization::CSerializable
{
  DEFINE_SERIALIZABLE(TMapGenericParams, mrpt::maps)
 public:
  /** (Default=true) If false, calling CMetricMap::getAs3DObject() will have
   * no effects */
  bool enableSaveAs3DObject{true};
  /** (Default=true) Enable computing observation likelihoods with this map */
  bool enableObservationLikelihood{true};
  /** (Default=true) Enable inserting observations in this map  */
  bool enableObservationInsertion{true};

  void loadFromConfigFile(
      const mrpt::config::CConfigFileBase& source,
      const std::string& sectionNamePrefix) override;  // See base docs
  void saveToConfigFile(
      mrpt::config::CConfigFileBase& target, const std::string& section) const override;
};

}  // namespace mrpt::maps
