#ifndef SHUTTER_HPP_INCLUDED
#define SHUTTER_HPP_INCLUDED

#include <iostream>
#include <memory>
#include <optional>
#include <set>
#include <string>
#include <vector>
#include <NBO/NBO/OpticalAperture_Type.h>
#include <NBO/NBO/ShutterFunction_Type.h>
#include <NBO/NBO/UnitsFrequency_Type.h>
#include <NBO/NBO/UnitsLength_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 element Shutter.
*
* This element describes a Shutter available for this Instrument. Shutters are devices that open and close, and they may be mechanically or electro-mechanically controlled. Shutters are typically used to control the Light that raches the sample (i.e., to limit phototoxicity and photobleaching especially in case of live specimens), or the Detecrtor at any one time. They can also be used for Excitation or Emission Wavelength selection.
*/
class NBO_EXPORT Shutter : public OpticalAperture_Type {

public:
	
	Shutter();
	~Shutter();

	/*!
	* \brief Cast a NBOBaseClass to a Shutter.
	*
	* \param base The base class to cast
	* \return The casted element, or nullptr if the cast fails
	*/
	static std::shared_ptr<Shutter> 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 ResponseTime attribute.
	*
	* This field (also known as Speed) records the time it takes for this Shutter to completely 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 (also known as Speed) records the time it takes for this Shutter to completely 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 (also known as Speed) records the time it takes for this Shutter to completely open and close, according to the Manufacturer.
	*/
	void resetResponseTime();

	/*!
	* \brief Checks whether the ResponseTime attribute is present.
	*
	* This field (also known as Speed) records the time it takes for this Shutter to completely 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 Function attribute.
	*
	* This field records whether this Shutter is used for the control of illumination (especially relevant for live imaging), the selection of Excitation or Emission wavelenghts or the control of the Light that reaches the Detector.
	*
	* \param value The value to set
	* \param validate If true, validates constraints on value. Default is true.
	*/
	void setFunction(const Inscoper::NBO::ShutterFunction_TypePtr& value, bool validate = true);

	/*!
	* \brief Returns the value of the Function attribute.
	*
	* This field records whether this Shutter is used for the control of illumination (especially relevant for live imaging), the selection of Excitation or Emission wavelenghts or the control of the Light that reaches the Detector.
	*
	* \return The value of the attribute
	*/
	ShutterFunction_TypePtr getFunction() const;

	/*!
	* \brief Resets the Function attribute to an unset state.
	*
	* This field records whether this Shutter is used for the control of illumination (especially relevant for live imaging), the selection of Excitation or Emission wavelenghts or the control of the Light that reaches the Detector.
	*/
	void resetFunction();

	/*!
	* \brief Checks whether the optional Function attribute is present.
	*
	* This field records whether this Shutter is used for the control of illumination (especially relevant for live imaging), the selection of Excitation or Emission wavelenghts or the control of the Light that reaches the Detector.
	*
	* \return true if the optional attribute has been set, false otherwise
	*/
	bool hasFunction() const;

	/*!
	* \brief Sets the value of the OperatingFrequency attribute.
	*
	* This field records the Frequency of Operation of this Shutter, according to the Manufactuers.
	*
	* \param value The value to set
	* \param validate If true, validates constraints on value. Default is true.
	*/
	void setOperatingFrequency(const float& value, bool validate = true);

	/*!
	* \brief Returns the value of the OperatingFrequency attribute.
	*
	* This field records the Frequency of Operation of this Shutter, according to the Manufactuers.
	*
	* \return The value of the attribute
	*/
	float getOperatingFrequency() const;

	/*!
	* \brief Resets the OperatingFrequency attribute to an unset state.
	*
	* This field records the Frequency of Operation of this Shutter, according to the Manufactuers.
	*/
	void resetOperatingFrequency();

	/*!
	* \brief Checks whether the OperatingFrequency attribute is present.
	*
	* This field records the Frequency of Operation of this Shutter, according to the Manufactuers.
	*
	* \return true if the attribute has been set, false otherwise
	*/
	bool hasOperatingFrequency() const;

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

	/*!
	* \brief Returns the value of the OperatingFrequencyUnit attribute.
	*
	* No description available in the XSD standard.
	*
	* \return The value of the attribute
	*/
	UnitsFrequency_TypePtr getOperatingFrequencyUnit() const;

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

	/*!
	* \brief Checks whether the optional OperatingFrequencyUnit attribute is present.
	*
	* No description available in the XSD standard.
	*
	* \return true if the optional attribute has been set, false otherwise
	*/
	bool hasOperatingFrequencyUnit() 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 MaxApertureDiameter attribute.
	*
	* This field records the Maximum physical Diameter of the Aperture of this Shutter.
	*
	* \param value The value to set
	* \param validate If true, validates constraints on value. Default is true.
	*/
	void setMaxApertureDiameter(const float& value, bool validate = true);

