#ifndef CHANNEL_HPP_INCLUDED
#define CHANNEL_HPP_INCLUDED

#include <iostream>
#include <memory>
#include <optional>
#include <set>
#include <string>
#include <vector>
#include <NBO/NBO/AnnotationRef.h>
#include <NBO/NBO/ChannelContrastMethod_Type.h>
#include <NBO/NBO/ChannelID_Type.h>
#include <NBO/NBO/Color_Type.h>
#include <NBO/NBO/Denomination_Type.h>
#include <NBO/NBO/ExcitationCalibration.h>
#include <NBO/NBO/Fluorophore.h>
#include <NBO/NBO/ImagingMethodList_Type.h>
#include <NBO/NBO/LightPath.h>
#include <NBO/NBO/PositiveInt_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 Channel.
*
* Each Image has to have at least one Plane and one Channel. The Channel element stores information about how the each Image Channel was acquired. The total number of Channel elements for a given Image must equal to SizeC.
*/
class NBO_EXPORT Channel : public NBOBaseClass {

public:
	
	Channel();
	~Channel();

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

	/*!
	* \brief Returns the value of the ID attribute.
	*
	* A unique identifier for this Channel.
	*
	* \return The value of the attribute
	*/
	ChannelID_TypePtr getID() const;

	/*!
	* \brief Resets the ID attribute to an unset state.
	*
	* A unique identifier for this Channel.
	*/
	void resetID();

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

	/*!
	* \brief Sets the value of the Name attribute.
	*
	* A Name for this Channel that is suitable for presentation to the user. 
	*
	* \param value The value to set
	* \param validate If true, validates constraints on value. Default is true.
	*/
	void setName(const Inscoper::NBO::Denomination_TypePtr& value, bool validate = true);

	/*!
	* \brief Returns the value of the Name attribute.
	*
	* A Name for this Channel that is suitable for presentation to the user. 
	*
	* \return The value of the attribute
	*/
	Denomination_TypePtr getName() const;

	/*!
	* \brief Resets the Name attribute to an unset state.
	*
	* A Name for this Channel that is suitable for presentation to the user. 
	*/
	void resetName();

	/*!
	* \brief Checks whether the optional Name attribute is present.
	*
	* A Name for this Channel that is suitable for presentation to the user. 
	*
	* \return true if the optional attribute has been set, false otherwise
	*/
	bool hasName() const;

	/*!
	* \brief Sets the value of the IlluminationType attribute.
	*
	* This field describes the Light Microscopy Illumination method performed in this case. Allowable terms were obtained from the Biological Imaging Methods Ontology (Fbbi; https://www.ebi.ac.uk/ols/ontologies/fbbi) Light Microscopy term (http://purl.obolibrary.org/obo/FBbi_00000345).
	*
	* \param value The value to set
	* \param validate If true, validates constraints on value. Default is true.
	*/
	void setIlluminationType(const Inscoper::NBO::ImagingMethodList_TypePtr& value, bool validate = true);

	/*!
	* \brief Returns the value of the IlluminationType attribute.
	*
	* This field describes the Light Microscopy Illumination method performed in this case. Allowable terms were obtained from the Biological Imaging Methods Ontology (Fbbi; https://www.ebi.ac.uk/ols/ontologies/fbbi) Light Microscopy term (http://purl.obolibrary.org/obo/FBbi_00000345).
	*
	* \return The value of the attribute
	*/
	ImagingMethodList_TypePtr getIlluminationType() const;

	/*!
	* \brief Resets the IlluminationType attribute to an unset state.
	*
	* This field describes the Light Microscopy Illumination method performed in this case. Allowable terms were obtained from the Biological Imaging Methods Ontology (Fbbi; https://www.ebi.ac.uk/ols/ontologies/fbbi) Light Microscopy term (http://purl.obolibrary.org/obo/FBbi_00000345).
	*/
	void resetIlluminationType();

	/*!
	* \brief Checks whether the optional IlluminationType attribute is present.
	*
	* This field describes the Light Microscopy Illumination method performed in this case. Allowable terms were obtained from the Biological Imaging Methods Ontology (Fbbi; https://www.ebi.ac.uk/ols/ontologies/fbbi) Light Microscopy term (http://purl.obolibrary.org/obo/FBbi_00000345).
	*
	* \return true if the optional attribute has been set, false otherwise
	*/
	bool hasIlluminationType() const;

