using System;
using System.Collections.Generic;
using System.Drawing;
using System.Text;
using NUnit.Framework;
using StarEngine.Core;
using StarEngine.Sdl;

namespace StarEngine.Tests.Sdl
{
    [TestFixture]
    public class TextureRenderingTextureTest
    {
        private void AssertPixels(uint[] expected, uint[] actual)
        {
            Assert.AreEqual(expected.Length, actual.Length);
            for (int i = 0; i < actual.Length; i++)
                Assert.AreEqual(expected[i], actual[i], string.Format("index: {0}", i));
        }

        private void AssertPixelsIgnoringAlpha(uint[] expected, uint[] actual)
        {
            Assert.AreEqual(expected.Length, actual.Length);
            for (int i = 0; i < actual.Length; i++)
                Assert.AreEqual(expected[i] & 0x00ffffff, actual[i] & 0x00ffffff,
                     string.Format("index: {0}", i));
        }

        [Test]
        public void TestRenderSelf()
        {
            Texture texture = new Texture(new Size(100, 100));
            texture.RenderTexture(texture, new Rectangle(Point.Empty, texture.Size),
                AffineMatrix.I, 255, BlendType.Alpha, Tone.Empty);
        }

        [Test]
        public void TestBlt1()
        {
            Texture src = new Texture(new Size(3, 3),
                new uint[] { 0xff000001, 0xff000002, 0xff000003,
                0xff000004, 0xff000005, 0xff000006,
                0xff000007, 0xff000008, 0xff000009, });
            Texture dst = new Texture(new Size(5, 4));

            dst.RenderTexture(src, new Rectangle(Point.Empty, src.Size),
                AffineMatrix.I, 255, BlendType.Alpha, Tone.Empty);

            AssertPixelsIgnoringAlpha(new uint[] {
                1,2,3,0,0,
                4,5,6,0,0,
                7,8,9,0,0,
                0,0,0,0,0,
            }, dst.Pixels);
        }

        [Test]
        public void TestBlt2()
        {
            Texture src = new Texture(new Size(3, 3),
                new uint[] { 0xff000001, 0xff000002, 0xff000003,
                0xff000004, 0xff000005, 0xff000006,
                0xff000007, 0xff000008, 0xff000009, });
            Texture dst = new Texture(new Size(5, 4));

            dst.RenderTexture(src, new Rectangle(Point.Empty, src.Size),
                new AffineMatrix(1, 0, 0, 1, 1, 1), 255, BlendType.Alpha, Tone.Empty);

            AssertPixelsIgnoringAlpha(new uint[] {
                0,0,0,0,0,
                0,1,2,3,0,
                0,4,5,6,0,
                0,7,8,9,0,
            }, dst.Pixels);
        }

        [Test]
        public void TestBlt3()
        {
            Texture src = new Texture(new Size(3, 3),
                new uint[] { 0xff000001, 0xff000002, 0xff000003,
                0xff000004, 0xff000005, 0xff000006,
                0xff000007, 0xff000008, 0xff000009, });
            Texture dst = new Texture(new Size(5, 4));

            dst.RenderTexture(src, new Rectangle(1, 1, 10, 10),
                new AffineMatrix(1, 0, 0, 1, 1, 1), 255, BlendType.Alpha, Tone.Empty);

            AssertPixelsIgnoringAlpha(new uint[] {
                0,0,0,0,0,
                0,5,6,0,0,
                0,8,9,0,0,
                0,0,0,0,0,
            }, dst.Pixels);
        }

        [Test]
        public void TestBlt4()
        {
            Texture src = new Texture(new Size(3, 3),
                new uint[] { 0xff000001, 0xff000002, 0xff000003,
                0xff000004, 0xff000005, 0xff000006,
                0xff000007, 0xff000008, 0xff000009, });
            Texture dst = new Texture(new Size(5, 4));

            dst.RenderTexture(src, new Rectangle(1, 1, 10, 10),
                new AffineMatrix(1, 0, 0, 1, 4, 3), 255, BlendType.Alpha, Tone.Empty);

            AssertPixelsIgnoringAlpha(new uint[] {
                0,0,0,0,0,
                0,0,0,0,0,
                0,0,0,0,0,
                0,0,0,0,5,
            }, dst.Pixels);
        }

