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

#ifdef GUI_WIN32

namespace gui {

	/**
	 * Direct 3D surface.
	 */
	class D3DSurface : public Surface3D {
		friend class DXDevice;
	public:
		// Destroy.
		~D3DSurface();

		// Create a graphics object.
		virtual Graphics3D *createGraphics(Engine &e);

		// Resize.
		virtual void resize(Size size, Float scale);

		// Present.
		virtual PresentStatus present(bool waitForVSync);

		// Get the D3D device.
		ID3D10Device1 *dev() const { return d3d.v; }

		// Get the color view.
		ID3D10RenderTargetView *color() const { return renderTarget.v; }

		// Get the depth view.
		ID3D10DepthStencilView *depth() const { return depthStencil.v; }

		// Set the appropriate render targets on the device.
		void setTargets();

		// Prepare for grabbing the surface.
		virtual void prepareGrab(Size size, Float scale);

		// Grab the surface as an image.
		virtual Image *grabImage(Engine &e);

	private:
		// Create.
		D3DSurface(Size size, Float scale, DXDevice *device, Nat id,
				const ComPtr<ID3D10Device1> &d3d, const ComPtr<IDXGISwapChain> &swap);

		// ID for the device.
		Nat deviceId;

		// DX resources.
		DXDevice *device;
		ComPtr<IDXGISwapChain> swapChain;
		// Note: The D3D10Device object is *shared* betweens surfaces in this implementation.
		// Therefore, we need to be a bit careful about not making assumptions about state between
		// draw-calls. There might be a point to create a separate device for each surface at some
		// point in the future (D3D11 seems to have a ID3D11DeviceContext which does what we want).
		// The drawback is that we can't share resources betwee different surfaces, but we already
		// have mechanisms to handle it from the OpenGL requirements.
		ComPtr<ID3D10Device1> d3d;
		ComPtr<ID3D10RenderTargetView> renderTarget;

		// Depth buffer.
		ComPtr<ID3D10Texture2D> depthTexture;
		ComPtr<ID3D10DepthStencilView> depthStencil;

		// Surface used when grabbing an image.
		ComPtr<ID3D10Texture2D> grabSurface;

		// Create 'renderTarget'.
		void createTarget();

		// Create depth and stencil buffers.
		void createDepthStencil(ID3D10Texture2D *backBuffer);
	};

}

#endif
