#ifndef CAMERA_TYPE_HPP_INCLUDED
#define CAMERA_TYPE_HPP_INCLUDED

#include <iostream>
#include <memory>
#include <optional>
#include <set>
#include <string>
#include <vector>
#include <NBO/NBO/CameraIllumination_Type.h>
#include <NBO/NBO/ColorMode_Type.h>
#include <NBO/NBO/Detector_Type.h>
#include <NBO/NBO/UnitsElectricCharge_Type.h>
#include <NBO/NBO/UnitsFrequency_Type.h>
#include <NBO/NBO/UnitsLength_Type.h>
#include <NBO/NBO/UnitsTime_Type.h>
#include <NBO/NBO/ENBOType.h>
#include <NBO/NBOGlobal.h>
#include <NBO/Shared/Base/NBOBaseClass.h>


namespace Inscoper::NBO {

/*!
* \brief Represents the XML complex type Camera.
*
* This element describes a Camera available for this Instrument. A Camera is a device that converts optical brightness into an electrical signal using a grid of pixel sensor unit cells and then reproduces an image of the specimen. An Instrument may have more than one camera of different types, such as traditional CCD, EMCCD, Intensified EMCCD, sCMOS, or Analog Video.
*/
class NBO_EXPORT Camera_Type : public Detector_Type {

public:
	
	Camera_Type();
	~Camera_Type();

	/*!
	* \brief Cast a NBOBaseClass to a Camera_Type.
	*
	* \param base The base class to cast
	* \return The casted element, or nullptr if the cast fails
	*/
	static std::shared_ptr<Camera_Type> fromBase(NBOBaseClassPtr base);

	/*!
	* \brief Returns the class type name.
	*
	* \return The class type name
	*/
	virtual 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 ArrayWidth attribute.
	*
	* This field records the Width of this Camera chip or sensor area, expressed in Pixel.
	*
	* \param value The value to set
	* \param validate If true, validates constraints on value. Default is true.
	*/
	void setArrayWidth(const long long& value, bool validate = true);

	/*!
	* \brief Returns the value of the ArrayWidth attribute.
	*
	* This field records the Width of this Camera chip or sensor area, expressed in Pixel.
	*
	* \return The value of the attribute
	*/
	long long getArrayWidth() const;

	/*!
	* \brief Resets the ArrayWidth attribute to an unset state.
	*
	* This field records the Width of this Camera chip or sensor area, expressed in Pixel.
	*/
	void resetArrayWidth();

	/*!
	* \brief Checks whether the ArrayWidth attribute is present.
	*
	* This field records the Width of this Camera chip or sensor area, expressed in Pixel.
	*
	* \return true if the attribute has been set, false otherwise
	*/
	bool hasArrayWidth() const;

	/*!
	* \brief Sets the value of the ArrayHeight attribute.
	*
	* This field records the Height of this Camera chip or sensor area, expressed in Pixel.
	*
	* \param value The value to set
	* \param validate If true, validates constraints on value. Default is true.
	*/
	void setArrayHeight(const long long& value, bool validate = true);

	/*!
	* \brief Returns the value of the ArrayHeight attribute.
	*
	* This field records the Height of this Camera chip or sensor area, expressed in Pixel.
	*
	* \return The value of the attribute
	*/
	long long getArrayHeight() const;

	/*!
	* \brief Resets the ArrayHeight attribute to an unset state.
	*
	* This field records the Height of this Camera chip or sensor area, expressed in Pixel.
	*/
	void resetArrayHeight();

	/*!
	* \brief Checks whether the ArrayHeight attribute is present.
	*
	* This field records the Height of this Camera chip or sensor area, expressed in Pixel.
	*
	* \return true if the attribute has been set, false otherwise
	*/
	bool hasArrayHeight() const;

	/*!
	* \brief Sets the value of the PixelWidth attribute.
	*
	* This field records the Physical Width of each Camera Pixel.
	*
	* \param value The value to set
	* \param validate If true, validates constraints on value. Default is true.
	*/
	void setPixelWidth(const float& value, bool validate = true);

	/*!
	* \brief Returns the value of the PixelWidth attribute.
	*
	* This field records the Physical Width of each Camera Pixel.
	*
	* \return The value of the attribute
	*/
	float getPixelWidth() const;

	/*!
	* \brief Resets the PixelWidth attribute to an unset state.
	*
	* This field records the Physical Width of each Camera Pixel.
	*/
	void resetPixelWidth();