	/*!
	* \brief Sets the value of the IlluminationTypeTermAcession attribute.
	*
	* This field records the Accession ID for the term used to describe the Illumination Type. A sub-classes of Light Microscopy term (http://purl.obolibrary.org/obo/FBbi_00000345) is recommended.
	*
	* \param value The value to set
	* \param validate If true, validates constraints on value. Default is true.
	*/
	void setIlluminationTypeTermAcession(const std::string& value, bool validate = true);

	/*!
	* \brief Returns the value of the IlluminationTypeTermAcession attribute.
	*
	* This field records the Accession ID for the term used to describe the Illumination Type. A sub-classes of Light Microscopy term (http://purl.obolibrary.org/obo/FBbi_00000345) is recommended.
	*
	* \return The value of the attribute
	*/
	std::string getIlluminationTypeTermAcession() const;

	/*!
	* \brief Resets the IlluminationTypeTermAcession attribute to an unset state.
	*
	* This field records the Accession ID for the term used to describe the Illumination Type. A sub-classes of Light Microscopy term (http://purl.obolibrary.org/obo/FBbi_00000345) is recommended.
	*/
	void resetIlluminationTypeTermAcession();

	/*!
	* \brief Checks whether the IlluminationTypeTermAcession attribute is present.
	*
	* This field records the Accession ID for the term used to describe the Illumination Type. A sub-classes of Light Microscopy term (http://purl.obolibrary.org/obo/FBbi_00000345) is recommended.
	*
	* \return true if the attribute has been set, false otherwise
	*/
	bool hasIlluminationTypeTermAcession() const;

	/*!
	* \brief Returns the allowed values for this attribut.
	*
	* This field records the Accession ID for the term used to describe the Illumination Type. A sub-classes of Light Microscopy term (http://purl.obolibrary.org/obo/FBbi_00000345) is recommended.
	*
	* \return The list of allowed values
	*/
	static const std::set<std::string>& getIlluminationTypeTermAcessionAllowedValues();

	/*!
	* \brief Sets the value of the ContrastMethod attribute.
	*
	* This field describes the technique used to achieve contrast for this Channel.
	*
	* \param value The value to set
	* \param validate If true, validates constraints on value. Default is true.
	*/
	void setContrastMethod(const Inscoper::NBO::ChannelContrastMethod_TypePtr& value, bool validate = true);

	/*!
	* \brief Returns the value of the ContrastMethod attribute.
	*
	* This field describes the technique used to achieve contrast for this Channel.
	*
	* \return The value of the attribute
	*/
	ChannelContrastMethod_TypePtr getContrastMethod() const;

	/*!
	* \brief Resets the ContrastMethod attribute to an unset state.
	*
	* This field describes the technique used to achieve contrast for this Channel.
	*/
	void resetContrastMethod();

	/*!
	* \brief Checks whether the optional ContrastMethod attribute is present.
	*
	* This field describes the technique used to achieve contrast for this Channel.
	*
	* \return true if the optional attribute has been set, false otherwise
	*/
	bool hasContrastMethod() const;

	/*!
	* \brief Sets the value of the Color attribute.
	*
	* This field records the Color used to render this Channel - encoded as RGBA. The default value is -1 corresponding #FFFFFFFF, so solid white (it is a signed 32 bit value).
	*
	* \param value The value to set
	* \param validate If true, validates constraints on value. Default is true.
	*/
	void setColor(const Inscoper::NBO::Color_TypePtr& value, bool validate = true);

	/*!
	* \brief Returns the value of the Color attribute.
	*
	* This field records the Color used to render this Channel - encoded as RGBA. The default value is -1 corresponding #FFFFFFFF, so solid white (it is a signed 32 bit value).
	*
	* \return The value of the attribute
	*/
	Color_TypePtr getColor() const;

	/*!
	* \brief Resets the Color attribute to an unset state.
	*
	* This field records the Color used to render this Channel - encoded as RGBA. The default value is -1 corresponding #FFFFFFFF, so solid white (it is a signed 32 bit value).
	*/
	void resetColor();

