#pragma once

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

#include "IParameter.h"
#include "IServiceLocator.h"


struct IDirect3D9BasePlugin
{
	virtual ~IDirect3D9BasePlugin() {}
	virtual void Initialize(IDirect3DDevice9* inDevice) = 0;
	virtual bool IsInitialized() const = 0;
	virtual void Deinitialize() = 0;

	virtual void Render() = 0;
	virtual void OnBeforeReset() = 0;
	virtual void OnAfterReset() = 0;

	virtual std::vector<IParameter*> get_ParameterList() const = 0;
	virtual IParameter* TryGetParameter(const GUID& ar_Guid) const = 0;
	virtual IParameter& GetParameter(const GUID& ar_Guid) const = 0;
	virtual void OnParameterHasChanged(IParameter& ar_Parameter) = 0;

	virtual void set_Active(bool ab_State) = 0;
	virtual bool get_Active() const = 0;
	virtual std::wstring get_Name() = 0;
	virtual std::wstring get_Description() = 0;

	virtual IServiceLocator& get_ServiceLocator() = 0;
};


typedef IDirect3D9BasePlugin* (*typeCreatePlugin)(IServiceLocator& ar_ServiceLocator);


class k_Direct3D9BasePlugin : public IDirect3D9BasePlugin
{
public:
	k_Direct3D9BasePlugin(IServiceLocator& ar_ServiceLocator, const std::wstring& as_Name, const std::wstring& as_Description)
		: mr_Device_(NULL)
		, mr_ServiceLocator(ar_ServiceLocator)
		, mb_Initialized(false)
		, mb_Active(false)
		, ms_Name(as_Name)
		, ms_Description(as_Description)
	{
	}

	virtual ~k_Direct3D9BasePlugin()
	{
		while (!mk_Parameters.empty())
		{
			delete mk_Parameters.front();
			mk_Parameters.erase(mk_Parameters.begin());
		}
	}

	virtual void Initialize(IDirect3DDevice9* ar_Device_)
	{
		mb_Initialized = ar_Device_ != NULL;
		mr_Device_ = ar_Device_;
	}

	virtual bool IsInitialized() const
	{
		return mb_Initialized;
	}

	virtual void Deinitialize()
	{
		mb_Initialized = false;
	}

	virtual std::vector<IParameter*> get_ParameterList() const
	{
		return mk_Parameters;
	}

	virtual IParameter* TryGetParameter(const GUID& ar_Guid) const
	{
		for (unsigned int i = 0; i < mk_Parameters.size(); ++i)
			if (mk_Parameters[i]->get_Id() == ar_Guid)
				return mk_Parameters[i];
		return NULL;
	}

	virtual IParameter& GetParameter(const GUID& ar_Guid) const
	{
		IParameter* lr_Parameter_ = this->TryGetParameter(ar_Guid);
		if (lr_Parameter_ == NULL)
			throw;
		return *lr_Parameter_;
	}

	virtual void OnParameterHasChanged(IParameter& ar_Parameter)
	{
	}

	virtual void set_Active(bool ab_State)
	{
		mb_Active = ab_State;
	}

	virtual bool get_Active() const
	{
		return mb_Active;
	}

	virtual std::wstring get_Name()
	{
		return ms_Name;
	}

	virtual std::wstring get_Description()
	{
		return ms_Description;
	}

	virtual IServiceLocator& get_ServiceLocator()
	{
		return mr_ServiceLocator;
	}

protected:
	bool mb_Initialized;
	bool mb_Active;
	IDirect3DDevice9* mr_Device_;
	IServiceLocator& mr_ServiceLocator;
	std::vector<IParameter*> mk_Parameters;
	std::wstring ms_Name;
	std::wstring ms_Description;
};