	/*!
	* \brief Checks whether the PixelWidth attribute is present.
	*
	* This field records the Physical Width of each Camera Pixel.
	*
	* \return true if the attribute has been set, false otherwise
	*/
	bool hasPixelWidth() const;

	/*!
	* \brief Sets the value of the PixelWidthUnit 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 setPixelWidthUnit(const Inscoper::NBO::UnitsLength_TypePtr& value, bool validate = true);

	/*!
	* \brief Returns the value of the PixelWidthUnit attribute.
	*
	* No description available in the XSD standard.
	*
	* \return The value of the attribute
	*/
	UnitsLength_TypePtr getPixelWidthUnit() const;

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

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

	/*!
	* \brief Sets the value of the PixelHeight attribute.
	*
	* This field records the Physical Height of each Camera Pixel.
	*
	* \param value The value to set
	* \param validate If true, validates constraints on value. Default is true.
	*/
	void setPixelHeight(const float& value, bool validate = true);

	/*!
	* \brief Returns the value of the PixelHeight attribute.
	*
	* This field records the Physical Height of each Camera Pixel.
	*
	* \return The value of the attribute
	*/
	float getPixelHeight() const;

	/*!
	* \brief Resets the PixelHeight attribute to an unset state.
	*
	* This field records the Physical Height of each Camera Pixel.
	*/
	void resetPixelHeight();

	/*!
	* \brief Checks whether the PixelHeight attribute is present.
	*
	* This field records the Physical Height of each Camera Pixel.
	*
	* \return true if the attribute has been set, false otherwise
	*/
	bool hasPixelHeight() const;

	/*!
	* \brief Sets the value of the PixelHeightUnit 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 setPixelHeightUnit(const Inscoper::NBO::UnitsLength_TypePtr& value, bool validate = true);

	/*!
	* \brief Returns the value of the PixelHeightUnit attribute.
	*
	* No description available in the XSD standard.
	*
	* \return The value of the attribute
	*/
	UnitsLength_TypePtr getPixelHeightUnit() const;

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

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

	/*!
	* \brief Sets the value of the Illumination attribute.
	*
	* This field records the type of illumination the Camera chip receives.
	*
	* \param value The value to set
	* \param validate If true, validates constraints on value. Default is true.
	*/
	void setIllumination(const Inscoper::NBO::CameraIllumination_TypePtr& value, bool validate = true);

	/*!
	* \brief Returns the value of the Illumination attribute.
	*
	* This field records the type of illumination the Camera chip receives.
	*
	* \return The value of the attribute
	*/
	CameraIllumination_TypePtr getIllumination() const;

	/*!
	* \brief Resets the Illumination attribute to an unset state.
	*
	* This field records the type of illumination the Camera chip receives.
	*/
	void resetIllumination();

	/*!
	* \brief Checks whether the optional Illumination attribute is present.
	*
	* This field records the type of illumination the Camera chip receives.
	*
	* \return true if the optional attribute has been set, false otherwise
	*/
	bool hasIllumination() const;

	/*!
	* \brief Sets the value of the ManufacturerOffet attribute.
	*
	* This field reports the Camera Offset when it is pre-set by the Manufacturer. The Offset is an electronic baseline added to the output signal from the sensor to ensure that the displayed signal level is always a positive number of counts.
	*
	* \param value The value to set
	* \param validate If true, validates constraints on value. Default is true.
	*/
	void setManufacturerOffet(const float& value, bool validate = true);

	/*!
	* \brief Returns the value of the ManufacturerOffet attribute.
	*
	* This field reports the Camera Offset when it is pre-set by the Manufacturer. The Offset is an electronic baseline added to the output signal from the sensor to ensure that the displayed signal level is always a positive number of counts.
	*
	* \return The value of the attribute
	*/
	float getManufacturerOffet() const;

	/*!
	* \brief Resets the ManufacturerOffet attribute to an unset state.
	*
	* This field reports the Camera Offset when it is pre-set by the Manufacturer. The Offset is an electronic baseline added to the output signal from the sensor to ensure that the displayed signal level is always a positive number of counts.
	*/
	void resetManufacturerOffet();

	/*!
	* \brief Checks whether the ManufacturerOffet attribute is present.
	*
	* This field reports the Camera Offset when it is pre-set by the Manufacturer. The Offset is an electronic baseline added to the output signal from the sensor to ensure that the displayed signal level is always a positive number of counts.
	*
	* \return true if the attribute has been set, false otherwise
	*/
	bool hasManufacturerOffet() const;

