#ifndef STAGE_TYPE_HPP_INCLUDED
#define STAGE_TYPE_HPP_INCLUDED

#include <iostream>
#include <memory>
#include <optional>
#include <set>
#include <string>
#include <vector>
#include <NBO/NBO/SamplePositioning_Type.h>
#include <NBO/NBO/UnitsLength_Type.h>
#include <NBO/NBO/UnitsTime_Type.h>
#include <NBO/NBO/UnitsVelocity_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 Stage.
*
* This element describes a platform positioned at right angle to the optical axis of this Microscope, which is designed to either directly hold a Specimen Holder containing a Sample to be observed, or a Stage Insert, which itself holds the Sample Holder. In many cases, this device is capable of mechanical movements (as in a Mechanical Stage) to allow easy positioning and rotation of the Sample in the X-, Y-, and Z-axes.
*/
class NBO_EXPORT Stage_Type : public SamplePositioning_Type {

public:
	
	Stage_Type();
	~Stage_Type();

	/*!
	* \brief Cast a NBOBaseClass to a Stage_Type.
	*
	* \param base The base class to cast
	* \return The casted element, or nullptr if the cast fails
	*/
	static std::shared_ptr<Stage_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 XYMaxVelocity attribute.
	*
	* This field describes the maximum XY-axis Velocity at which this Stage is capable of moving.
	*
	* \param value The value to set
	* \param validate If true, validates constraints on value. Default is true.
	*/
	void setXYMaxVelocity(const float& value, bool validate = true);

	/*!
	* \brief Returns the value of the XYMaxVelocity attribute.
	*
	* This field describes the maximum XY-axis Velocity at which this Stage is capable of moving.
	*
	* \return The value of the attribute
	*/
	float getXYMaxVelocity() const;

	/*!
	* \brief Resets the XYMaxVelocity attribute to an unset state.
	*
	* This field describes the maximum XY-axis Velocity at which this Stage is capable of moving.
	*/
	void resetXYMaxVelocity();

	/*!
	* \brief Checks whether the XYMaxVelocity attribute is present.
	*
	* This field describes the maximum XY-axis Velocity at which this Stage is capable of moving.
	*
	* \return true if the attribute has been set, false otherwise
	*/
	bool hasXYMaxVelocity() const;

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

	/*!
	* \brief Returns the value of the XYMaxVelocityUnit attribute.
	*
	* No description available in the XSD standard.
	*
	* \return The value of the attribute
	*/
	UnitsVelocity_TypePtr getXYMaxVelocityUnit() const;

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

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

	/*!
	* \brief Sets the value of the XYRepeatability attribute.
	*
	* This field captures the expected Accuracy with which this Stage is capable of returning to a previously visited XY-plane Position, as specified by the Manufacturer. This metric is important for example for Tiling.
	*
	* \param value The value to set
	* \param validate If true, validates constraints on value. Default is true.
	*/
	void setXYRepeatability(const float& value, bool validate = true);

	/*!
	* \brief Returns the value of the XYRepeatability attribute.
	*
	* This field captures the expected Accuracy with which this Stage is capable of returning to a previously visited XY-plane Position, as specified by the Manufacturer. This metric is important for example for Tiling.
	*
	* \return The value of the attribute
	*/
	float getXYRepeatability() const;

	/*!
	* \brief Resets the XYRepeatability attribute to an unset state.
	*
	* This field captures the expected Accuracy with which this Stage is capable of returning to a previously visited XY-plane Position, as specified by the Manufacturer. This metric is important for example for Tiling.
	*/
	void resetXYRepeatability();

	/*!
	* \brief Checks whether the XYRepeatability attribute is present.
	*
	* This field captures the expected Accuracy with which this Stage is capable of returning to a previously visited XY-plane Position, as specified by the Manufacturer. This metric is important for example for Tiling.
	*
	* \return true if the attribute has been set, false otherwise
	*/
	bool hasXYRepeatability() const;

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

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

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

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

	/*!
	* \brief Sets the value of the XTravelRange attribute.
	*
	* This field describes the Total Range in the X-axis that this Stage can Travel.
	*
	* \param value The value to set
	* \param validate If true, validates constraints on value. Default is true.
	*/
	void setXTravelRange(const float& value, bool validate = true);

