#ifndef TIFFDATA_HPP_INCLUDED
#define TIFFDATA_HPP_INCLUDED

#include <iostream>
#include <memory>
#include <optional>
#include <set>
#include <string>
#include <vector>
#include <NBO/NBO/NonNegativeInt_Type.h>
#include <NBO/NBO/UniversallyUniqueIdentifier_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 TiffData.
*
* This field describes the location of the pixel data in a tiff file.
*/
class NBO_EXPORT TiffData : public NBOBaseClass {

public:
	/*!
	* \brief Represents the XML element UUID.
	*
	* This must be used when the IFDs are located in another file. Note: It is permissible for this to be self referential. 
	*/
	class NBO_EXPORT InlineUUID : public UniversallyUniqueIdentifier_Type {
	
	public:
		
		InlineUUID();
		~InlineUUID();
	
		/*!
		* \brief Cast a NBOBaseClass to a InlineUUID.
		*
		* \param base The base class to cast
		* \return The casted element, or nullptr if the cast fails
		*/
		static std::shared_ptr<InlineUUID> 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 FileName attribute.
		*
		* This can be used when the IFDs are located in another file. The / (forward slash) is used as the path separator. A relative path is recommended. However an absolute path can be specified. Default is to use the file the ome-xml data has been pulled from. Note: It is permissible for this to be self referential. The file image1.tiff may contain ome-xml data that has FilePath="image1.tiff" or "./image1.tiff" 
		*
		* \param value The value to set
		* \param validate If true, validates constraints on value. Default is true.
		*/
		void setFileName(const std::string& value, bool validate = true);
	
		/*!
		* \brief Returns the value of the FileName attribute.
		*
		* This can be used when the IFDs are located in another file. The / (forward slash) is used as the path separator. A relative path is recommended. However an absolute path can be specified. Default is to use the file the ome-xml data has been pulled from. Note: It is permissible for this to be self referential. The file image1.tiff may contain ome-xml data that has FilePath="image1.tiff" or "./image1.tiff" 
		*
		* \return The value of the attribute
		*/
		std::string getFileName() const;
	
		/*!
		* \brief Resets the FileName attribute to an unset state.
		*
		* This can be used when the IFDs are located in another file. The / (forward slash) is used as the path separator. A relative path is recommended. However an absolute path can be specified. Default is to use the file the ome-xml data has been pulled from. Note: It is permissible for this to be self referential. The file image1.tiff may contain ome-xml data that has FilePath="image1.tiff" or "./image1.tiff" 
		*/
		void resetFileName();
	
		/*!
		* \brief Checks whether the FileName attribute is present.
		*
		* This can be used when the IFDs are located in another file. The / (forward slash) is used as the path separator. A relative path is recommended. However an absolute path can be specified. Default is to use the file the ome-xml data has been pulled from. Note: It is permissible for this to be self referential. The file image1.tiff may contain ome-xml data that has FilePath="image1.tiff" or "./image1.tiff" 
		*
		* \return true if the attribute has been set, false otherwise
		*/
		bool hasFileName() const;
	
		/*!
		* \brief Returns the allowed values for this attribut.
		*
		* This can be used when the IFDs are located in another file. The / (forward slash) is used as the path separator. A relative path is recommended. However an absolute path can be specified. Default is to use the file the ome-xml data has been pulled from. Note: It is permissible for this to be self referential. The file image1.tiff may contain ome-xml data that has FilePath="image1.tiff" or "./image1.tiff" 
		*
		* \return The list of allowed values
		*/
		static const std::set<std::string>& getFileNameAllowedValues();
	
	
	private:
		class Impl;
		std::unique_ptr<Impl> pImpl;
	
	    std::optional<std::string> FileName; // Optional attribute
	    static const std::set<std::string> FileNameAllowedValues;
	};
	
	/*! Shared pointer for InlineUUID*/
	typedef std::shared_ptr<InlineUUID> InlineUUIDPtr;
	
	
	TiffData();
	~TiffData();

	/*!
	* \brief Cast a NBOBaseClass to a TiffData.
	*
	* \param base The base class to cast
	* \return The casted element, or nullptr if the cast fails
	*/
	static std::shared_ptr<TiffData> 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 IFD attribute.
	*
	* Gives the IFD(s) for which this element is applicable. Indexed from 0. Default is 0 (the first IFD). [units:none] 
	*
	* \param value The value to set
	* \param validate If true, validates constraints on value. Default is true.
	*/
	void setIFD(const Inscoper::NBO::NonNegativeInt_TypePtr& value, bool validate = true);

