#ifndef EXPERIMENTER_HPP_INCLUDED
#define EXPERIMENTER_HPP_INCLUDED

#include <iostream>
#include <memory>
#include <optional>
#include <set>
#include <string>
#include <vector>
#include <NBO/NBO/AnnotationRef.h>
#include <NBO/NBO/ExperimenterID_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 Experimenter.
*
* This element describes a person who performed an imaging experiment. This person may also be a user of the OME system, in which case the UserName element contains their login name.Experimenters may belong to one or more groups which are specified using one or more ExperimenterGroupRef elements. 
*/
class NBO_EXPORT Experimenter : public NBOBaseClass {

public:
	
	Experimenter();
	~Experimenter();

	/*!
	* \brief Cast a NBOBaseClass to a Experimenter.
	*
	* \param base The base class to cast
	* \return The casted element, or nullptr if the cast fails
	*/
	static std::shared_ptr<Experimenter> 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.
	*
	* 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 setID(const Inscoper::NBO::ExperimenterID_TypePtr& value, bool validate = true);

	/*!
	* \brief Returns the value of the ID attribute.
	*
	* No description available in the XSD standard.
	*
	* \return The value of the attribute
	*/
	ExperimenterID_TypePtr getID() const;

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

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

	/*!
	* \brief Sets the value of the FirstName 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 setFirstName(const std::string& value, bool validate = true);

	/*!
	* \brief Returns the value of the FirstName attribute.
	*
	* No description available in the XSD standard.
	*
	* \return The value of the attribute
	*/
	std::string getFirstName() const;

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

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

	/*!
	* \brief Returns the allowed values for this attribut.
	*
	* No description available in the XSD standard.
	*
	* \return The list of allowed values
	*/
	static const std::set<std::string>& getFirstNameAllowedValues();

	/*!
	* \brief Sets the value of the MiddleName 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 setMiddleName(const std::string& value, bool validate = true);

	/*!
	* \brief Returns the value of the MiddleName attribute.
	*
	* No description available in the XSD standard.
	*
	* \return The value of the attribute
	*/
	std::string getMiddleName() const;

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

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

	/*!
	* \brief Returns the allowed values for this attribut.
	*
	* No description available in the XSD standard.
	*
	* \return The list of allowed values
	*/
	static const std::set<std::string>& getMiddleNameAllowedValues();

	/*!
	* \brief Sets the value of the LastName 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 setLastName(const std::string& value, bool validate = true);

	/*!
	* \brief Returns the value of the LastName attribute.
	*
	* No description available in the XSD standard.
	*
	* \return The value of the attribute
	*/
	std::string getLastName() const;

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

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

	/*!
	* \brief Returns the allowed values for this attribut.
	*
	* No description available in the XSD standard.
	*
	* \return The list of allowed values
	*/
	static const std::set<std::string>& getLastNameAllowedValues();

	/*!
	* \brief Sets the value of the Email 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 setEmail(const std::string& value, bool validate = true);

	/*!
	* \brief Returns the value of the Email attribute.
	*
	* No description available in the XSD standard.
	*
	* \return The value of the attribute
	*/
	std::string getEmail() const;

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

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

	/*!
	* \brief Returns the allowed values for this attribut.
	*
	* No description available in the XSD standard.
	*
	* \return The list of allowed values
	*/
	static const std::set<std::string>& getEmailAllowedValues();

	/*!
	* \brief Sets the value of the Institution attribute.
	*
	* A person's Institution The organizing structure that people belong to other than groups. A university, or company, etc. We do not specify a department element, and do not mean for Institution to be used in this way. We simply wish to say XXX at YYY. Where YYY has a better chance of being tied to a geographically fixed location and of being more recognizable than a group of experimenters. [plain text string] 
	*
	* \param value The value to set
	* \param validate If true, validates constraints on value. Default is true.
	*/
	void setInstitution(const std::string& value, bool validate = true);

	/*!
	* \brief Returns the value of the Institution attribute.
	*
	* A person's Institution The organizing structure that people belong to other than groups. A university, or company, etc. We do not specify a department element, and do not mean for Institution to be used in this way. We simply wish to say XXX at YYY. Where YYY has a better chance of being tied to a geographically fixed location and of being more recognizable than a group of experimenters. [plain text string] 
	*
	* \return The value of the attribute
	*/
	std::string getInstitution() const;

	/*!
	* \brief Resets the Institution attribute to an unset state.
	*
	* A person's Institution The organizing structure that people belong to other than groups. A university, or company, etc. We do not specify a department element, and do not mean for Institution to be used in this way. We simply wish to say XXX at YYY. Where YYY has a better chance of being tied to a geographically fixed location and of being more recognizable than a group of experimenters. [plain text string] 
	*/
	void resetInstitution();

	/*!
	* \brief Checks whether the Institution attribute is present.
	*
	* A person's Institution The organizing structure that people belong to other than groups. A university, or company, etc. We do not specify a department element, and do not mean for Institution to be used in this way. We simply wish to say XXX at YYY. Where YYY has a better chance of being tied to a geographically fixed location and of being more recognizable than a group of experimenters. [plain text string] 
	*
	* \return true if the attribute has been set, false otherwise
	*/
	bool hasInstitution() const;

	/*!
	* \brief Returns the allowed values for this attribut.
	*
	* A person's Institution The organizing structure that people belong to other than groups. A university, or company, etc. We do not specify a department element, and do not mean for Institution to be used in this way. We simply wish to say XXX at YYY. Where YYY has a better chance of being tied to a geographically fixed location and of being more recognizable than a group of experimenters. [plain text string] 
	*
	* \return The list of allowed values
	*/
	static const std::set<std::string>& getInstitutionAllowedValues();

	/*!
	* \brief Sets the value of the UserName 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 setUserName(const std::string& value, bool validate = true);

	/*!
	* \brief Returns the value of the UserName attribute.
	*
	* No description available in the XSD standard.
	*
	* \return The value of the attribute
	*/
	std::string getUserName() const;

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

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

	/*!
	* \brief Returns the allowed values for this attribut.
	*
	* No description available in the XSD standard.
	*
	* \return The list of allowed values
	*/
	static const std::set<std::string>& getUserNameAllowedValues();

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

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

	/*!
	* \brief Adds a new AnnotationRef 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 addToAnnotationRef_List(const Inscoper::NBO::AnnotationRefPtr& value, bool validate = true);

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


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

	ExperimenterID_TypePtr ID = nullptr; // Required attribute
    std::optional<std::string> FirstName; // Optional attribute
    static const std::set<std::string> FirstNameAllowedValues;
    std::optional<std::string> MiddleName; // Optional attribute
    static const std::set<std::string> MiddleNameAllowedValues;
    std::optional<std::string> LastName; // Optional attribute
    static const std::set<std::string> LastNameAllowedValues;
    std::optional<std::string> Email; // Optional attribute
    static const std::set<std::string> EmailAllowedValues;
    std::optional<std::string> Institution; // Optional attribute
    static const std::set<std::string> InstitutionAllowedValues;
    std::optional<std::string> UserName; // Optional attribute
    static const std::set<std::string> UserNameAllowedValues;
    std::vector<Inscoper::NBO::AnnotationRefPtr> AnnotationRef_List;
};

/*! Shared pointer for Experimenter*/
typedef std::shared_ptr<Experimenter> ExperimenterPtr;

} // namespace Inscoper::NBO

#endif // EXPERIMENTER_HPP_INCLUDED