	/*!
	* \brief Returns the value of the XTravelRange attribute.
	*
	* This field describes the Total Range in the X-axis that this Stage can Travel.
	*
	* \return The value of the attribute
	*/
	float getXTravelRange() const;

	/*!
	* \brief Resets the XTravelRange attribute to an unset state.
	*
	* This field describes the Total Range in the X-axis that this Stage can Travel.
	*/
	void resetXTravelRange();

	/*!
	* \brief Checks whether the XTravelRange attribute is present.
	*
	* This field describes the Total Range in the X-axis that this Stage can Travel.
	*
	* \return true if the attribute has been set, false otherwise
	*/
	bool hasXTravelRange() const;

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

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

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

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

	/*!
	* \brief Sets the value of the YTravelRange attribute.
	*
	* This field describes the Total Range in the Y-axis that this Stage can Travel.
	*
	* \param value The value to set
	* \param validate If true, validates constraints on value. Default is true.
	*/
	void setYTravelRange(const float& value, bool validate = true);

	/*!
	* \brief Returns the value of the YTravelRange attribute.
	*
	* This field describes the Total Range in the Y-axis that this Stage can Travel.
	*
	* \return The value of the attribute
	*/
	float getYTravelRange() const;

	/*!
	* \brief Resets the YTravelRange attribute to an unset state.
	*
	* This field describes the Total Range in the Y-axis that this Stage can Travel.
	*/
	void resetYTravelRange();

	/*!
	* \brief Checks whether the YTravelRange attribute is present.
	*
	* This field describes the Total Range in the Y-axis that this Stage can Travel.
	*
	* \return true if the attribute has been set, false otherwise
	*/
	bool hasYTravelRange() const;

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

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

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

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

	/*!
	* \brief Sets the value of the XYReproducibility attribute.
	*
	* This field captures the expected Precision with which this Stage is capable of maintaining a given XY-plane Position over time during as specified by the Manufacturer. This metric is generally referred to as Reproducibility and it might also be referred to as Lateral Drift. This metric is particularly relevant for Stereology systems and for the calibration of Sample Positioning devices.
	*
	* \param value The value to set
	* \param validate If true, validates constraints on value. Default is true.
	*/
	void setXYReproducibility(const float& value, bool validate = true);

	/*!
	* \brief Returns the value of the XYReproducibility attribute.
	*
	* This field captures the expected Precision with which this Stage is capable of maintaining a given XY-plane Position over time during as specified by the Manufacturer. This metric is generally referred to as Reproducibility and it might also be referred to as Lateral Drift. This metric is particularly relevant for Stereology systems and for the calibration of Sample Positioning devices.
	*
	* \return The value of the attribute
	*/
	float getXYReproducibility() const;

	/*!
	* \brief Resets the XYReproducibility attribute to an unset state.
	*
	* This field captures the expected Precision with which this Stage is capable of maintaining a given XY-plane Position over time during as specified by the Manufacturer. This metric is generally referred to as Reproducibility and it might also be referred to as Lateral Drift. This metric is particularly relevant for Stereology systems and for the calibration of Sample Positioning devices.
	*/
	void resetXYReproducibility();

	/*!
	* \brief Checks whether the XYReproducibility attribute is present.
	*
	* This field captures the expected Precision with which this Stage is capable of maintaining a given XY-plane Position over time during as specified by the Manufacturer. This metric is generally referred to as Reproducibility and it might also be referred to as Lateral Drift. This metric is particularly relevant for Stereology systems and for the calibration of Sample Positioning devices.
	*
	* \return true if the attribute has been set, false otherwise
	*/
	bool hasXYReproducibility() const;

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

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

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

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

	/*!
	* \brief Sets the value of the XYSettlingTime attribute.
	*
	* This field describes the expected time it takes for this Stage to stabilize at the target XY-plane position, as specified by the Manufacturer.
	*
	* \param value The value to set
	* \param validate If true, validates constraints on value. Default is true.
	*/
	void setXYSettlingTime(const float& value, bool validate = true);

	/*!
	* \brief Returns the value of the XYSettlingTime attribute.
	*
	* This field describes the expected time it takes for this Stage to stabilize at the target XY-plane position, as specified by the Manufacturer.
	*
	* \return The value of the attribute
	*/
	float getXYSettlingTime() const;

