//// THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF
//// ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO
//// THE IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A
//// PARTICULAR PURPOSE.
////
//// Copyright (c) Microsoft Corporation. All rights reserved

#pragma once

#include "BasicMath.h"
#include <vector>
#include <map>
#include <memory>
#include <list>

namespace BasicSprites
{
    namespace Parameters
    {
        // The index buffer format for feature-level 9.1 devices may only be 16 bits.
        // With 4 vertices per sprite, this allows a maximum of (1 << 16) / 4 sprites.
        static unsigned int MaximumCapacityCompatible = (1 << 16) / 4;
    }

    enum class PositionUnits
    {
        DIPs,         // Interpret position as device-independent pixel values.
        Pixels,       // Interpret position as pixel values.
        Normalized,   // Interpret position as a fraction of the render target dimensions.
        UniformWidth, // Interpret position as a fraction of the render target width.
        UniformHeight // Interpret position as a fraction of the render target height.
    };

    enum class SizeUnits
    {
        DIPs,      // Interpret size as device-independent pixel values.
        Pixels,    // Interpret size as pixel values.
        Normalized // Interpret size as a multiplier of the pixel size of the sprite.
    };

    enum class BlendMode
    {
        Alpha,   // Use alpha blending (out = old * (1 - new.a) + new * new.a).
        Additive // Use additive blending (out = old + new * new.a).
    };

	struct SpriteDrawer
	{
	public:
		virtual void Initialize(
			ID3D11Device1* d3dDevice,
			int capacity
			) = 0;

		virtual void AddTexture(
			 ID3D11Texture2D* texture,float2 textureCellSize ) = 0;

		virtual void RemoveTexture(
			 ID3D11Texture2D* texture
			) = 0;

		virtual void Begin() = 0;

		virtual void End() = 0;

		virtual void Draw(
			 ID3D11Texture2D* texture,
			 float4 position,
			 PositionUnits positionUnits,
			 float2 size,
			 SizeUnits sizeUnits,
			 float4 color,
			 float rotation,
			 BlendMode blendMode,
			 float2 textureCellOffset
			) = 0;
	};

	ref class SpriteBatch 
    {
    internal:
        SpriteBatch();
        void Initialize(
            _In_ ID3D11Device1* d3dDevice,
            _In_ int capacity
            );
        void AddTexture(
            _In_ ID3D11Texture2D* texture,float2 textureCellSize
            );
        void RemoveTexture(
            _In_ ID3D11Texture2D* texture
            );
        void Begin();
        void End();
        void Draw(
            _In_ ID3D11Texture2D* texture,
            _In_ float4 position,
            _In_ PositionUnits positionUnits
            );
        void Draw(
            _In_ ID3D11Texture2D* texture,
            _In_ float4 position,
            _In_ PositionUnits positionUnits,
            _In_ float2 size,
            _In_ SizeUnits sizeUnits
            );
        void Draw(
            _In_ ID3D11Texture2D* texture,
            _In_ float4 position,
            _In_ PositionUnits positionUnits,
            _In_ float2 size,
            _In_ SizeUnits sizeUnits,
            _In_ float4 color
            );
        void Draw(
            _In_ ID3D11Texture2D* texture,
            _In_ float4 position,
            _In_ PositionUnits positionUnits,
            _In_ float2 size,
            _In_ SizeUnits sizeUnits,
            _In_ float4 color,
            _In_ float rotation
            );
        void Draw(
            _In_ ID3D11Texture2D* texture,
            _In_ float4 position,
            _In_ PositionUnits positionUnits,
            _In_ float2 size,
            _In_ SizeUnits sizeUnits,
            _In_ float4 color,
            _In_ float rotation,
            _In_ BlendMode blendMode
            );

		void Draw(
            _In_ ID3D11Texture2D* texture,
            _In_ float4 position,
            _In_ PositionUnits positionUnits,
            _In_ float2 size,
            _In_ SizeUnits sizeUnits,
            _In_ float4 color,
            _In_ float rotation,
            _In_ BlendMode blendMode,
			_In_ float2 textureOffset
			);

    private:
		std::unique_ptr<SpriteDrawer> drawer_;
    };
}
