#ifndef FOCUSSTABILIZATIONDEVICE_HPP_INCLUDED
#define FOCUSSTABILIZATIONDEVICE_HPP_INCLUDED

#include <iostream>
#include <memory>
#include <optional>
#include <set>
#include <string>
#include <vector>
#include <NBO/NBO/AnnotationRef.h>
#include <NBO/NBO/Denomination_Type.h>
#include <NBO/NBO/FocusStabilizationID_Type.h>
#include <NBO/NBO/FocusStabilizationMechanism_Type.h>
#include <NBO/NBO/ManufacturerSpec_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 FocusStabilizationDevice.
*
* This element describes an optional focus stabilization device (also known as, Auto Focus) that may be used for bringing an object automatically into focus for this instrument. Such devices can be controlled either via an imaging software and/or by a hardware device that detects and adjusts the objective or sample positions.
*/
class NBO_EXPORT FocusStabilizationDevice : public ManufacturerSpec_Type {

public:
	
	FocusStabilizationDevice();
	~FocusStabilizationDevice();

	/*!
	* \brief Cast a NBOBaseClass to a FocusStabilizationDevice.
	*
	* \param base The base class to cast
	* \return The casted element, or nullptr if the cast fails
	*/
	static std::shared_ptr<FocusStabilizationDevice> 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 ID attribute.
	*
	* A Unique Identifier for this component.
	*
	* \param value The value to set
	* \param validate If true, validates constraints on value. Default is true.
	*/
	void setID(const Inscoper::NBO::FocusStabilizationID_TypePtr& value, bool validate = true);

	/*!
	* \brief Returns the value of the ID attribute.
	*
	* A Unique Identifier for this component.
	*
	* \return The value of the attribute
	*/
	FocusStabilizationID_TypePtr getID() const;

	/*!
	* \brief Resets the ID attribute to an unset state.
	*
	* A Unique Identifier for this component.
	*/
	void resetID();

	/*!
	* \brief Checks whether the optional ID attribute is present.
	*
	* A Unique Identifier for this component.
	*
	* \return true if the optional attribute has been set, false otherwise
	*/
	bool hasID() const;

	/*!
	* \brief Sets the value of the Name attribute.
	*
	* A User-defined Name for this component.
	*
	* \param value The value to set
	* \param validate If true, validates constraints on value. Default is true.
	*/
	void setName(const Inscoper::NBO::Denomination_TypePtr& value, bool validate = true);

	/*!
	* \brief Returns the value of the Name attribute.
	*
	* A User-defined Name for this component.
	*
	* \return The value of the attribute
	*/
	Denomination_TypePtr getName() const;

	/*!
	* \brief Resets the Name attribute to an unset state.
	*
	* A User-defined Name for this component.
	*/
	void resetName();

	/*!
	* \brief Checks whether the optional Name attribute is present.
	*
	* A User-defined Name for this component.
	*
	* \return true if the optional attribute has been set, false otherwise
	*/
	bool hasName() const;

	/*!
	* \brief Sets the value of the Mechanism attribute.
	*
	* This field refers to the mechanism employed by this Focus Stabilization Device. Software (also referred to as Image) based methods rely on the acquisition of a Z-series of images followed by image analysis to determine the best focal position based primarily on contrast comparisons. Hardware based methods rely on an external light beam (typically infrared) that is reflected off the coverslip and whose reflection is measured to determine and correct the focal offset of the sample.
	*
	* \param value The value to set
	* \param validate If true, validates constraints on value. Default is true.
	*/
	void setMechanism(const Inscoper::NBO::FocusStabilizationMechanism_TypePtr& value, bool validate = true);

	/*!
	* \brief Returns the value of the Mechanism attribute.
	*
	* This field refers to the mechanism employed by this Focus Stabilization Device. Software (also referred to as Image) based methods rely on the acquisition of a Z-series of images followed by image analysis to determine the best focal position based primarily on contrast comparisons. Hardware based methods rely on an external light beam (typically infrared) that is reflected off the coverslip and whose reflection is measured to determine and correct the focal offset of the sample.
	*
	* \return The value of the attribute
	*/
	FocusStabilizationMechanism_TypePtr getMechanism() const;

	/*!
	* \brief Resets the Mechanism attribute to an unset state.
	*
	* This field refers to the mechanism employed by this Focus Stabilization Device. Software (also referred to as Image) based methods rely on the acquisition of a Z-series of images followed by image analysis to determine the best focal position based primarily on contrast comparisons. Hardware based methods rely on an external light beam (typically infrared) that is reflected off the coverslip and whose reflection is measured to determine and correct the focal offset of the sample.
	*/
	void resetMechanism();

	/*!
	* \brief Checks whether the optional Mechanism attribute is present.
	*
	* This field refers to the mechanism employed by this Focus Stabilization Device. Software (also referred to as Image) based methods rely on the acquisition of a Z-series of images followed by image analysis to determine the best focal position based primarily on contrast comparisons. Hardware based methods rely on an external light beam (typically infrared) that is reflected off the coverslip and whose reflection is measured to determine and correct the focal offset of the sample.
	*
	* \return true if the optional attribute has been set, false otherwise
	*/
	bool hasMechanism() const;

	/*!
	* \brief Sets the value of the Algorithm attribute.
	*
	* In case this Focus Stabilization Device is Software Based, this field refers to the name of the Algorithm used to maintain Focus.
	*
	* \param value The value to set
	* \param validate If true, validates constraints on value. Default is true.
	*/
	void setAlgorithm(const std::string& value, bool validate = true);

