#pragma once

#include <d3d9.h>
#include <d3dx9.h>
#include <dxerr.h>
#include <vector>

/// <summary>
/// Enumerationsstruktur für Parametertypen
/// </summary>
struct ShaderParameterType
{
	/// <summary>
	/// Enumeration für Parametertypen
	/// </summary>
	enum Enumeration
	{
		/// <summary>
		/// einfacher float Wert
		/// </summary>
		Float,

		/// <summary>
		/// 2D float Vektor
		/// </summary>
		Float2,

		/// <summary>
		/// 3D float Vektor
		/// </summary>
		Float3,

		/// <summary>
		/// 4D float Vektor
		/// </summary>
		Float4,

		/// <summary>
		/// 4D float Vektor Array
		/// </summary>
		Float4Array,

		/// <summary>
		/// 3D float Vektor Array
		/// </summary>
		Float3Array,

		/// <summary>
		/// 3D float Vektor Array
		/// </summary>
		Float2Array,

		/// <summary>
		/// float Array
		/// </summary>
		FloatArray,

		/// <summary>
		/// int Array
		/// </summary>
		IntArray,

		/// <summary>
		/// Texture1D (Die interne Verwendung aller Textur Typen ist identisch.)
		/// </summary>
		Texture1D,

		/// <summary>
		/// Texture3D (Die interne Verwendung aller Textur Typen ist identisch.)
		/// </summary>
		Texture2D,

		/// <summary>
		/// Texture3D (Die interne Verwendung aller Textur Typen ist identisch.)
		/// </summary>
		Texture3D,

		/// <summary>
		/// TextureCube (Die interne Verwendung aller Textur Typen ist identisch.)
		/// </summary>
		TextureCube,

		/// <summary>
		/// Matrix Wertetabelle
		/// </summary>
		Matrix,

		/// <summary>
		/// einfacher int Wert
		/// </summary>
		Int,

		/// <summary>
		/// bool int Wert
		/// </summary>
		Bool,

		/// <summary>
		/// einfacher String Wert
		/// </summary>
		String,

		/// <summary>
		/// kein Typ (Nicht benutzen, nur für interne Verwendung!)
		/// </summary>
		Void,

		/// <summary>
		/// eine Struktur (Nicht benutzen, nur für interne Verwendung!)
		/// </summary>
		Struct,

		/// <summary>
		/// unbekannter Typ (Nicht benutzen, nur für interne Verwendung!)
		/// </summary>
		Unknown
	};
};

/// <summary>
/// Der einzelne Shader Parameter
/// </summary>
/*!
*  \include ShaderParameter.cpp
*/
struct IShaderParameter
{
	/// <summary>
	/// Der virtuelle Destruktor des Shaders.
	/// </summary>
	virtual ~IShaderParameter() {}

	/// <summary>
	///	Gibt den benutzten Parametertyp zurück.
	/// </summary>
	/// <returns>Den Parametertyp.</returns>
	virtual ShaderParameterType::Enumeration get_Type() const = 0;

	/// <summary>
	///	Setzt den Parameterwert und aktualisiert den dazugehörigen Effekt.
	/// </summary>
	/// <param name="inValue">Der neue Parameterwert.</param>
	virtual void set_Float4(const D3DXVECTOR4& inValue) = 0;

	/// <summary>
	///	Gibt den benutzten Parameterwert zurück. Sollte man nicht sicher sein welchen typ der Parameter angehört sollte man dies immer zuerst überprüfen.
	/// </summary>
	/// <returns>Den Parameterwert.</returns>
	virtual D3DXVECTOR4 get_Float4() const = 0;

	/// <summary>
	///	Setzt den Parameterwert und aktualisiert den dazugehörigen Effekt.
	/// </summary>
	/// <param name="inValue">Der neue Parameterwert.</param>
	virtual void set_Float3(const D3DXVECTOR3& inValue) = 0;

	/// <summary>
	///	Gibt den benutzten Parameterwert zurück. Sollte man nicht sicher sein welchen typ der Parameter angehört sollte man dies immer zuerst überprüfen.
	/// </summary>
	/// <returns>Den Parameterwert.</returns>
	virtual D3DXVECTOR3 get_Float3() const = 0;

	/// <summary>
	///	Setzt den Parameterwert und aktualisiert den dazugehörigen Effekt.
	/// </summary>
	/// <param name="inValue">Der neue Parameterwert.</param>
	virtual void set_Float2(const D3DXVECTOR2& inValue) = 0;

	/// <summary>
	///	Gibt den benutzten Parameterwert zurück. Sollte man nicht sicher sein welchen typ der Parameter angehört sollte man dies immer zuerst überprüfen.
	/// </summary>
	/// <returns>Den Parameterwert.</returns>
	virtual D3DXVECTOR2 get_Float2() const = 0;

