#ifndef NEUTRALDENSITYFILTER_HPP_INCLUDED
#define NEUTRALDENSITYFILTER_HPP_INCLUDED

#include <iostream>
#include <memory>
#include <optional>
#include <set>
#include <string>
#include <vector>
#include <NBO/NBO/Filter_Type.h>
#include <NBO/NBO/NDTYPE_Type.h>
#include <NBO/NBO/ENBOType.h>
#include <NBO/NBOGlobal.h>
#include <NBO/Shared/Base/NBOBaseClass.h>


namespace Inscoper::NBO {

/*!
* \brief Represents the XML element NeutralDensityFilter.
*
* An optical Filter is a device designed to selectively control the Wavelengths, color temperature, vibration direction, and/or intensity of the radiation which it transmits or reflects. This element refers to an optical Filter whose purpose is to attenuate the intensity of the transmitted Light independent of the Wavelength.
*/
class NBO_EXPORT NeutralDensityFilter : public Filter_Type {

public:
	
	NeutralDensityFilter();
	~NeutralDensityFilter();

	/*!
	* \brief Cast a NBOBaseClass to a NeutralDensityFilter.
	*
	* \param base The base class to cast
	* \return The casted element, or nullptr if the cast fails
	*/
	static std::shared_ptr<NeutralDensityFilter> fromBase(NBOBaseClassPtr base);

	/*!
	* \brief Returns the class type name.
	*
	* \return The class type name
	*/
	std::string getTypeName() const override;

	/*!
	* \brief Returns the XML element name corresponding to this class.
	*
	* \return The XML element name
	*/
	std::string getXMLName() const override;

	/*!
	* \brief Returns the NBO Type corresponding to this class.
	*
	* \return The NBO Type value
	*/
	ENBOType getNBOType() const override;

	/*!
	* \brief Returns a list of all classes derived from this class.
	*
	* \return The list of derived classes
	*/
	std::vector<NBOBaseClassPtr> getChildren() const override;

	/*!
	* \brief Returns a list of all child elements contained in this class.
	*
	* \return The list of child classes
	*/
	std::vector<NBOBaseClassPtr> getSubElements() const override;

	/*!
	* \brief Populates this object from a JSON file.
	*
	* \param path The path to the JSON file
	* \param validate If true, validates constraints on value. Default is true.
	*/
	void fromJsonFile(const std::string& path, bool validate = true);

	/*!
	* \brief Populates this object from a JSON string.
	*
	* \param json_string The JSON content as a string
	* \param validate If true, validates constraints on value. Default is true.
	*/
	void fromJsonString(const std::string& json_string, bool validate = true);

	/*!
	* \brief Populates this object from a XML file.
	*
	* \param path The path to the XML file
	* \param validate If true, validates constraints on value. Default is true.
	*/
	void fromXmlFile(const std::string& path, bool validate = true);

	/*!
	* \brief Populates this object from a XML string.
	*
	* \param xml_string The XML content as a string
	* \param validate If true, validates constraints on value. Default is true.
	*/
	void fromXmlString(const std::string& xml_string, bool validate = true);

	/*!
	* \brief Serializes this object to an XML file.
	*
	* \param filename The path to the output XML file
	* \param validate If true, validates constraints on value. Default is true.
	*/
	void toXmlFile(const std::string& filename, bool validate = true) const;

	/*!
	* \brief Serializes this object to an XML string.
	*
	* \param validate If true, validates constraints on value. Default is true.
	* \return A string containing the XML representation of this object
	*/
	std::string toXmlString(bool validate = true) const;

	/*!
	* \brief Sets the value of the NDType attribute.
	*
	* This field refers to the general category of this Neutral Density Filter. Neutral Density Filters come in two general types. Those made of darkened glass that absorb light and those coated with a metal film that reflect light.
	*
	* \param value The value to set
	* \param validate If true, validates constraints on value. Default is true.
	*/
	void setNDType(const Inscoper::NBO::NDTYPE_TypePtr& value, bool validate = true);

	/*!
	* \brief Returns the value of the NDType attribute.
	*
	* This field refers to the general category of this Neutral Density Filter. Neutral Density Filters come in two general types. Those made of darkened glass that absorb light and those coated with a metal film that reflect light.
	*
	* \return The value of the attribute
	*/
	NDTYPE_TypePtr getNDType() const;

	/*!
	* \brief Resets the NDType attribute to an unset state.
	*
	* This field refers to the general category of this Neutral Density Filter. Neutral Density Filters come in two general types. Those made of darkened glass that absorb light and those coated with a metal film that reflect light.
	*/
	void resetNDType();

	/*!
	* \brief Checks whether the optional NDType attribute is present.
	*
	* This field refers to the general category of this Neutral Density Filter. Neutral Density Filters come in two general types. Those made of darkened glass that absorb light and those coated with a metal film that reflect light.
	*
	* \return true if the optional attribute has been set, false otherwise
	*/
	bool hasNDType() const;

	/*!
	* \brief Sets the value of the OpticalDensity attribute.
	*
	* This field measures the absolute value of the logarithm of base 10 of the power transmission factor. For example, an optical density of 3 means an attenuation of optical powers by the factor 10^3 = 1000.
	*
	* \param value The value to set
	* \param validate If true, validates constraints on value. Default is true.
	*/
	void setOpticalDensity(const float& value, bool validate = true);

	/*!
	* \brief Returns the value of the OpticalDensity attribute.
	*
	* This field measures the absolute value of the logarithm of base 10 of the power transmission factor. For example, an optical density of 3 means an attenuation of optical powers by the factor 10^3 = 1000.
	*
	* \return The value of the attribute
	*/
	float getOpticalDensity() const;

	/*!
	* \brief Resets the OpticalDensity attribute to an unset state.
	*
	* This field measures the absolute value of the logarithm of base 10 of the power transmission factor. For example, an optical density of 3 means an attenuation of optical powers by the factor 10^3 = 1000.
	*/
	void resetOpticalDensity();

	/*!
	* \brief Checks whether the OpticalDensity attribute is present.
	*
	* This field measures the absolute value of the logarithm of base 10 of the power transmission factor. For example, an optical density of 3 means an attenuation of optical powers by the factor 10^3 = 1000.
	*
	* \return true if the attribute has been set, false otherwise
	*/
	bool hasOpticalDensity() const;


private:
	class Impl;
	std::unique_ptr<Impl> pImpl;

	NDTYPE_TypePtr NDType = nullptr; // Required attribute
    std::optional<float> OpticalDensity; // Required attribute
};

/*! Shared pointer for NeutralDensityFilter*/
typedef std::shared_ptr<NeutralDensityFilter> NeutralDensityFilterPtr;

} // namespace Inscoper::NBO

#endif // NEUTRALDENSITYFILTER_HPP_INCLUDED