#pragma once
#include "Gui/3D/Graphics.h"

namespace gui {

	class D3DSurface;
	class D3DPipeline;

	class D3DGraphics : public Graphics3D {
		STORM_CLASS;
	public:
		// Create.
		D3DGraphics(D3DSurface &surface, Nat id);

		// Before/after rendering.
		virtual void beforeRender();
		virtual Bool afterRender();

		// Fill the surface.
		virtual void STORM_FN fill(Color color);

		// Fill the depth buffer.
		virtual void STORM_FN clearDepth();

		/**
		 * Rendering parameters.
		 */
		class D3DParams : public Graphics3D::RenderParams {
			STORM_CLASS;
		public:
			friend class D3DGraphics;

			// Create.
			D3DParams(D3DGraphics *graphics) : graphics(graphics) {}

			// Bind vertex buffers.
			virtual void STORM_FN bind(Nat id, VertexBufferBase *buffer);

			// Bind index buffer.
			virtual void STORM_FN bind(IndexBufferBase *buffer);

			// Set primitive type.
			virtual void STORM_FN primitive(DrawPrimitive p);

			// Render.
			void STORM_FN done();

		private:
			// Current graphics object.
			D3DGraphics *graphics;

			// Pipeline.
			D3DPipeline *pipeline;

			// Number of primitives to draw. Initialized from binding a vertex buffer.
			Nat numVertices;

			// Number of buffers that are bound. Used to determine how to update 'numVertices'.
			Nat numBuffers;

			// Primitive type to draw.
			DrawPrimitive topology;

			// Should we use the index buffer?
			Bool indexed;

			// Clear the state here.
			void clear();
		};

		// Resource management.
		virtual void createResource(Resource3D *resource, void *&data, Resource3D::Cleanup &cleanup);
		virtual void updateResource(Resource3D *resource, void *data, const DirtyRange &dirty);

	protected:
		// Render a pipeline.
		virtual Graphics3D::RenderParams *STORM_FN beginRender(Pipeline *pipeline);

	private:
		// The surface itself.
		D3DSurface &surface;

		// Cached instance of rendering parameters, so that we can avoid allocations.
		D3DParams *renderParams;
	};

}