	/*!
	* \brief Returns the value of the IFD attribute.
	*
	* Gives the IFD(s) for which this element is applicable. Indexed from 0. Default is 0 (the first IFD). [units:none] 
	*
	* \return The value of the attribute
	*/
	NonNegativeInt_TypePtr getIFD() const;

	/*!
	* \brief Resets the IFD attribute to an unset state.
	*
	* Gives the IFD(s) for which this element is applicable. Indexed from 0. Default is 0 (the first IFD). [units:none] 
	*/
	void resetIFD();

	/*!
	* \brief Checks whether the optional IFD attribute is present.
	*
	* Gives the IFD(s) for which this element is applicable. Indexed from 0. Default is 0 (the first IFD). [units:none] 
	*
	* \return true if the optional attribute has been set, false otherwise
	*/
	bool hasIFD() const;

	/*!
	* \brief Sets the value of the FirstZ attribute.
	*
	* Gives the Z position of the Image Plane at the specified IFD. Indexed from 0. Default is 0 (the first Z position). [units:none] 
	*
	* \param value The value to set
	* \param validate If true, validates constraints on value. Default is true.
	*/
	void setFirstZ(const Inscoper::NBO::NonNegativeInt_TypePtr& value, bool validate = true);

	/*!
	* \brief Returns the value of the FirstZ attribute.
	*
	* Gives the Z position of the Image Plane at the specified IFD. Indexed from 0. Default is 0 (the first Z position). [units:none] 
	*
	* \return The value of the attribute
	*/
	NonNegativeInt_TypePtr getFirstZ() const;

	/*!
	* \brief Resets the FirstZ attribute to an unset state.
	*
	* Gives the Z position of the Image Plane at the specified IFD. Indexed from 0. Default is 0 (the first Z position). [units:none] 
	*/
	void resetFirstZ();

	/*!
	* \brief Checks whether the optional FirstZ attribute is present.
	*
	* Gives the Z position of the Image Plane at the specified IFD. Indexed from 0. Default is 0 (the first Z position). [units:none] 
	*
	* \return true if the optional attribute has been set, false otherwise
	*/
	bool hasFirstZ() const;

	/*!
	* \brief Sets the value of the FirstT attribute.
	*
	* Gives the T position of the Image Plane at the specified IFD. Indexed from 0. Default is 0 (the first T position). [units:none] 
	*
	* \param value The value to set
	* \param validate If true, validates constraints on value. Default is true.
	*/
	void setFirstT(const Inscoper::NBO::NonNegativeInt_TypePtr& value, bool validate = true);

	/*!
	* \brief Returns the value of the FirstT attribute.
	*
	* Gives the T position of the Image Plane at the specified IFD. Indexed from 0. Default is 0 (the first T position). [units:none] 
	*
	* \return The value of the attribute
	*/
	NonNegativeInt_TypePtr getFirstT() const;

	/*!
	* \brief Resets the FirstT attribute to an unset state.
	*
	* Gives the T position of the Image Plane at the specified IFD. Indexed from 0. Default is 0 (the first T position). [units:none] 
	*/
	void resetFirstT();

	/*!
	* \brief Checks whether the optional FirstT attribute is present.
	*
	* Gives the T position of the Image Plane at the specified IFD. Indexed from 0. Default is 0 (the first T position). [units:none] 
	*
	* \return true if the optional attribute has been set, false otherwise
	*/
	bool hasFirstT() const;

	/*!
	* \brief Sets the value of the FirstC attribute.
	*
	* Gives the C position of the Image Plane at the specified IFD. Indexed from 0. Default is 0 (the first C position). [units:none] 
	*
	* \param value The value to set
	* \param validate If true, validates constraints on value. Default is true.
	*/
	void setFirstC(const Inscoper::NBO::NonNegativeInt_TypePtr& value, bool validate = true);

	/*!
	* \brief Returns the value of the FirstC attribute.
	*
	* Gives the C position of the Image Plane at the specified IFD. Indexed from 0. Default is 0 (the first C position). [units:none] 
	*
	* \return The value of the attribute
	*/
	NonNegativeInt_TypePtr getFirstC() const;

