/* +------------------------------------------------------------------------+
   |                     Mobile Robot Programming Toolkit (MRPT)            |
   |                          https://www.mrpt.org/                         |
   |                                                                        |
   | Copyright (c) 2005-2022, 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/containers/deepcopy_ptr.h>  // copy_ptr<>

namespace mrpt::bayes
{
/** use for CProbabilityParticle
 * \ingroup mrpt_bayes_grp
 */
enum class particle_storage_mode
{
	VALUE,
	POINTER
};

/** A template class for holding a the data and the weight of a particle.
 * Particles comprise two parts: a "data payload field", and a logarithmic
 * importance sampling weight.
 *
 * \tparam T The type of the payload. Must be default constructable.
 * \tparam STORAGE If `POINTER`, a (wrapper to a) pointer is used to store
 * the payload; if `VALUE`, the payload is stored directly as a value.
 *
 * \sa CParticleFilterData
 * \ingroup mrpt_bayes_grp
 */
template <class T, particle_storage_mode STORAGE>
struct CProbabilityParticle;

struct CProbabilityParticleBase
{
	CProbabilityParticleBase(double logw = 0) : log_w(logw) {}
	/** The (logarithmic) weight value for this particle. */
	double log_w{.0};
};

template <class T>
struct CProbabilityParticle<T, particle_storage_mode::POINTER>
	: public CProbabilityParticleBase
{
	/** The data associated with this particle. The use of copy_ptr<> allows
	 * relying on compiler-generated copy ctor, etc. */
	mrpt::containers::copy_ptr<T> d{};
};

template <class T>
struct CProbabilityParticle<T, particle_storage_mode::VALUE>
	: public CProbabilityParticleBase
{
	CProbabilityParticle() = default;
	CProbabilityParticle(const T& data, const double logw)
		: CProbabilityParticleBase(logw), d(data)
	{
	}
	/** The data associated with this particle */
	T d{};
};

}  // namespace mrpt::bayes
