#ifndef POCKELSCELL_HPP_INCLUDED
#define POCKELSCELL_HPP_INCLUDED

#include <iostream>
#include <memory>
#include <optional>
#include <set>
#include <string>
#include <vector>
#include <NBO/NBO/PockelsCellMaterial_Type.h>
#include <NBO/NBO/UnitsElectricPotential_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 PockelsCell.
*
* Pockels cells are the basic components of electro-optic modulators. A Pockels cell is a device consisting of an electro-optic crystal (with some electrodes attached to it) through which a light beam can propagate. The phase delay in the crystal (→ Pockels effect) can be modulated by applying a variable electric voltage. The Pockels cell thus acts as a voltage-controlled waveplate.
*/
class NBO_EXPORT PockelsCell : public NBOBaseClass {

public:
	
	PockelsCell();
	~PockelsCell();

	/*!
	* \brief Cast a NBOBaseClass to a PockelsCell.
	*
	* \param base The base class to cast
	* \return The casted element, or nullptr if the cast fails
	*/
	static std::shared_ptr<PockelsCell> 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 HalfWaveVoltage attribute.
	*
	* This field record the Voltage required for inducing a phase change equivalent to a half an optical wavelength. In an amplitude modulator, the applied voltage has to be changed by this value in order to go from the operation point with minimum transmission to that with maximum transmission. The HalfWaveVoltage can be referred to as, Uπ, Uλ/2 or Vλ/2.
	*
	* \param value The value to set
	* \param validate If true, validates constraints on value. Default is true.
	*/
	void setHalfWaveVoltage(const float& value, bool validate = true);

	/*!
	* \brief Returns the value of the HalfWaveVoltage attribute.
	*
	* This field record the Voltage required for inducing a phase change equivalent to a half an optical wavelength. In an amplitude modulator, the applied voltage has to be changed by this value in order to go from the operation point with minimum transmission to that with maximum transmission. The HalfWaveVoltage can be referred to as, Uπ, Uλ/2 or Vλ/2.
	*
	* \return The value of the attribute
	*/
	float getHalfWaveVoltage() const;

	/*!
	* \brief Resets the HalfWaveVoltage attribute to an unset state.
	*
	* This field record the Voltage required for inducing a phase change equivalent to a half an optical wavelength. In an amplitude modulator, the applied voltage has to be changed by this value in order to go from the operation point with minimum transmission to that with maximum transmission. The HalfWaveVoltage can be referred to as, Uπ, Uλ/2 or Vλ/2.
	*/
	void resetHalfWaveVoltage();

	/*!
	* \brief Checks whether the HalfWaveVoltage attribute is present.
	*
	* This field record the Voltage required for inducing a phase change equivalent to a half an optical wavelength. In an amplitude modulator, the applied voltage has to be changed by this value in order to go from the operation point with minimum transmission to that with maximum transmission. The HalfWaveVoltage can be referred to as, Uπ, Uλ/2 or Vλ/2.
	*
	* \return true if the attribute has been set, false otherwise
	*/
	bool hasHalfWaveVoltage() const;

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

	/*!
	* \brief Returns the value of the HalfWaveVoltageUnit attribute.
	*
	* No description available in the XSD standard.
	*
	* \return The value of the attribute
	*/
	UnitsElectricPotential_TypePtr getHalfWaveVoltageUnit() const;

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

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

	/*!
	* \brief Sets the value of the Material attribute.
	*
	* This field describes the nonlinear crystal materials used to contruct this Pockels cell.
	*
	* \param value The value to set
	* \param validate If true, validates constraints on value. Default is true.
	*/
	void setMaterial(const Inscoper::NBO::PockelsCellMaterial_TypePtr& value, bool validate = true);

	/*!
	* \brief Returns the value of the Material attribute.
	*
	* This field describes the nonlinear crystal materials used to contruct this Pockels cell.
	*
	* \return The value of the attribute
	*/
	PockelsCellMaterial_TypePtr getMaterial() const;

	/*!
	* \brief Resets the Material attribute to an unset state.
	*
	* This field describes the nonlinear crystal materials used to contruct this Pockels cell.
	*/
	void resetMaterial();

	/*!
	* \brief Checks whether the optional Material attribute is present.
	*
	* This field describes the nonlinear crystal materials used to contruct this Pockels cell.
	*
	* \return true if the optional attribute has been set, false otherwise
	*/
	bool hasMaterial() const;


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

    std::optional<float> HalfWaveVoltage; // Required attribute
	UnitsElectricPotential_TypePtr HalfWaveVoltageUnit = nullptr; // Required attribute
	PockelsCellMaterial_TypePtr Material = nullptr; // Optional attribute
};

/*! Shared pointer for PockelsCell*/
typedef std::shared_ptr<PockelsCell> PockelsCellPtr;

} // namespace Inscoper::NBO

#endif // POCKELSCELL_HPP_INCLUDED