	/*!
	* \brief Returns the value of the MaxApertureDiameter attribute.
	*
	* This field records the Maximum physical Diameter of the Aperture of this Shutter.
	*
	* \return The value of the attribute
	*/
	float getMaxApertureDiameter() const;

	/*!
	* \brief Resets the MaxApertureDiameter attribute to an unset state.
	*
	* This field records the Maximum physical Diameter of the Aperture of this Shutter.
	*/
	void resetMaxApertureDiameter();

	/*!
	* \brief Checks whether the MaxApertureDiameter attribute is present.
	*
	* This field records the Maximum physical Diameter of the Aperture of this Shutter.
	*
	* \return true if the attribute has been set, false otherwise
	*/
	bool hasMaxApertureDiameter() const;

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

	/*!
	* \brief Returns the value of the MaxApertureDiameterUnit attribute.
	*
	* No description available in the XSD standard.
	*
	* \return The value of the attribute
	*/
	UnitsLength_TypePtr getMaxApertureDiameterUnit() const;

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

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

	/*!
	* \brief Sets the value of the Multimode attribute.
	*
	* This field records whether (True) multiple operation modes are available for this Shutter or not (False). Typical operation modes are are: Fast, Soft and Neutral Density. The Fast mode provides the quickest open and close action sequence for which the shutter is capable. The Soft mode gradually opens and closes the shutter to reduce vibration. Control of light intensity without affecting wavelength is accommodated by a Neutral Density shutter mode (for more details see https://www.microscopyu.com/applications/live-cell-imaging/the-automatic-microscope).
	*
	* \param value The value to set
	* \param validate If true, validates constraints on value. Default is true.
	*/
	void setMultimode(const bool& value, bool validate = true);

	/*!
	* \brief Returns the value of the Multimode attribute.
	*
	* This field records whether (True) multiple operation modes are available for this Shutter or not (False). Typical operation modes are are: Fast, Soft and Neutral Density. The Fast mode provides the quickest open and close action sequence for which the shutter is capable. The Soft mode gradually opens and closes the shutter to reduce vibration. Control of light intensity without affecting wavelength is accommodated by a Neutral Density shutter mode (for more details see https://www.microscopyu.com/applications/live-cell-imaging/the-automatic-microscope).
	*
	* \return The value of the attribute
	*/
	bool getMultimode() const;

	/*!
	* \brief Resets the Multimode attribute to an unset state.
	*
	* This field records whether (True) multiple operation modes are available for this Shutter or not (False). Typical operation modes are are: Fast, Soft and Neutral Density. The Fast mode provides the quickest open and close action sequence for which the shutter is capable. The Soft mode gradually opens and closes the shutter to reduce vibration. Control of light intensity without affecting wavelength is accommodated by a Neutral Density shutter mode (for more details see https://www.microscopyu.com/applications/live-cell-imaging/the-automatic-microscope).
	*/
	void resetMultimode();

	/*!
	* \brief Checks whether the Multimode attribute is present.
	*
	* This field records whether (True) multiple operation modes are available for this Shutter or not (False). Typical operation modes are are: Fast, Soft and Neutral Density. The Fast mode provides the quickest open and close action sequence for which the shutter is capable. The Soft mode gradually opens and closes the shutter to reduce vibration. Control of light intensity without affecting wavelength is accommodated by a Neutral Density shutter mode (for more details see https://www.microscopyu.com/applications/live-cell-imaging/the-automatic-microscope).
	*
	* \return true if the attribute has been set, false otherwise
	*/
	bool hasMultimode() const;


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

    std::optional<float> ResponseTime; // Optional attribute
	UnitsTime_TypePtr ResponseTimeUnit = nullptr; // Optional attribute
	ShutterFunction_TypePtr Function = nullptr; // Optional attribute
    std::optional<float> OperatingFrequency; // Optional attribute
	UnitsFrequency_TypePtr OperatingFrequencyUnit = nullptr; // Optional attribute
    std::optional<bool> Motorized; // Optional attribute
    std::optional<float> MaxApertureDiameter; // Optional attribute
	UnitsLength_TypePtr MaxApertureDiameterUnit = nullptr; // Optional attribute
    std::optional<bool> Multimode; // Optional attribute
};

/*! Shared pointer for Shutter*/
typedef std::shared_ptr<Shutter> ShutterPtr;

} // namespace Inscoper::NBO

#endif // SHUTTER_HPP_INCLUDED