	/*!
	* \brief Checks whether the optional Color attribute is present.
	*
	* This field records the Color used to render this Channel - encoded as RGBA. The default value is -1 corresponding #FFFFFFFF, so solid white (it is a signed 32 bit value).
	*
	* \return true if the optional attribute has been set, false otherwise
	*/
	bool hasColor() const;

	/*!
	* \brief Sets the value of the SamplesPerPixel attribute.
	*
	* This field is prevalently used for RGB Images and records the number of samples the detector takes to form each pixel value. [units:none]
	*
	* \param value The value to set
	* \param validate If true, validates constraints on value. Default is true.
	*/
	void setSamplesPerPixel(const Inscoper::NBO::PositiveInt_TypePtr& value, bool validate = true);

	/*!
	* \brief Returns the value of the SamplesPerPixel attribute.
	*
	* This field is prevalently used for RGB Images and records the number of samples the detector takes to form each pixel value. [units:none]
	*
	* \return The value of the attribute
	*/
	PositiveInt_TypePtr getSamplesPerPixel() const;

	/*!
	* \brief Resets the SamplesPerPixel attribute to an unset state.
	*
	* This field is prevalently used for RGB Images and records the number of samples the detector takes to form each pixel value. [units:none]
	*/
	void resetSamplesPerPixel();

	/*!
	* \brief Checks whether the optional SamplesPerPixel attribute is present.
	*
	* This field is prevalently used for RGB Images and records the number of samples the detector takes to form each pixel value. [units:none]
	*
	* \return true if the optional attribute has been set, false otherwise
	*/
	bool hasSamplesPerPixel() const;

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

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

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

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

	/*!
	* \brief Sets the value of the LightPath element.
	*
	* 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 setLightPath(const Inscoper::NBO::LightPathPtr& value, bool validate = true);

	/*!
	* \brief Returns the value of the LightPath element.
	*
	* No description available in the XSD standard.
	*
	* \return The value of the element
	*/
	Inscoper::NBO::LightPathPtr getLightPath() const
;
	/*!
	* \brief Resets the LightPath element to an unset state.
	*
	* No description available in the XSD standard.
	*/
	void resetLightPath();

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

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

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

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

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

	/*!
	* \brief Sets the value of the AnnotationRef element.
	*
	* This is a simple multi-line comment or annotation describing this component.
	*
	* \param value The value to set
	* \param validate If true, validates constraints on value. Default is true.
	*/
	void setAnnotationRef(const Inscoper::NBO::AnnotationRefPtr& value, bool validate = true);

	/*!
	* \brief Returns the value of the AnnotationRef element.
	*
	* This is a simple multi-line comment or annotation describing this component.
	*
	* \return The value of the element
	*/
	Inscoper::NBO::AnnotationRefPtr getAnnotationRef() const;

	/*!
	* \brief Resets the AnnotationRef element to an unset state.
	*
	* This is a simple multi-line comment or annotation describing this component.
	*/
	void resetAnnotationRef();

	/*!
	* \brief Checks whether the optional AnnotationRef element is present.
	*
	* This is a simple multi-line comment or annotation describing this component.
	*
	* \return true if the optional attribute has been set, false otherwise
	*/
	bool hasAnnotationRef() const;


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

	ChannelID_TypePtr ID = nullptr; // Required attribute
	Denomination_TypePtr Name = nullptr; // Required attribute
	ImagingMethodList_TypePtr IlluminationType = nullptr; // Required attribute
    std::optional<std::string> IlluminationTypeTermAcession; // Optional attribute
    static const std::set<std::string> IlluminationTypeTermAcessionAllowedValues;
	ChannelContrastMethod_TypePtr ContrastMethod = nullptr; // Required attribute
	Color_TypePtr Color = nullptr; // Optional attribute
	PositiveInt_TypePtr SamplesPerPixel = nullptr; // Optional attribute
    std::vector<Inscoper::NBO::FluorophorePtr> Fluorophore_List;
    Inscoper::NBO::LightPathPtr LightPath = nullptr;
    std::vector<Inscoper::NBO::ExcitationCalibrationPtr> ExcitationCalibration_List;
    Inscoper::NBO::AnnotationRefPtr AnnotationRef = nullptr;
};

/*! Shared pointer for Channel*/
typedef std::shared_ptr<Channel> ChannelPtr;

} // namespace Inscoper::NBO

#endif // CHANNEL_HPP_INCLUDED