#ifndef OPTICSHOLDER_TYPE_HPP_INCLUDED
#define OPTICSHOLDER_TYPE_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/LensID_Type.h>
#include <NBO/NBO/ManufacturerSpec_Type.h>
#include <NBO/NBO/UnitsTime_Type.h>
#include <NBO/NBO/ENBOType.h>
#include <NBO/NBOGlobal.h>
#include <NBO/Shared/Base/NBOBaseClass.h>


namespace Inscoper::NBO {

/*!
* \brief Represents the XML complex type OpticsHolder.
*
* This element represents a Holder for Filters, Dichroic and other Optical Element that is associated with this Instrument. These Holders come in different arrangements such as Cubes, Sliders, Turrets, and Wheels. While some of these Holders, such as Filter Cubes, might be pre-assebled by the Manufacturer and pruchased as a whole, in the majority of cases they are assembled on site depending on the needs of the user.
*/
class NBO_EXPORT OpticsHolder_Type : public ManufacturerSpec_Type {

public:
	
	OpticsHolder_Type();
	~OpticsHolder_Type();

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

	/*!
	* \brief Returns the class type name.
	*
	* \return The class type name
	*/
	virtual 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::LensID_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
	*/
	LensID_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 Motorized attribute.
	*
	* This field describes whether this device is Motor (True) or Manually (False) operated.
	*
	* \param value The value to set
	* \param validate If true, validates constraints on value. Default is true.
	*/
	void setMotorized(const bool& value, bool validate = true);

	/*!
	* \brief Returns the value of the Motorized attribute.
	*
	* This field describes whether this device is Motor (True) or Manually (False) operated.
	*
	* \return The value of the attribute
	*/
	bool getMotorized() const;

	/*!
	* \brief Resets the Motorized attribute to an unset state.
	*
	* This field describes whether this device is Motor (True) or Manually (False) operated.
	*/
	void resetMotorized();

	/*!
	* \brief Checks whether the Motorized attribute is present.
	*
	* This field describes whether this device is Motor (True) or Manually (False) operated.
	*
	* \return true if the attribute has been set, false otherwise
	*/
	bool hasMotorized() const;

	/*!
	* \brief Sets the value of the ResponseTime attribute.
	*
	* This field records the time it takes for this Shutter to open and close, according to the Manufacturer.
	*
	* \param value The value to set
	* \param validate If true, validates constraints on value. Default is true.
	*/
	void setResponseTime(const float& value, bool validate = true);

	/*!
	* \brief Returns the value of the ResponseTime attribute.
	*
	* This field records the time it takes for this Shutter to open and close, according to the Manufacturer.
	*
	* \return The value of the attribute
	*/
	float getResponseTime() const;

	/*!
	* \brief Resets the ResponseTime attribute to an unset state.
	*
	* This field records the time it takes for this Shutter to open and close, according to the Manufacturer.
	*/
	void resetResponseTime();

	/*!
	* \brief Checks whether the ResponseTime attribute is present.
	*
	* This field records the time it takes for this Shutter to open and close, according to the Manufacturer.
	*
	* \return true if the attribute has been set, false otherwise
	*/
	bool hasResponseTime() const;

	/*!
	* \brief Sets the value of the ResponseTimeUnit attribute.
	*
	* 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 setResponseTimeUnit(const Inscoper::NBO::UnitsTime_TypePtr& value, bool validate = true);

	/*!
	* \brief Returns the value of the ResponseTimeUnit attribute.
	*
	* No description available in the XSD standard.
	*
	* \return The value of the attribute
	*/
	UnitsTime_TypePtr getResponseTimeUnit() const;

	/*!
	* \brief Resets the ResponseTimeUnit attribute to an unset state.
	*
	* No description available in the XSD standard.
	*/
	void resetResponseTimeUnit();

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

	/*!
	* \brief Sets the value of the NrOfSlots attribute.
	*
	* This field records how many Slots this Optics Holder has.
	*
	* \param value The value to set
	* \param validate If true, validates constraints on value. Default is true.
	*/
	void setNrOfSlots(const long long& value, bool validate = true);

	/*!
	* \brief Returns the value of the NrOfSlots attribute.
	*
	* This field records how many Slots this Optics Holder has.
	*
	* \return The value of the attribute
	*/
	long long getNrOfSlots() const;

	/*!
	* \brief Resets the NrOfSlots attribute to an unset state.
	*
	* This field records how many Slots this Optics Holder has.
	*/
	void resetNrOfSlots();

	/*!
	* \brief Checks whether the NrOfSlots attribute is present.
	*
	* This field records how many Slots this Optics Holder has.
	*
	* \return true if the attribute has been set, false otherwise
	*/
	bool hasNrOfSlots() const;

	/*!
	* \brief Sets the value of the AnnotationRef 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 setAnnotationRef(const Inscoper::NBO::AnnotationRefPtr& value, bool validate = true);

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

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

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


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

	LensID_TypePtr ID = nullptr; // Required attribute
	Denomination_TypePtr Name = nullptr; // Optional attribute
    std::optional<bool> Motorized; // Optional attribute
    std::optional<float> ResponseTime; // Optional attribute
	UnitsTime_TypePtr ResponseTimeUnit = nullptr; // Optional attribute
    std::optional<long long> NrOfSlots; // Optional attribute
    Inscoper::NBO::AnnotationRefPtr AnnotationRef = nullptr;
};

/*! Shared pointer for OpticsHolder_Type*/
typedef std::shared_ptr<OpticsHolder_Type> OpticsHolder_TypePtr;

} // namespace Inscoper::NBO

#endif // OPTICSHOLDER_TYPE_HPP_INCLUDED