	/// <summary>
	///	Setzt den Parameterwert und aktualisiert den dazugehörigen Effekt.
	/// </summary>
	/// <param name="inValue">Der neue Parameterwert.</param>
	virtual void set_Float(float inValue) = 0;

	/// <summary>
	///	Gibt den benutzten Parameterwert zurück. Sollte man nicht sicher sein welchen typ der Parameter angehört sollte man dies immer zuerst überprüfen.
	/// </summary>
	/// <returns>Den Parameterwert.</returns>
	virtual float get_Float() const = 0;

	/// <summary>
	///	Setzt den Parameterwert und aktualisiert den dazugehörigen Effekt.
	/// </summary>
	/// <param name="inValue">Der neue Parameterwert.</param>
	virtual void set_Int(int inValue) = 0;

	/// <summary>
	///	Gibt den benutzten Parameterwert zurück. Sollte man nicht sicher sein welchen typ der Parameter angehört sollte man dies immer zuerst überprüfen.
	/// </summary>
	/// <returns>Den Parameterwert.</returns>
	virtual int get_Int() const = 0;

	/// <summary>
	///	Setzt den Parameterwert und aktualisiert den dazugehörigen Effekt.
	/// </summary>
	/// <param name="inValue">Der neue Parameterwert.</param>
	virtual void set_Bool(bool inValue) = 0;

	/// <summary>
	///	Gibt den benutzten Parameterwert zurück. Sollte man nicht sicher sein welchen typ der Parameter angehört sollte man dies immer zuerst überprüfen.
	/// </summary>
	/// <returns>Den Parameterwert.</returns>
	virtual bool get_Bool() const = 0;

	/// <summary>
	///	Setzt den Parameterwert und aktualisiert den dazugehörigen Effekt.
	/// </summary>
	/// <param name="inValue">Der neue Parameterwert.</param>
	virtual void set_String(const std::string& inValue) = 0;

	/// <summary>
	///	Gibt den benutzten Parameterwert zurück. Sollte man nicht sicher sein welchen typ der Parameter angehört sollte man dies immer zuerst überprüfen.
	/// </summary>
	/// <returns>Den Parameterwert.</returns>
	virtual std::string get_String() const = 0;

	/// <summary>
	///	Setzt den Parameterwert und aktualisiert den dazugehörigen Effekt.
	/// </summary>
	/// <param name="inValue">Der neue Parameterwert.</param>
	virtual void set_Matrix(const D3DXMATRIX& inValue) = 0;

	/// <summary>
	///	Gibt den benutzten Parameterwert zurück. Sollte man nicht sicher sein welchen typ der Parameter angehört sollte man dies immer zuerst überprüfen.
	/// </summary>
	/// <returns>Den Parameterwert.</returns>
	virtual D3DXMATRIX get_Matrix() const = 0;

	/// <summary>
	///	Setzt den Parameterwert und aktualisiert den dazugehörigen Effekt.
	/// </summary>
	/// <param name="inValue">Der neue Parameterwert.</param>
	virtual void set_Texture1D(IDirect3DBaseTexture9* inValue) = 0;

	/// <summary>
	///	Gibt den benutzten Parameterwert zurück. Sollte man nicht sicher sein welchen typ der Parameter angehört sollte man dies immer zuerst überprüfen.
	/// </summary>
	/// <returns>Den Parameterwert.</returns>
	virtual IDirect3DBaseTexture9* get_Texture1D() const = 0;

	/// <summary>
	///	Setzt den Parameterwert und aktualisiert den dazugehörigen Effekt.
	/// </summary>
	/// <param name="inValue">Der neue Parameterwert.</param>
	virtual void set_Texture2D(IDirect3DBaseTexture9* inValue) = 0;

	/// <summary>
	///	Gibt den benutzten Parameterwert zurück. Sollte man nicht sicher sein welchen typ der Parameter angehört sollte man dies immer zuerst überprüfen.
	/// </summary>
	/// <returns>Den Parameterwert.</returns>
	virtual IDirect3DBaseTexture9* get_Texture2D() const = 0;

	/// <summary>
	///	Setzt den Parameterwert und aktualisiert den dazugehörigen Effekt.
	/// </summary>
	/// <param name="inValue">Der neue Parameterwert.</param>
	virtual void set_Texture3D(IDirect3DBaseTexture9* inValue) = 0;

	/// <summary>
	///	Gibt den benutzten Parameterwert zurück. Sollte man nicht sicher sein welchen typ der Parameter angehört sollte man dies immer zuerst überprüfen.
	/// </summary>
	/// <returns>Den Parameterwert.</returns>
	virtual IDirect3DBaseTexture9* get_Texture3D() const = 0;

	/// <summary>
	///	Setzt den Parameterwert und aktualisiert den dazugehörigen Effekt.
	/// </summary>
	/// <param name="inValue">Der neue Parameterwert.</param>
	virtual void set_TextureCube(IDirect3DBaseTexture9* inValue) = 0;