	/*!
	* \brief Sets the value of the Color attribute.
	*
	* This field records whether this is a Color Camera and what type it is.
	*
	* \param value The value to set
	* \param validate If true, validates constraints on value. Default is true.
	*/
	void setColor(const Inscoper::NBO::ColorMode_TypePtr& value, bool validate = true);

	/*!
	* \brief Returns the value of the Color attribute.
	*
	* This field records whether this is a Color Camera and what type it is.
	*
	* \return The value of the attribute
	*/
	ColorMode_TypePtr getColor() const;

	/*!
	* \brief Resets the Color attribute to an unset state.
	*
	* This field records whether this is a Color Camera and what type it is.
	*/
	void resetColor();

	/*!
	* \brief Checks whether the optional Color attribute is present.
	*
	* This field records whether this is a Color Camera and what type it is.
	*
	* \return true if the optional attribute has been set, false otherwise
	*/
	bool hasColor() const;

	/*!
	* \brief Sets the value of the PixelWellCapacity attribute.
	*
	* This field records the maximum amount of charge each Pixel Well can hold, measured in electron counts.
	*
	* \param value The value to set
	* \param validate If true, validates constraints on value. Default is true.
	*/
	void setPixelWellCapacity(const long long& value, bool validate = true);

	/*!
	* \brief Returns the value of the PixelWellCapacity attribute.
	*
	* This field records the maximum amount of charge each Pixel Well can hold, measured in electron counts.
	*
	* \return The value of the attribute
	*/
	long long getPixelWellCapacity() const;

	/*!
	* \brief Resets the PixelWellCapacity attribute to an unset state.
	*
	* This field records the maximum amount of charge each Pixel Well can hold, measured in electron counts.
	*/
	void resetPixelWellCapacity();

	/*!
	* \brief Checks whether the PixelWellCapacity attribute is present.
	*
	* This field records the maximum amount of charge each Pixel Well can hold, measured in electron counts.
	*
	* \return true if the attribute has been set, false otherwise
	*/
	bool hasPixelWellCapacity() const;

	/*!
	* \brief Sets the value of the PixelWellCapacityUnit 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 setPixelWellCapacityUnit(const Inscoper::NBO::UnitsElectricCharge_TypePtr& value, bool validate = true);

	/*!
	* \brief Returns the value of the PixelWellCapacityUnit attribute.
	*
	* No description available in the XSD standard.
	*
	* \return The value of the attribute
	*/
	UnitsElectricCharge_TypePtr getPixelWellCapacityUnit() const;

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

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

	/*!
	* \brief Sets the value of the MaximumFrameRate attribute.
	*
	* This field records the maximal rate at which this Camera can acquire a single full-frame.
	*
	* \param value The value to set
	* \param validate If true, validates constraints on value. Default is true.
	*/
	void setMaximumFrameRate(const float& value, bool validate = true);

	/*!
	* \brief Returns the value of the MaximumFrameRate attribute.
	*
	* This field records the maximal rate at which this Camera can acquire a single full-frame.
	*
	* \return The value of the attribute
	*/
	float getMaximumFrameRate() const;

	/*!
	* \brief Resets the MaximumFrameRate attribute to an unset state.
	*
	* This field records the maximal rate at which this Camera can acquire a single full-frame.
	*/
	void resetMaximumFrameRate();

	/*!
	* \brief Checks whether the MaximumFrameRate attribute is present.
	*
	* This field records the maximal rate at which this Camera can acquire a single full-frame.
	*
	* \return true if the attribute has been set, false otherwise
	*/
	bool hasMaximumFrameRate() const;

	/*!
	* \brief Sets the value of the MaximumFrameRateUnit 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 setMaximumFrameRateUnit(const Inscoper::NBO::UnitsFrequency_TypePtr& value, bool validate = true);

	/*!
	* \brief Returns the value of the MaximumFrameRateUnit attribute.
	*
	* No description available in the XSD standard.
	*
	* \return The value of the attribute
	*/
	UnitsFrequency_TypePtr getMaximumFrameRateUnit() const;

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

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

	/*!
	* \brief Sets the value of the MaximumReadoutRate attribute.
	*
	* This field records the maximal Pixel Readout Rate allowed by this Camera.
	*
	* \param value The value to set
	* \param validate If true, validates constraints on value. Default is true.
	*/
	void setMaximumReadoutRate(const float& value, bool validate = true);