	/*!
	* \brief Resets the XYSettlingTime attribute to an unset state.
	*
	* This field describes the expected time it takes for this Stage to stabilize at the target XY-plane position, as specified by the Manufacturer.
	*/
	void resetXYSettlingTime();

	/*!
	* \brief Checks whether the XYSettlingTime attribute is present.
	*
	* This field describes the expected time it takes for this Stage to stabilize at the target XY-plane position, as specified by the Manufacturer.
	*
	* \return true if the attribute has been set, false otherwise
	*/
	bool hasXYSettlingTime() const;

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

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

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

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

	/*!
	* \brief Sets the value of the XYResolution attribute.
	*
	* This field describes the XY-plane motion Resolution of this Stage as specified by the Manufacturer.
	*
	* \param value The value to set
	* \param validate If true, validates constraints on value. Default is true.
	*/
	void setXYResolution(const float& value, bool validate = true);

	/*!
	* \brief Returns the value of the XYResolution attribute.
	*
	* This field describes the XY-plane motion Resolution of this Stage as specified by the Manufacturer.
	*
	* \return The value of the attribute
	*/
	float getXYResolution() const;

	/*!
	* \brief Resets the XYResolution attribute to an unset state.
	*
	* This field describes the XY-plane motion Resolution of this Stage as specified by the Manufacturer.
	*/
	void resetXYResolution();

	/*!
	* \brief Checks whether the XYResolution attribute is present.
	*
	* This field describes the XY-plane motion Resolution of this Stage as specified by the Manufacturer.
	*
	* \return true if the attribute has been set, false otherwise
	*/
	bool hasXYResolution() const;

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

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

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

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

	/*!
	* \brief Sets the value of the XYPositionLinearityError attribute.
	*
	* This field describes the XY-axis positioning error (typically expressed in % error) associated with this Stage as specified by the Manufacturer.
	*
	* \param value The value to set
	* \param validate If true, validates constraints on value. Default is true.
	*/
	void setXYPositionLinearityError(const float& value, bool validate = true);

	/*!
	* \brief Returns the value of the XYPositionLinearityError attribute.
	*
	* This field describes the XY-axis positioning error (typically expressed in % error) associated with this Stage as specified by the Manufacturer.
	*
	* \return The value of the attribute
	*/
	float getXYPositionLinearityError() const;

	/*!
	* \brief Resets the XYPositionLinearityError attribute to an unset state.
	*
	* This field describes the XY-axis positioning error (typically expressed in % error) associated with this Stage as specified by the Manufacturer.
	*/
	void resetXYPositionLinearityError();

	/*!
	* \brief Checks whether the XYPositionLinearityError attribute is present.
	*
	* This field describes the XY-axis positioning error (typically expressed in % error) associated with this Stage as specified by the Manufacturer.
	*
	* \return true if the attribute has been set, false otherwise
	*/
	bool hasXYPositionLinearityError() const;


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

    std::optional<float> XYMaxVelocity; // Optional attribute
	UnitsVelocity_TypePtr XYMaxVelocityUnit = nullptr; // Optional attribute
    std::optional<float> XYRepeatability; // Required attribute
	UnitsLength_TypePtr XYRepeatabilityUnit = nullptr; // Optional attribute
    std::optional<float> XTravelRange; // Required attribute
	UnitsLength_TypePtr XTravelRangeUnit = nullptr; // Optional attribute
    std::optional<float> YTravelRange; // Required attribute
	UnitsLength_TypePtr YTravelRangeUnit = nullptr; // Optional attribute
    std::optional<float> XYReproducibility; // Optional attribute
	UnitsLength_TypePtr XYReproducibilityUnit = nullptr; // Optional attribute
    std::optional<float> XYSettlingTime; // Optional attribute
	UnitsTime_TypePtr XYSettlingTimeUnit = nullptr; // Optional attribute
    std::optional<float> XYResolution; // Optional attribute
	UnitsLength_TypePtr XYZResolutionUnit = nullptr; // Optional attribute
    std::optional<float> XYPositionLinearityError; // Optional attribute
};

/*! Shared pointer for Stage_Type*/
typedef std::shared_ptr<Stage_Type> Stage_TypePtr;

} // namespace Inscoper::NBO

#endif // STAGE_TYPE_HPP_INCLUDED