        [Test]
        public void TestBlt5()
        {
            Texture src = new Texture(new Size(3, 3),
                new uint[] { 0xff000001, 0xff000002, 0xff000003,
                0xff000004, 0xff000005, 0xff000006,
                0xff000007, 0xff000008, 0xff000009, });
            Texture dst = new Texture(new Size(5, 4));

            dst.RenderTexture(src, new Rectangle(1, 1, 10, 10),
                new AffineMatrix(1, 0, 0, 1, -1, -1), 255, BlendType.Alpha, Tone.Empty);

            AssertPixelsIgnoringAlpha(new uint[] {
                9,0,0,0,0,
                0,0,0,0,0,
                0,0,0,0,0,
                0,0,0,0,0,
            }, dst.Pixels);
        }

        [Test]
        public void TestBlt6()
        {
            Texture src = new Texture(new Size(3, 3),
                new uint[] { 0xff000001, 0xff000002, 0xff000003,
                0xff000004, 0xff000005, 0xff000006,
                0xff000007, 0xff000008, 0xff000009, });
            Texture dst = new Texture(new Size(1, 1));

            dst.RenderTexture(src, new Rectangle(0, 0, 10, 10),
                new AffineMatrix(1, 0, 0, 1, -1, -1), 255, BlendType.Alpha, Tone.Empty);

            AssertPixelsIgnoringAlpha(new uint[] { 5 }, dst.Pixels);
        }

        [Test]
        public void TestFlipX()
        {
            Texture src = new Texture(new Size(3, 3),
                new uint[] { 0xff000001, 0xff000002, 0xff000003,
                0xff000004, 0xff000005, 0xff000006,
                0xff000007, 0xff000008, 0xff000009, });
            Texture dst = new Texture(new Size(3, 3));
            dst.RenderTexture(src, new Rectangle(0, 0, 3, 3),
               new AffineMatrix(0, -1, 1, 0, 3, 0), 255, BlendType.Alpha, Tone.Empty);
            AssertPixelsIgnoringAlpha(new uint[] { 7, 4, 1, 8, 5, 2, 9, 6, 3 }, dst.Pixels);
        }

        [Test]
        public void TestFlipY()
        {
            Texture src = new Texture(new Size(3, 3),
                new uint[] { 0xff000001, 0xff000002, 0xff000003,
                0xff000004, 0xff000005, 0xff000006,
                0xff000007, 0xff000008, 0xff000009, });
            Texture dst = new Texture(new Size(3, 3));
            dst.RenderTexture(src, new Rectangle(0, 0, 3, 3),
               new AffineMatrix(0, 1, -1, 0, 0, 3), 255, BlendType.Alpha, Tone.Empty);
            AssertPixelsIgnoringAlpha(new uint[] { 3, 6, 9, 2, 5, 8, 1, 4, 7 }, dst.Pixels);
        }

        [Test]
        public void TestFlipXY()
        {
            Texture src = new Texture(new Size(3, 3),
                new uint[] { 0xff000001, 0xff000002, 0xff000003,
                0xff000004, 0xff000005, 0xff000006,
                0xff000007, 0xff000008, 0xff000009, });
            Texture dst = new Texture(new Size(3, 3));
            dst.RenderTexture(src, new Rectangle(0, 0, 3, 3),
               new AffineMatrix(-1, 0, 0, -1, 3, 3), 255, BlendType.Alpha, Tone.Empty);
            AssertPixelsIgnoringAlpha(new uint[] { 9, 8, 7, 6, 5, 4, 3, 2, 1 }, dst.Pixels);
        }

        [Test]
        public void TestFlipXYScale2()
        {
            Texture src = new Texture(new Size(3, 3),
                new uint[] { 0xff000001, 0xff000002, 0xff000003,
                0xff000004, 0xff000005, 0xff000006,
                0xff000007, 0xff000008, 0xff000009, });
            Texture dst = new Texture(new Size(6, 6));
            dst.RenderTexture(src, new Rectangle(0, 0, 3, 3),
               new AffineMatrix(-2, 0, 0, -2, 6, 6), 255, BlendType.Alpha, Tone.Empty);
            AssertPixelsIgnoringAlpha(new uint[] { 9, 9, 8, 8, 7, 7, 9, 9, 8, 8, 7, 7, 6, 6, 5, 5, 4, 4, 6, 6, 5, 5, 4, 4, 3, 3, 2, 2, 1, 1, 3, 3, 2, 2, 1, 1 }, dst.Pixels);
        }
    }
}