	/*!
	* \brief Resets the FirstC attribute to an unset state.
	*
	* Gives the C position of the Image Plane at the specified IFD. Indexed from 0. Default is 0 (the first C position). [units:none] 
	*/
	void resetFirstC();

	/*!
	* \brief Checks whether the optional FirstC attribute is present.
	*
	* Gives the C position of the Image Plane at the specified IFD. Indexed from 0. Default is 0 (the first C position). [units:none] 
	*
	* \return true if the optional attribute has been set, false otherwise
	*/
	bool hasFirstC() const;

	/*!
	* \brief Sets the value of the PlaneCount attribute.
	*
	* Gives the number of IFDs affected. Dimension order of IFDs is given by the enclosing Pixels element's DimensionOrder attribute. Default is the number of IFDs in the TIFF file, unless an IFD is specified, in which case the default is 1. [units:none] 
	*
	* \param value The value to set
	* \param validate If true, validates constraints on value. Default is true.
	*/
	void setPlaneCount(const Inscoper::NBO::NonNegativeInt_TypePtr& value, bool validate = true);

	/*!
	* \brief Returns the value of the PlaneCount attribute.
	*
	* Gives the number of IFDs affected. Dimension order of IFDs is given by the enclosing Pixels element's DimensionOrder attribute. Default is the number of IFDs in the TIFF file, unless an IFD is specified, in which case the default is 1. [units:none] 
	*
	* \return The value of the attribute
	*/
	NonNegativeInt_TypePtr getPlaneCount() const;

	/*!
	* \brief Resets the PlaneCount attribute to an unset state.
	*
	* Gives the number of IFDs affected. Dimension order of IFDs is given by the enclosing Pixels element's DimensionOrder attribute. Default is the number of IFDs in the TIFF file, unless an IFD is specified, in which case the default is 1. [units:none] 
	*/
	void resetPlaneCount();

	/*!
	* \brief Checks whether the optional PlaneCount attribute is present.
	*
	* Gives the number of IFDs affected. Dimension order of IFDs is given by the enclosing Pixels element's DimensionOrder attribute. Default is the number of IFDs in the TIFF file, unless an IFD is specified, in which case the default is 1. [units:none] 
	*
	* \return true if the optional attribute has been set, false otherwise
	*/
	bool hasPlaneCount() const;

	/*!
	* \brief Sets the value of the UUID element.
	*
	* This must be used when the IFDs are located in another file. Note: It is permissible for this to be self referential. 
	*
	* \param value The value to set
	* \param validate If true, validates constraints on value. Default is true.
	*/
	void setUUID(const Inscoper::NBO::TiffData::InlineUUIDPtr& value, bool validate = true);

	/*!
	* \brief Returns the value of the UUID element.
	*
	* This must be used when the IFDs are located in another file. Note: It is permissible for this to be self referential. 
	*
	* \return The value of the element
	*/
	Inscoper::NBO::TiffData::InlineUUIDPtr getUUID() const;

	/*!
	* \brief Resets the UUID element to an unset state.
	*
	* This must be used when the IFDs are located in another file. Note: It is permissible for this to be self referential. 
	*/
	void resetUUID();

	/*!
	* \brief Checks whether the optional UUID element is present.
	*
	* This must be used when the IFDs are located in another file. Note: It is permissible for this to be self referential. 
	*
	* \return true if the optional attribute has been set, false otherwise
	*/
	bool hasUUID() const;


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

	NonNegativeInt_TypePtr IFD = nullptr; // Optional attribute
	NonNegativeInt_TypePtr FirstZ = nullptr; // Optional attribute
	NonNegativeInt_TypePtr FirstT = nullptr; // Optional attribute
	NonNegativeInt_TypePtr FirstC = nullptr; // Optional attribute
	NonNegativeInt_TypePtr PlaneCount = nullptr; // Optional attribute
    Inscoper::NBO::TiffData::InlineUUIDPtr UUID = nullptr;
};

/*! Shared pointer for TiffData*/
typedef std::shared_ptr<TiffData> TiffDataPtr;

} // namespace Inscoper::NBO

#endif // TIFFDATA_HPP_INCLUDED