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 TextureTest
    {
        private ITextureFactory factory = TextureFactory.Instance;

        [Test]
        public void TestCreate()
        {
            Texture texture = (Texture)factory.Create(new Size(100, 200));
            Assert.AreEqual(new Size(100, 200), texture.Size);
            Assert.AreEqual(100, texture.Width);
            Assert.AreEqual(200, texture.Height);
            foreach (uint p in texture.Pixels)
                Assert.AreEqual(0x00000000, p);
        }

        [Test]
        public void TestLoad1()
        {
            Texture texture = (Texture)factory.Load("Resources/Images/Ruby.png");
            Assert.AreEqual(50, texture.Width);
            Assert.AreEqual(35, texture.Height);

            uint[] pixels = texture.Pixels;
            Assert.AreEqual(0x00ffffff, pixels[0]);
            foreach (uint p in pixels)
            {
                byte b = (byte)(p >> 24);
                Assert.IsTrue(b == 0x00 || b == 0xff, b.ToString());
            }
        }

        [Test]
        public void TestLoad2()
        {
            Texture texture = (Texture)factory.Load("Resources/Images/RubyCompressed.pngx");
            Assert.AreEqual(50, texture.Width);
            Assert.AreEqual(35, texture.Height);
        }

        [Test]
        public void TestLoad3()
        {
            Texture texture = (Texture)factory.Load("Resources/Images/RubyPng");
            Assert.AreEqual(50, texture.Width);
            Assert.AreEqual(35, texture.Height);
        }

        [Test]
        public void TestLoadFailureInvalidFile()
        {
            try
            {
                factory.Load("Resources/Images/NotImage.txt");
                Assert.Fail();
            }
            catch (ArgumentException)
            {
            }
        }

        [Test]
        public void TestLoadFailureInvalidPath()
        {
            try
            {
                factory.Load("Resources/hoge/fuga");
                Assert.Fail();
            }
            catch (System.IO.FileNotFoundException)
            {
            }
        }

        [Test]
        public void TestClone()
        {
            Texture texture1 = (Texture)factory.Load("Resources/Images/Ruby.png");
            Texture texture2 = (Texture)texture1.Clone();
            Assert.AreEqual(texture1.Width, texture2.Width);
            Assert.AreEqual(texture1.Height, texture2.Height);
            Assert.AreNotSame(texture1, texture2);
            uint[] pixels1 = texture1.Pixels;
            uint[] pixels2 = texture2.Pixels;
            for (int i = 0; i < pixels1.Length; i++)
                Assert.AreEqual(pixels1[i], pixels2[i]);
        }

        [Test]
        public void TestGetAndSetPixel()
        {
            Texture texture = new Texture(new Size(3, 3),
                new uint[] { 1, 2, 3, 4, 5, 6, 7, 8, 0xffffffff });
            Assert.AreEqual(Color.FromArgb(1), texture.GetPixel(0, 0));
            Assert.AreEqual(Color.FromArgb(2), texture.GetPixel(1, 0));
            Assert.AreEqual(Color.FromArgb(3), texture.GetPixel(2, 0));
            Assert.AreEqual(Color.FromArgb(4), texture.GetPixel(0, 1));
            Assert.AreEqual(Color.FromArgb(5), texture.GetPixel(1, 1));
            Assert.AreEqual(Color.FromArgb(6), texture.GetPixel(2, 1));
            Assert.AreEqual(Color.FromArgb(7), texture.GetPixel(0, 2));
            Assert.AreEqual(Color.FromArgb(8), texture.GetPixel(1, 2));
            Assert.AreEqual(0xffffffff, (uint)texture.GetPixel(2, 2).ToArgb());

            texture.SetPixel(0, 1, Color.Red);
            texture.SetPixel(1, 2, Color.Green);
            texture.SetPixel(2, 0, Color.Blue);
            Assert.AreEqual(Color.Red.ToArgb(), texture.GetPixel(0, 1).ToArgb());
            Assert.AreEqual(Color.Green.ToArgb(), texture.GetPixel(1, 2).ToArgb());
            Assert.AreEqual(Color.Blue.ToArgb(), texture.GetPixel(2, 0).ToArgb());
        }

        [Test]
        public void TestChangeHue()
        {
            ITexture texture = factory.Load("Resources/Images/Ruby.png");
            for (int i = -10; i < 369; i++)
                texture.ChangeHue(i);
        }

        [Test]
        public void TestClear()
        {
            Texture texture = (Texture)factory.Load("Resources/Images/Ruby.png");
            texture.Clear();
            foreach (uint p in texture.Pixels)
                Assert.AreEqual(0, p);
        }

        [Test]
        public void TestFill()
        {
            Texture texture = (Texture)factory.Create(new Size(100, 200));

            foreach (uint p in texture.Pixels)
                Assert.AreEqual(0x00000000, p);

            texture.Fill(Color.FromArgb(0x12345678));

            foreach (uint p in texture.Pixels)
                Assert.AreEqual(0x12345678, p);

            texture.Fill(Color.FromArgb(unchecked((int)0x98765432)));

            foreach (uint p in texture.Pixels)
                Assert.AreEqual(0x98765432, p);
        }

        [Test]
        public void TestFillRectangle()
        {
            Texture texture = (Texture)factory.Create(new Size(100, 200));

            foreach (uint p in texture.Pixels)
                Assert.AreEqual(0x00000000, p);

            Rectangle rect = new Rectangle(50, 60, 100, 95);
            texture.FillRectangle(rect, Color.FromArgb(0x12345678));

            for (int j = 0; j < texture.Height; j++)
            {
                for (int i = 0; i < texture.Width; i++)
                {
                    if (50 <= i && 60 <= j && i < 150 && j < 155)
                        Assert.AreEqual(Color.FromArgb(0x12345678), texture.GetPixel(i, j));
                    else
                        Assert.AreEqual(Color.FromArgb(0x00000000), texture.GetPixel(i, j));
                }
            }
            
        }

        private void AssertEqual(Texture t1, Texture t2)
        {
            Assert.AreEqual(t1.Width, t2.Width);
            Assert.AreEqual(t1.Height, t2.Height);

            uint[] p1 = t1.Pixels;
            uint[] p2 = t2.Pixels;

            for (int i = 0; i < p1.Length; i++)
                Assert.AreEqual(p1[i], p2[i],
                    string.Format("[{0}] {1:x}:{2:x}", i, p1[i], p2[i]));
        }

        [Test]
        public void TestRenderText1()
        {
            Texture texture = (Texture)factory.Create(new Size(66, 18));

            Font font = new Font("ＭＳ ゴシック", 12, GraphicsUnit.Pixel);

            texture.Fill(Color.Black);
            texture.RenderText("こんにちは", Point.Empty, font, Color.White);
            string path = "Resources/Images/TestRenderText/Hello1.png";
            Texture textureHello1 = (Texture)factory.Load(path);
            AssertEqual(textureHello1, texture);
        }

        [Test]
        public void TestRenderText2()
        {
            Texture texture = (Texture)factory.Create(new Size(66, 18));

            Font font = new Font("ＭＳ ゴシック", 12, GraphicsUnit.Pixel);

            texture.Fill(Color.Black);
            texture.RenderText("こんにちは", new Point(3, 3), font, Color.White);
            string path = "Resources/Images/TestRenderText/Hello2.png";
            Texture textureHello2 = (Texture)factory.Load(path);
            AssertEqual(textureHello2, texture);
        }

        [Test]
        public void TestRenderText3()
        {
            Texture texture = (Texture)factory.Create(new Size(66, 18));

            Font font = new Font("ＭＳ ゴシック", 12, GraphicsUnit.Pixel);

            texture.Fill(Color.Black);
            texture.RenderText("こんにちは", new Point(8, 8), font, Color.White);
            string path = "Resources/Images/TestRenderText/Hello3.png";
            Texture textureHello3 = (Texture)factory.Load(path);
            AssertEqual(textureHello3, texture);
        }

        [Test]
        public void TestRenderText4()
        {
            Texture texture = (Texture)factory.Create(new Size(66, 18));

            Font font = new Font("ＭＳ ゴシック", 12, GraphicsUnit.Pixel);

            texture.Fill(Color.Black);
            texture.RenderText("こんにちは", new Point(-2, -1), font, Color.White);
            string path = "Resources/Images/TestRenderText/Hello4.png";
            Texture textureHello4 = (Texture)factory.Load(path);
            AssertEqual(textureHello4, texture);
        }

        [Test]
        public void TestRenderText5()
        {
            Texture texture = (Texture)factory.Create(new Size(54, 6));

            Font font = new Font("ＭＳ ゴシック", 12, GraphicsUnit.Pixel);

            texture.Fill(Color.Black);
            texture.RenderText("こんにちは", new Point(-3, -3), font, Color.White);
            string path = "Resources/Images/TestRenderText/Hello5.png";
            Texture textureHello5 = (Texture)factory.Load(path);
            AssertEqual(textureHello5, texture);
        }

    }
}