	/// <summary>
	///	Gibt den benutzten Parameterwert zurück. Sollte man nicht sicher sein welchen typ der Parameter angehört sollte man dies immer zuerst überprüfen.
	/// </summary>
	/// <returns>Den Parameterwert.</returns>
	virtual IDirect3DBaseTexture9* get_TextureCube() const = 0;

	/// <summary>
	///	Setzt den Parameterwert und aktualisiert den dazugehörigen Effekt.
	/// </summary>
	/// <param name="inValue">Der neue Parameterwert.</param>
	virtual void set_Float4Array(const std::vector<D3DXVECTOR4>& inValue) = 0;

	/// <summary>
	///	Gibt den benutzten Parameterwert zurück. Sollte man nicht sicher sein welchen typ der Parameter angehört sollte man dies immer zuerst überprüfen.
	/// </summary>
	/// <returns>Den Parameterwert.</returns>
	virtual std::vector<D3DXVECTOR4> get_Float4Array() const = 0;

	/// <summary>
	///	Setzt den Parameterwert und aktualisiert den dazugehörigen Effekt.
	/// </summary>
	/// <param name="inValue">Der neue Parameterwert.</param>
	virtual void set_Float3Array(const std::vector<D3DXVECTOR3>& inValue) = 0;

	/// <summary>
	///	Gibt den benutzten Parameterwert zurück. Sollte man nicht sicher sein welchen typ der Parameter angehört sollte man dies immer zuerst überprüfen.
	/// </summary>
	/// <returns>Den Parameterwert.</returns>
	virtual std::vector<D3DXVECTOR3> get_Float3Array() const = 0;

	/// <summary>
	///	Setzt den Parameterwert und aktualisiert den dazugehörigen Effekt.
	/// </summary>
	/// <param name="inValue">Der neue Parameterwert.</param>
	virtual void set_Float2Array(const std::vector<D3DXVECTOR2>& inValue) = 0;

	/// <summary>
	///	Gibt den benutzten Parameterwert zurück. Sollte man nicht sicher sein welchen typ der Parameter angehört sollte man dies immer zuerst überprüfen.
	/// </summary>
	/// <returns>Den Parameterwert.</returns>
	virtual std::vector<D3DXVECTOR2> get_Float2Array() const = 0;

	/// <summary>
	///	Setzt den Parameterwert und aktualisiert den dazugehörigen Effekt.
	/// </summary>
	/// <param name="inValue">Der neue Parameterwert.</param>
	virtual void set_FloatArray(const std::vector<float>& inValue) = 0;

	/// <summary>
	///	Gibt den benutzten Parameterwert zurück. Sollte man nicht sicher sein welchen typ der Parameter angehört sollte man dies immer zuerst überprüfen.
	/// </summary>
	/// <returns>Den Parameterwert.</returns>
	virtual std::vector<float> get_FloatArray() const = 0;

	/// <summary>
	///	Setzt den Parameterwert und aktualisiert den dazugehörigen Effekt.
	/// </summary>
	/// <param name="inValue">Der neue Parameterwert.</param>
	virtual void set_IntArray(const std::vector<int>& inValue) = 0;

	/// <summary>
	///	Gibt den benutzten Parameterwert zurück. Sollte man nicht sicher sein welchen typ der Parameter angehört sollte man dies immer zuerst überprüfen.
	/// </summary>
	/// <returns>Den Parameterwert.</returns>
	virtual std::vector<int> get_IntArray() const = 0;


	/// <summary>
	///	Gibt die Länge des Arrays zurück welcher für diesen Parameter verwendet wurde, oder 0 für nicht Arrayparameter.
	/// </summary>
	/// <returns>Die Länge des Parameterarrays.</returns>
	virtual unsigned int get_ArrayLength() const = 0;

	/// <summary>
	///	Gibt den Namen des Parameters zurück.
	/// </summary>
	/// <returns>Den Namen des Parameters.</returns>
	virtual const std::string& get_Name() const = 0;

	/// <summary>
	///	Überprüft ob der Parameter einsatzbereit ist oder ob Fehler aufgetreten sind.
	/// </summary>
	/// <returns>True für einen funktionsfähigen Parameter, false für einen Fehlerhaften.</returns>
	virtual bool isValid() const = 0;

	/// <summary>
	///	Aktualisiert den Parameter anhand des neuen DX9 Effektes
	/// </summary>
	/// <param name="inEffect">Der neue DX9 Effekt.</param>
	virtual void Refresh(ID3DXEffect* inEffect) = 0;

	/// <summary>
	///	Gibt den verwendeten Parameterhandle zurück.
	/// </summary>
	/// <returns>Den Parameterhandle.</returns>
	virtual D3DXHANDLE get_Handle() const = 0;
};
