#ifndef ADDITIONALVENDORINFORMATION_HPP_INCLUDED
#define ADDITIONALVENDORINFORMATION_HPP_INCLUDED

#include <iostream>
#include <memory>
#include <optional>
#include <set>
#include <string>
#include <vector>
#include <NBO/NBO/AnnotationRef.h>
#include <NBO/NBO/LSID_Type.h>
#include <NBO/NBO/VendorBinData.h>
#include <NBO/NBO/ENBOType.h>
#include <NBO/NBOGlobal.h>
#include <NBO/Shared/Base/NBOBaseClass.h>


namespace Inscoper::NBO {

/*!
* \brief Represents the XML element AdditionalVendorInformation.
*
* This element is intendended to be used as a last-resort solution to capture vendor-specific Additional Information about this hardware component, which cannot be described using either available model elements (Classes or Attributes) or the Map Annotation feature of the schema. The use of this feature should not be intended as a way to hide information that the Imaging Community has designated as essential to ensure rigor and reproducibility. In case this feature is used, the Vendor is fully responsible for this information, including but not limited to, making sure this information is appropriately recorded and kept up to date.
*/
class NBO_EXPORT AdditionalVendorInformation : public NBOBaseClass {

public:
	
	AdditionalVendorInformation();
	~AdditionalVendorInformation();

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

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

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

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

	/*!
	* \brief Sets the value of the VendorName attribute.
	*
	* The Name of the Vendor responsible for this Information.
	*
	* \param value The value to set
	* \param validate If true, validates constraints on value. Default is true.
	*/
	void setVendorName(const std::string& value, bool validate = true);

	/*!
	* \brief Returns the value of the VendorName attribute.
	*
	* The Name of the Vendor responsible for this Information.
	*
	* \return The value of the attribute
	*/
	std::string getVendorName() const;

	/*!
	* \brief Resets the VendorName attribute to an unset state.
	*
	* The Name of the Vendor responsible for this Information.
	*/
	void resetVendorName();

	/*!
	* \brief Checks whether the VendorName attribute is present.
	*
	* The Name of the Vendor responsible for this Information.
	*
	* \return true if the attribute has been set, false otherwise
	*/
	bool hasVendorName() const;

	/*!
	* \brief Returns the allowed values for this attribut.
	*
	* The Name of the Vendor responsible for this Information.
	*
	* \return The list of allowed values
	*/
	static const std::set<std::string>& getVendorNameAllowedValues();

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

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

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

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

	/*!
	* \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;

	LSID_TypePtr ID = nullptr; // Required attribute
    std::optional<std::string> VendorName; // Required attribute
    static const std::set<std::string> VendorNameAllowedValues;
    std::vector<Inscoper::NBO::VendorBinDataPtr> VendorBinData_List;
    std::vector<Inscoper::NBO::AnnotationRefPtr> AnnotationRef_List;
};

/*! Shared pointer for AdditionalVendorInformation*/
typedef std::shared_ptr<AdditionalVendorInformation> AdditionalVendorInformationPtr;

} // namespace Inscoper::NBO

#endif // ADDITIONALVENDORINFORMATION_HPP_INCLUDED