#ifndef CALIBRATIONMAP_HPP_INCLUDED
#define CALIBRATIONMAP_HPP_INCLUDED

#include <iostream>
#include <memory>
#include <optional>
#include <set>
#include <string>
#include <vector>
#include <NBO/NBO/Description.h>
#include <NBO/NBO/MatrixTypeEnum_Type.h>
#include <NBO/NBO/rowType_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 CalibrationMap.
*
* This element describes a 2D matrix containing values computed as a resulut of the calibration procedure. This matrix is the same size of the experimental Image this calibration refers to.
*/
class NBO_EXPORT CalibrationMap : public NBOBaseClass {

public:
	
	CalibrationMap();
	~CalibrationMap();

	/*!
	* \brief Cast a NBOBaseClass to a CalibrationMap.
	*
	* \param base The base class to cast
	* \return The casted element, or nullptr if the cast fails
	*/
	static std::shared_ptr<CalibrationMap> 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 MetricType attribute.
	*
	* This field captures the type of metric that was computed as part of the calibratin procedure in this instance.
	*
	* \param value The value to set
	* \param validate If true, validates constraints on value. Default is true.
	*/
	void setMetricType(const Inscoper::NBO::MatrixTypeEnum_TypePtr& value, bool validate = true);

	/*!
	* \brief Returns the value of the MetricType attribute.
	*
	* This field captures the type of metric that was computed as part of the calibratin procedure in this instance.
	*
	* \return The value of the attribute
	*/
	MatrixTypeEnum_TypePtr getMetricType() const;

	/*!
	* \brief Resets the MetricType attribute to an unset state.
	*
	* This field captures the type of metric that was computed as part of the calibratin procedure in this instance.
	*/
	void resetMetricType();

	/*!
	* \brief Checks whether the optional MetricType attribute is present.
	*
	* This field captures the type of metric that was computed as part of the calibratin procedure in this instance.
	*
	* \return true if the optional attribute has been set, false otherwise
	*/
	bool hasMetricType() const;

	/*!
	* \brief Sets the value of the IlluminationIntensity attribute.
	*
	* This attribute only applies to matrices of type Variance and Mean. It represents the illumination intensity that was used to acquire the images used to contruct this matrix. The value can range from 0 (i.e. dark image) to any intenisty value experssed either as percentage or as absolute power.
	*
	* \param value The value to set
	* \param validate If true, validates constraints on value. Default is true.
	*/
	void setIlluminationIntensity(const float& value, bool validate = true);

	/*!
	* \brief Returns the value of the IlluminationIntensity attribute.
	*
	* This attribute only applies to matrices of type Variance and Mean. It represents the illumination intensity that was used to acquire the images used to contruct this matrix. The value can range from 0 (i.e. dark image) to any intenisty value experssed either as percentage or as absolute power.
	*
	* \return The value of the attribute
	*/
	float getIlluminationIntensity() const;

	/*!
	* \brief Resets the IlluminationIntensity attribute to an unset state.
	*
	* This attribute only applies to matrices of type Variance and Mean. It represents the illumination intensity that was used to acquire the images used to contruct this matrix. The value can range from 0 (i.e. dark image) to any intenisty value experssed either as percentage or as absolute power.
	*/
	void resetIlluminationIntensity();

	/*!
	* \brief Checks whether the IlluminationIntensity attribute is present.
	*
	* This attribute only applies to matrices of type Variance and Mean. It represents the illumination intensity that was used to acquire the images used to contruct this matrix. The value can range from 0 (i.e. dark image) to any intenisty value experssed either as percentage or as absolute power.
	*
	* \return true if the attribute has been set, false otherwise
	*/
	bool hasIlluminationIntensity() const;

	/*!
	* \brief Sets the value of the NrOfImages attribute.
	*
	* This field represents the number of images that were employed to generate this calibration matrix.
	*
	* \param value The value to set
	* \param validate If true, validates constraints on value. Default is true.
	*/
	void setNrOfImages(const int& value, bool validate = true);

	/*!
	* \brief Returns the value of the NrOfImages attribute.
	*
	* This field represents the number of images that were employed to generate this calibration matrix.
	*
	* \return The value of the attribute
	*/
	int getNrOfImages() const;

	/*!
	* \brief Resets the NrOfImages attribute to an unset state.
	*
	* This field represents the number of images that were employed to generate this calibration matrix.
	*/
	void resetNrOfImages();

	/*!
	* \brief Checks whether the NrOfImages attribute is present.
	*
	* This field represents the number of images that were employed to generate this calibration matrix.
	*
	* \return true if the attribute has been set, false otherwise
	*/
	bool hasNrOfImages() const;

	/*!
	* \brief Sets the list of Row elements.
	*
	* No description available in the XSD standard.
	*
	* \param value The new list of Row elements
	* \param validate If true, validates constraints on value. Default is true.
	*/
	void setRow_List(const std::vector<Inscoper::NBO::rowType_TypePtr>& value, bool validate = true);

	/*!
	* \brief Returns the list of Row elements.
	*
	* No description available in the XSD standard.
	*
	* \return The list of Row elements
	*/
	std::vector<Inscoper::NBO::rowType_TypePtr> getRow_List() const;

	/*!
	* \brief Adds a new Row element to this object.
	*
	* No description available in the XSD standard.
	*
	* \param value The element to add
	* \param validate If true, validates constraints on value. Default is true.
	*/
	void addToRow_List(const Inscoper::NBO::rowType_TypePtr& value, bool validate = true);

	/*!
	* \brief Clear the list of Row.
	*
	* No description available in the XSD standard.
	*/
	void clearRow_List();

	/*!
	* \brief Sets the value of the Description element.
	*
	* No description available in the XSD standard.
	*
	* \param value The value to set
	* \param validate If true, validates constraints on value. Default is true.
	*/
	void setDescription(const Inscoper::NBO::DescriptionPtr& value, bool validate = true);

	/*!
	* \brief Returns the value of the Description element.
	*
	* No description available in the XSD standard.
	*
	* \return The value of the element
	*/
	Inscoper::NBO::DescriptionPtr getDescription() const;

	/*!
	* \brief Resets the Description element to an unset state.
	*
	* No description available in the XSD standard.
	*/
	void resetDescription();

	/*!
	* \brief Checks whether the optional Description element is present.
	*
	* No description available in the XSD standard.
	*
	* \return true if the optional attribute has been set, false otherwise
	*/
	bool hasDescription() const;


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

	MatrixTypeEnum_TypePtr MetricType = nullptr; // Required attribute
    std::optional<float> IlluminationIntensity; // Required attribute
    std::optional<int> NrOfImages; // Required attribute
    std::vector<Inscoper::NBO::rowType_TypePtr> Row_List;
    Inscoper::NBO::DescriptionPtr Description = nullptr;
};

/*! Shared pointer for CalibrationMap*/
typedef std::shared_ptr<CalibrationMap> CalibrationMapPtr;

} // namespace Inscoper::NBO

#endif // CALIBRATIONMAP_HPP_INCLUDED