	/*!
	* \brief Returns the value of the MaximumReadoutRate attribute.
	*
	* This field records the maximal Pixel Readout Rate allowed by this Camera.
	*
	* \return The value of the attribute
	*/
	float getMaximumReadoutRate() const;

	/*!
	* \brief Resets the MaximumReadoutRate attribute to an unset state.
	*
	* This field records the maximal Pixel Readout Rate allowed by this Camera.
	*/
	void resetMaximumReadoutRate();

	/*!
	* \brief Checks whether the MaximumReadoutRate attribute is present.
	*
	* This field records the maximal Pixel Readout Rate allowed by this Camera.
	*
	* \return true if the attribute has been set, false otherwise
	*/
	bool hasMaximumReadoutRate() const;

	/*!
	* \brief Sets the value of the MaximumReadoutRateUnit 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 setMaximumReadoutRateUnit(const Inscoper::NBO::UnitsFrequency_TypePtr& value, bool validate = true);

	/*!
	* \brief Returns the value of the MaximumReadoutRateUnit attribute.
	*
	* No description available in the XSD standard.
	*
	* \return The value of the attribute
	*/
	UnitsFrequency_TypePtr getMaximumReadoutRateUnit() const;

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

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

	/*!
	* \brief Sets the value of the VerticalClockSpeed attribute.
	*
	* This field records the maximal speed at which each vertical column of pixels in the camera chip can be shifted down and read. 
	*
	* \param value The value to set
	* \param validate If true, validates constraints on value. Default is true.
	*/
	void setVerticalClockSpeed(const float& value, bool validate = true);

	/*!
	* \brief Returns the value of the VerticalClockSpeed attribute.
	*
	* This field records the maximal speed at which each vertical column of pixels in the camera chip can be shifted down and read. 
	*
	* \return The value of the attribute
	*/
	float getVerticalClockSpeed() const;

	/*!
	* \brief Resets the VerticalClockSpeed attribute to an unset state.
	*
	* This field records the maximal speed at which each vertical column of pixels in the camera chip can be shifted down and read. 
	*/
	void resetVerticalClockSpeed();

	/*!
	* \brief Checks whether the VerticalClockSpeed attribute is present.
	*
	* This field records the maximal speed at which each vertical column of pixels in the camera chip can be shifted down and read. 
	*
	* \return true if the attribute has been set, false otherwise
	*/
	bool hasVerticalClockSpeed() const;

	/*!
	* \brief Sets the value of the VerticalClockSpeedUnit 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 setVerticalClockSpeedUnit(const Inscoper::NBO::UnitsTime_TypePtr& value, bool validate = true);

	/*!
	* \brief Returns the value of the VerticalClockSpeedUnit attribute.
	*
	* No description available in the XSD standard.
	*
	* \return The value of the attribute
	*/
	UnitsTime_TypePtr getVerticalClockSpeedUnit() const;

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

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


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

    std::optional<long long> ArrayWidth; // Optional attribute
    std::optional<long long> ArrayHeight; // Optional attribute
    std::optional<float> PixelWidth; // Required attribute
	UnitsLength_TypePtr PixelWidthUnit = nullptr; // Optional attribute
    std::optional<float> PixelHeight; // Required attribute
	UnitsLength_TypePtr PixelHeightUnit = nullptr; // Optional attribute
	CameraIllumination_TypePtr Illumination = nullptr; // Required attribute
    std::optional<float> ManufacturerOffet; // Optional attribute
	ColorMode_TypePtr Color = nullptr; // Optional attribute
    std::optional<long long> PixelWellCapacity; // Required attribute
	UnitsElectricCharge_TypePtr PixelWellCapacityUnit = nullptr; // Optional attribute
    std::optional<float> MaximumFrameRate; // Required attribute
	UnitsFrequency_TypePtr MaximumFrameRateUnit = nullptr; // Optional attribute
    std::optional<float> MaximumReadoutRate; // Required attribute
	UnitsFrequency_TypePtr MaximumReadoutRateUnit = nullptr; // Optional attribute
    std::optional<float> VerticalClockSpeed; // Optional attribute
	UnitsTime_TypePtr VerticalClockSpeedUnit = nullptr; // Optional attribute
};

/*! Shared pointer for Camera_Type*/
typedef std::shared_ptr<Camera_Type> Camera_TypePtr;

} // namespace Inscoper::NBO

#endif // CAMERA_TYPE_HPP_INCLUDED