#ifndef VENDORBINDATA_HPP_INCLUDED
#define VENDORBINDATA_HPP_INCLUDED

#include <iostream>
#include <memory>
#include <optional>
#include <set>
#include <string>
#include <vector>
#include <NBO/NBO/NonNegativeLong_Type.h>
#include <NBO/NBO/base64Binary_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 VendorBinData.
*
* The contents of this element are base64-encoded. These are not CDATA sections, just base64 streams.
*/
class NBO_EXPORT VendorBinData : public base64Binary_Type {

public:
	
	VendorBinData();
	~VendorBinData();

	/*!
	* \brief Cast a NBOBaseClass to a VendorBinData.
	*
	* \param base The base class to cast
	* \return The casted element, or nullptr if the cast fails
	*/
	static std::shared_ptr<VendorBinData> 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 Compression attribute.
	*
	* Specifies the compression scheme used to encode the data. 
	*
	* \param value The value to set
	* \param validate If true, validates constraints on value. Default is true.
	*/
	void setCompression(const std::string& value, bool validate = true);

	/*!
	* \brief Returns the value of the Compression attribute.
	*
	* Specifies the compression scheme used to encode the data. 
	*
	* \return The value of the attribute
	*/
	std::string getCompression() const;

	/*!
	* \brief Resets the Compression attribute to an unset state.
	*
	* Specifies the compression scheme used to encode the data. 
	*/
	void resetCompression();

	/*!
	* \brief Checks whether the Compression attribute is present.
	*
	* Specifies the compression scheme used to encode the data. 
	*
	* \return true if the attribute has been set, false otherwise
	*/
	bool hasCompression() const;

	/*!
	* \brief Returns the allowed values for this attribut.
	*
	* Specifies the compression scheme used to encode the data. 
	*
	* \return The list of allowed values
	*/
	static const std::set<std::string>& getCompressionAllowedValues();

	/*!
	* \brief Sets the value of the BigEndian attribute.
	*
	* This is true if the binary data was written in BigEndian order. This is dependent on the system architecture of the machine that wrote the pixels. True for essentially all modern CPUs other than Intel and Alpha. All Binary data must be written in the same endian order.
	*
	* \param value The value to set
	* \param validate If true, validates constraints on value. Default is true.
	*/
	void setBigEndian(const bool& value, bool validate = true);

	/*!
	* \brief Returns the value of the BigEndian attribute.
	*
	* This is true if the binary data was written in BigEndian order. This is dependent on the system architecture of the machine that wrote the pixels. True for essentially all modern CPUs other than Intel and Alpha. All Binary data must be written in the same endian order.
	*
	* \return The value of the attribute
	*/
	bool getBigEndian() const;

	/*!
	* \brief Resets the BigEndian attribute to an unset state.
	*
	* This is true if the binary data was written in BigEndian order. This is dependent on the system architecture of the machine that wrote the pixels. True for essentially all modern CPUs other than Intel and Alpha. All Binary data must be written in the same endian order.
	*/
	void resetBigEndian();

	/*!
	* \brief Checks whether the BigEndian attribute is present.
	*
	* This is true if the binary data was written in BigEndian order. This is dependent on the system architecture of the machine that wrote the pixels. True for essentially all modern CPUs other than Intel and Alpha. All Binary data must be written in the same endian order.
	*
	* \return true if the attribute has been set, false otherwise
	*/
	bool hasBigEndian() const;

	/*!
	* \brief Sets the value of the Length attribute.
	*
	* Character count attribute for the BinData field. This is the length of the base-64 encoded block. It allows easy skipping of the block when parsing the file. [unit:bytes]
	*
	* \param value The value to set
	* \param validate If true, validates constraints on value. Default is true.
	*/
	void setLength(const Inscoper::NBO::NonNegativeLong_TypePtr& value, bool validate = true);

	/*!
	* \brief Returns the value of the Length attribute.
	*
	* Character count attribute for the BinData field. This is the length of the base-64 encoded block. It allows easy skipping of the block when parsing the file. [unit:bytes]
	*
	* \return The value of the attribute
	*/
	NonNegativeLong_TypePtr getLength() const;

	/*!
	* \brief Resets the Length attribute to an unset state.
	*
	* Character count attribute for the BinData field. This is the length of the base-64 encoded block. It allows easy skipping of the block when parsing the file. [unit:bytes]
	*/
	void resetLength();

	/*!
	* \brief Checks whether the optional Length attribute is present.
	*
	* Character count attribute for the BinData field. This is the length of the base-64 encoded block. It allows easy skipping of the block when parsing the file. [unit:bytes]
	*
	* \return true if the optional attribute has been set, false otherwise
	*/
	bool hasLength() const;


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

    std::optional<std::string> Compression; // Optional attribute
    static const std::set<std::string> CompressionAllowedValues;
    std::optional<bool> BigEndian; // Required attribute
	NonNegativeLong_TypePtr Length = nullptr; // Required attribute
};

/*! Shared pointer for VendorBinData*/
typedef std::shared_ptr<VendorBinData> VendorBinDataPtr;

} // namespace Inscoper::NBO

#endif // VENDORBINDATA_HPP_INCLUDED