using System;

using Microsoft.DirectX;
using Microsoft.DirectX.Direct3D;
using System.Drawing;

using Icarus.Graphics.Animation;

namespace Icarus.Renderer.Animation
{
	/// <summary>
	/// This is a single animation frame that is stored in such a format as
	/// to allow easy rendering with DirectX. If the bitmap passed in is larger than the maximum allowed texture size, the frame will be composited out of multiple pieces.
	/// </summary>
	public class D3DFrame : AbstractFrame
	{
		/// <summary>
		/// The textures that make up this frame.
		/// </summary>
		private Texture[,] m_Textures;

		/// <summary>
		/// Creates a texture from the frame. 
		/// </summary>
		public override bool initializeFromBitmap(Bitmap image) 
		{
			// Get the dimensions of the texture:
			int maxWidth = Direct3DSettings.Instance.MaximumTextureSize.Width;
			int maxHeight = Direct3DSettings.Instance.MaximumTextureSize.Height;

			Rectangle imageRectangle = new Rectangle(0, 0, image.Width, image.Height);
			Rectangle textureRectangle = new Rectangle(0, 0, 0, 0);

			// Cut the image up into textures of acceptable size:
			int columns = (int) Math.Ceiling(((double) image.Width) / ((double) maxWidth));
			int rows = (int) Math.Ceiling(((double) image.Height) / ((double) maxHeight));

			// Make the array of textures:
			m_Textures = new Texture[rows,columns];

			// Populate the array of textures:
			for (int r = 0; r < rows; r++)
			{
				textureRectangle.Y = r * maxHeight;

				for (int c = 0; c < columns; c++)
				{
					textureRectangle.X = c * maxWidth;

					textureRectangle.Width = maxWidth;
					textureRectangle.Height = maxHeight;

					textureRectangle.Intersect(imageRectangle);

					// Cut out the piece of the image we want:
					Bitmap bmp = new Bitmap(textureRectangle.Width, textureRectangle.Height);
					System.Drawing.Graphics g = System.Drawing.Graphics.FromImage(bmp);
					g.DrawImage(image, new Rectangle(0, 0, textureRectangle.Width, textureRectangle.Height), textureRectangle, GraphicsUnit.Pixel);

					// Make the texture:
					m_Textures[r, c] = Texture.FromBitmap(
						Direct3DSettings.Instance.RenderingDevice,
						bmp,
						Direct3DSettings.Instance.TextureUsage,
						Pool.Managed //TODO: What's the pool we want to put stuff in?
						);
				}
			}

			return true;
		}

		/// <summary>
		/// Returns null, because we shouldn't be saving D3D frames to files. 
		/// </summary>
		/// <returns></returns>
		public override Bitmap getFrameImage() { return null; }

		/// <summary>
		/// Renders this frame into a sprite.
		/// </summary>
		public override void Render(Rectangle coords, IRenderParameters param)
		{
			D3DRenderParameters p = (D3DRenderParameters) param;

			for (int r = 0; r < m_Textures.GetLength(0); r++)
			{
				for (int c = 0; c < m_Textures.GetLength(1); c++)
				{
					p.TargetSprite.Draw(m_Textures[r, c], Rectangle.Empty,
						new Vector3(this.getAnchorPoint().X, this.getAnchorPoint().Y, 0),
						new Vector3(coords.X + c * Direct3DSettings.Instance.MaximumTextureSize.Width, coords.Y + r * Direct3DSettings.Instance.MaximumTextureSize.Height, 0), Color.White);
				}
			}
		}
	}
}
