#pragma once

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

#include "IShaderParameter.h"
struct IAnnotationHandler;
struct ISemanticHandler;
struct ICallbackHandler;


/// <summary>
/// Enumerationsstruktur für Pass Rückgabewerte
/// </summary>
struct RenderPassReturnValue
{
	/// <summary>
	/// Enumeration für Pass Rückgabewerte
	/// </summary>
	enum Enumeration
	{
		/// <summary>
		/// Behandlung egal, RendeAndCallOnce wird aber bevorzugt.
		/// </summary>
		RenderAndCallOnceOrAgain,

		/// <summary>
		/// Behandlung soll ein weiteres mal durchgeführt werden, RenderAndCallOnce überlagert aber.
		/// </summary>
		RenderAndCallAgain,

		/// <summary>
		/// Behandlung soll nur dieses eine mal durchgeführt werden, RenderAndCallNot überlagert aber.
		/// </summary>
		RenderAndCallOnce,

		/// <summary>
		/// Behandlung soll abgebrochen und nicht weiter beachtet werden.
		/// </summary>
		RenderAndCallNot
	};
};

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

	/// <summary>
	///	Bereitet den Shader auf die Benutzung eines Passes vor.
	/// </summary>
	/// <param name="inPassNumber">Der Pass welcher benutzt werden soll.</param>
	/// <returns>Den Wunsch des Passes auf eine weitere Verfahrensweise mit dem Pass.</returns>
	virtual RenderPassReturnValue::Enumeration BeginPass(unsigned int inPassNumber) = 0;

	/// <summary>
	/// Beendet die Benutzung eines Passes.
	/// </summary>
	virtual void EndPass() = 0;

	/// <summary>
	///	Gibt die Anzehl der zur Verfügung stehenden Passes an.
	/// </summary>
	/// <returns>Die Anzahl der zur Verfügung stehenden Passes.</returns>
	virtual unsigned int get_PassCount() = 0;

	/// <summary>
	///	Startet die Benutzung dieses Shaders.
	/// </summary>
	/// <returns>Die Anzahl der zur Verfügung stehenden Passes.</returns>
	virtual unsigned int Begin() = 0;

	/// <summary>
	///	Beendet die Benutzung dieses Shaders.
	/// </summary>
	virtual void End() = 0;

	/// <summary>
	///	Gibt den Namen dieses Shaders zurück.
	/// </summary>
	/// <returns>Der Name dieses Shaders.</returns>
	virtual const std::string& get_Name() const = 0;

	/// <summary>
	///	Fügt einen Annotationhandler dem Annotationhandlerpool des Shaders hinzu. Annotationhandler welche nicht vom Shadersystem zugewiesen wurden können durch gleichnamige AnnotationHandler überschrieben werden.
	/// </summary>
	/// <param name="inAnnotationHandler">Ein Zeiger auf den Handler, der Besitz des Handlers obliegt bei Erfolg dem Shader.</param>
	/// <returns>True für Erfolg, false für Fehlschlag der Aktion.</returns>
	virtual bool AddAnnotationHandler(IAnnotationHandler* inAnnotationHandler) = 0;

	/// <summary>
	///	Entfernt einen Annotationhandler aus dem Annotationhandlerpool des Shaders. Annotationhandler welche übergeben werden, aber nicht im Besitz des Shaders sind werden nicht frei gegeben.
	/// </summary>
	/// <param name="inAnnotationHandler">Ein Zeiger auf den Handler.</param>
	/// <returns>True für Erfolg, false für Fehlschlag der Aktion.</returns>
	virtual bool RemoveAnnotationHandler(IAnnotationHandler* inAnnotationHandler) = 0;

	/// <summary>
	///	Entfernt einen Annotationhandler aus dem Annotationhandlerpool des Shaders mit den angegebenen Namen.
	/// </summary>
	/// <param name="inAnnotationHandlerName">Der Name des Annotationhandlers.</param>
	/// <returns>True für Erfolg, false für Fehlschlag der Aktion.</returns>
	virtual bool RemoveAnnotationHandler(const std::string& inAnnotationHandlerName) = 0;

	/// <summary>
	///	Sucht einen Annotationhandler aus dem Annotationhandlerpool des Shaders mit den angegebenen Namen.
	/// </summary>
	/// <param name="inAnnotationHandlerName">Der Name des Annotationhandlers.</param>
	/// <returns>Den gesuchten Annotationhandler oder NULL wenn der Handler nicht gefunden wurde.</returns>
	virtual IAnnotationHandler* get_AnnotationHandler(const std::string& inAnnotationHandlerName) const = 0;

	/// <summary>
	///	Fügt einen Callbackhandler dem Callbackhandlerpool des Shaders hinzu. Callbackhandler welche nicht vom Shadersystem zugewiesen wurden können durch gleichnamige CallbackHandler überschrieben werden.
	/// </summary>
	/// <param name="inCallbackHandler">Ein Zeiger auf den Handler, der Besitz des Handlers obliegt bei Erfolg dem Shader.</param>
	/// <returns>True für Erfolg, false für Fehlschlag der Aktion.</returns>
	virtual bool AddCallbackHandler(ICallbackHandler* inCallbackHandler) = 0;

	/// <summary>
	///	Entfernt einen Callbackhandler aus dem Callbackhandlerpool des Shaders. Callbackhandler welche übergeben werden, aber nicht im Besitz des Shaders sind werden nicht frei gegeben.
	/// </summary>
	/// <param name="inCallbackHandler">Ein Zeiger auf den Handler.</param>
	/// <returns>True für Erfolg, false für Fehlschlag der Aktion.</returns>
	virtual bool RemoveCallbackHandler(ICallbackHandler* inCallbackHandler) = 0;

	/// <summary>
	///	Entfernt einen Callbackhandler aus dem Callbackhandlerpool des Shaders mit den angegebenen Namen.
	/// </summary>
	/// <param name="inCallbackHandlerName">Der Name des Callbackhandlers.</param>
	/// <returns>True für Erfolg, false für Fehlschlag der Aktion.</returns>
	virtual bool RemoveCallbackHandler(const std::string& inCallbackHandlerName) = 0;

	/// <summary>
	///	Sucht einen Callbackhandler aus dem Callbackhandlerpool des Shaders mit den angegebenen Namen.
	/// </summary>
	/// <param name="inCallbackHandlerName">Der Name des Callbackhandlers.</param>
	/// <returns>Den gesuchten Annotationhandler oder NULL wenn der Handler nicht gefunden wurde.</returns>
	virtual ICallbackHandler* get_CallbackHandler(const std::string& inCallbackHandlerName) const = 0;

	/// <summary>
	///	Fügt einen Semantichandler dem Semantichandlerpool des Shaders hinzu. Semantichandler welche nicht vom Shadersystem zugewiesen wurden können durch gleichnamige SemanticHandler überschrieben werden.
	/// </summary>
	/// <param name="inSemanticHandler">Ein Zeiger auf den Handler, der Besitz des Handlers obliegt bei Erfolg dem Shader.</param>
	/// <returns>True für Erfolg, false für Fehlschlag der Aktion.</returns>
	virtual bool AddSemanticHandler(ISemanticHandler* inSemanticHandler) = 0;

	/// <summary>
	///	Entfernt einen Semantichandler aus dem Semantichandlerpool des Shaders. Semantichandler welche übergeben werden, aber nicht im Besitz des Shaders sind werden nicht frei gegeben.
	/// </summary>
	/// <param name="inSemanticHandler">Ein Zeiger auf den Handler.</param>
	/// <returns>True für Erfolg, false für Fehlschlag der Aktion.</returns>
	virtual bool RemoveSemanticHandler(ISemanticHandler* inSemanticHandler) = 0;

	/// <summary>
	///	Entfernt einen Semantichandler aus dem Semantichandlerpool des Shaders mit den angegebenen Namen.
	/// </summary>
	/// <param name="inSemanticHandlerName">Der Name des Semantichandlers.</param>
	/// <returns>True für Erfolg, false für Fehlschlag der Aktion.</returns>
	virtual bool RemoveSemanticHandler(const std::string& inSemanticHandlerName) = 0;

	/// <summary>
	///	Sucht einen Semantichandler aus dem Semantichandlerpool des Shaders mit den angegebenen Namen.
	/// </summary>
	/// <param name="inSemanticHandlerName">Der Name des Semantichandlers.</param>
	/// <returns>Den gesuchten Annotationhandler oder NULL wenn der Handler nicht gefunden wurde.</returns>
	virtual ISemanticHandler* get_SemanticHandler(const std::string& inSemanticHandlerName) const = 0;

	/// <summary>
	///	Sucht einen Shaderparameter anhand des angegebenen Parameternamens und wenn nötig anhand des angegebenen Parametertyps.
	/// </summary>
	/// <param name="inName">Der Name des Parameters.</param>
	/// <param name="inType">Der Typ des Parameters. Unknown für keine Beschränkung des Typs.</param>
	/// <returns>Den gesuchten Parameter oder NULL wenn kein passender Parameter gefunden wurde.</returns>
	virtual IShaderParameter* get_ParameterByName(const std::string& inName, ShaderParameterType::Enumeration inType=ShaderParameterType::Unknown) = 0;

	/// <summary>
	///	Sucht einen Shaderparameter anhand des angegebenen Semanticnamens und wenn nötig anhand des angegebenen Parametertyps.
	/// </summary>
	/// <param name="inName">Der Semanticname des Parameters.</param>
	/// <param name="inType">Der Typ des Parameters. Unknown für keine Beschränkung des Typs.</param>
	/// <returns>Den gesuchten Parameter oder NULL wenn kein passender Parameter gefunden wurde.</returns>
	virtual IShaderParameter* get_ParameterBySemantic(const std::string& inName, ShaderParameterType::Enumeration inType=ShaderParameterType::Unknown) = 0;

	/// <summary>
	///	Gibt eine Liste der bereits gesuchten Parameter des Shaders zurück.
	/// </summary>
	/// <returns>Die Liste der bereits gesuchten Parameter des Shaders.</returns>
	virtual const std::vector<IShaderParameter*>& get_ParameterList() const = 0;

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

	/// <summary>
	///	Gibt die Fehlermeldung des letzten Fehlers des Shaders zurück.
	/// </summary>
	/// <returns>Den Fehlerstring.</returns>
	virtual const std::string& get_ShaderErrors() const = 0;

	/// <summary>
	///	Aktualisiert den Shader anhand des neuen DX9 Devices
	/// </summary>
	/// <param name="inDevice">Das neue DX9 Device.</param>
	virtual void Refresh(IDirect3DDevice9* inDevice) = 0;

	/// <summary>
	///	Gibt den benutzten Effekt zurück.
	/// </summary>
	/// <returns>Der Effekt.</returns>
	virtual ID3DXEffect* get_Effect() = 0;
};