	/*!
	* \brief Returns the value of the Algorithm attribute.
	*
	* In case this Focus Stabilization Device is Software Based, this field refers to the name of the Algorithm used to maintain Focus.
	*
	* \return The value of the attribute
	*/
	std::string getAlgorithm() const;

	/*!
	* \brief Resets the Algorithm attribute to an unset state.
	*
	* In case this Focus Stabilization Device is Software Based, this field refers to the name of the Algorithm used to maintain Focus.
	*/
	void resetAlgorithm();

	/*!
	* \brief Checks whether the Algorithm attribute is present.
	*
	* In case this Focus Stabilization Device is Software Based, this field refers to the name of the Algorithm used to maintain Focus.
	*
	* \return true if the attribute has been set, false otherwise
	*/
	bool hasAlgorithm() const;

	/*!
	* \brief Returns the allowed values for this attribut.
	*
	* In case this Focus Stabilization Device is Software Based, this field refers to the name of the Algorithm used to maintain Focus.
	*
	* \return The list of allowed values
	*/
	static const std::set<std::string>& getAlgorithmAllowedValues();

	/*!
	* \brief Sets the value of the TwoStep attribute.
	*
	* This field records whether this Focus Stabilization Device utilizes a 2-step progressive procedure (True) or not (False).
	*
	* \param value The value to set
	* \param validate If true, validates constraints on value. Default is true.
	*/
	void setTwoStep(const bool& value, bool validate = true);

	/*!
	* \brief Returns the value of the TwoStep attribute.
	*
	* This field records whether this Focus Stabilization Device utilizes a 2-step progressive procedure (True) or not (False).
	*
	* \return The value of the attribute
	*/
	bool getTwoStep() const;

	/*!
	* \brief Resets the TwoStep attribute to an unset state.
	*
	* This field records whether this Focus Stabilization Device utilizes a 2-step progressive procedure (True) or not (False).
	*/
	void resetTwoStep();

	/*!
	* \brief Checks whether the TwoStep attribute is present.
	*
	* This field records whether this Focus Stabilization Device utilizes a 2-step progressive procedure (True) or not (False).
	*
	* \return true if the attribute has been set, false otherwise
	*/
	bool hasTwoStep() const;

	/*!
	* \brief Sets the value of the Wavelength attribute.
	*
	* This field refers to the Wavelength of the beam that is relevant for this Focus Stabilization Device. For example this might represent the Wavelength of the beam that is reflected against the Coverglass to obtain a measurement of the focal offset of the sample at a given time during Acquisition.
	*
	* \param value The value to set
	* \param validate If true, validates constraints on value. Default is true.
	*/
	void setWavelength(const float& value, bool validate = true);

	/*!
	* \brief Returns the value of the Wavelength attribute.
	*
	* This field refers to the Wavelength of the beam that is relevant for this Focus Stabilization Device. For example this might represent the Wavelength of the beam that is reflected against the Coverglass to obtain a measurement of the focal offset of the sample at a given time during Acquisition.
	*
	* \return The value of the attribute
	*/
	float getWavelength() const;

	/*!
	* \brief Resets the Wavelength attribute to an unset state.
	*
	* This field refers to the Wavelength of the beam that is relevant for this Focus Stabilization Device. For example this might represent the Wavelength of the beam that is reflected against the Coverglass to obtain a measurement of the focal offset of the sample at a given time during Acquisition.
	*/
	void resetWavelength();

	/*!
	* \brief Checks whether the Wavelength attribute is present.
	*
	* This field refers to the Wavelength of the beam that is relevant for this Focus Stabilization Device. For example this might represent the Wavelength of the beam that is reflected against the Coverglass to obtain a measurement of the focal offset of the sample at a given time during Acquisition.
	*
	* \return true if the attribute has been set, false otherwise
	*/
	bool hasWavelength() const;

	/*!
	* \brief Sets the value of the AnnotationRef element.
	*
	* This is a simple multi-line comment or annotation describing this component.
	*
	* \param value The value to set
	* \param validate If true, validates constraints on value. Default is true.
	*/
	void setAnnotationRef(const Inscoper::NBO::AnnotationRefPtr& value, bool validate = true);

	/*!
	* \brief Returns the value of the AnnotationRef element.
	*
	* This is a simple multi-line comment or annotation describing this component.
	*
	* \return The value of the element
	*/
	Inscoper::NBO::AnnotationRefPtr getAnnotationRef() const;

	/*!
	* \brief Resets the AnnotationRef element to an unset state.
	*
	* This is a simple multi-line comment or annotation describing this component.
	*/
	void resetAnnotationRef();

	/*!
	* \brief Checks whether the optional AnnotationRef element is present.
	*
	* This is a simple multi-line comment or annotation describing this component.
	*
	* \return true if the optional attribute has been set, false otherwise
	*/
	bool hasAnnotationRef() const;


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

	FocusStabilizationID_TypePtr ID = nullptr; // Required attribute
	Denomination_TypePtr Name = nullptr; // Optional attribute
	FocusStabilizationMechanism_TypePtr Mechanism = nullptr; // Required attribute
    std::optional<std::string> Algorithm; // Optional attribute
    static const std::set<std::string> AlgorithmAllowedValues;
    std::optional<bool> TwoStep; // Optional attribute
    std::optional<float> Wavelength; // Optional attribute
    Inscoper::NBO::AnnotationRefPtr AnnotationRef = nullptr;
};

/*! Shared pointer for FocusStabilizationDevice*/
typedef std::shared_ptr<FocusStabilizationDevice> FocusStabilizationDevicePtr;

} // namespace Inscoper::NBO

#endif // FOCUSSTABILIZATIONDEVICE_HPP_INCLUDED