/*
 * Copyright (C) 2013 FooProject
 * * This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 3 of the License, or (at your option) any later version.

 * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of 
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.

You should have received a copy of the GNU General Public License along with this program. If not, see <http://www.gnu.org/licenses/>.
 */
using System;
using System.Linq;
using System.Text.RegularExpressions;
using System.Collections.Generic;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using FooEditEngine;

namespace UnitTest
{
    [TestClass]
    public class UnitTest2
    {
        [TestMethod]
        public void AppendTest()
        {
            Document doc = new Document();
            const string str = "te";
            doc.Append(str);
            Assert.IsTrue(doc.ToString(0,doc.Length) == str);
        }
        [TestMethod]
        public void InsertTest()
        {
            Document doc = new Document();
            const string str = "t";
            doc.Append("this");
            doc.Insert(0, str);
            Assert.IsTrue(doc[0] == 't');
        }
        [TestMethod]
        public void RemoveTest()
        {
            Document doc = new Document();
            doc.Append("this");
            doc.Remove(0, 1);
            Assert.IsTrue(doc[0] == 'h');
        }
        [TestMethod]
        public void FindTest1()
        {
            Document doc = new Document();
            doc.Append("is this a pen");
            doc.SetFindParam("is", false, RegexOptions.None);
            IEnumerator<SearchResult> it = doc.Find();
            it.MoveNext();
            SearchResult sr = it.Current;
            Assert.IsTrue(sr.Start == 0 && sr.End == 1);
            it.MoveNext();
            sr = it.Current;
            Assert.IsTrue(sr.Start == 5 && sr.End == 6);
        }

        [TestMethod]
        public void FindTest2()
        {
            Document doc = new Document();
            doc.Append("is this a pen");
            doc.SetFindParam("is", false, RegexOptions.None);
            IEnumerator<SearchResult> it = doc.Find(3,4);
            it.MoveNext();
            SearchResult sr = it.Current;
            Assert.IsTrue(sr.Start == 5 && sr.End == 6);
        }

        [TestMethod]
        public void FindTest3()
        {
            Document doc = new Document();
            doc.Append("is this a pen");
            doc.SetFindParam("is", false, RegexOptions.None);
            IEnumerator<SearchResult> it = doc.Find(0, 8);
            it.MoveNext();
            SearchResult sr = it.Current;
            doc.Replace(sr.Start, sr.End - sr.Start + 1, "aaa");
            it.MoveNext();
            sr = it.Current;
            Assert.IsTrue(sr.Start == 6 && sr.End == 7);
        }

        [TestMethod]
        public void ReaderTest1()
        {
            Document doc = new Document();
            doc.Append("a");
            DocumentReader reader = doc.CreateReader();
            Assert.IsTrue(reader.Read() == 'a');
            Assert.IsTrue(reader.Peek() == -1);
        }

        [TestMethod]
        public void ReaderTest2()
        {
            Document doc = new Document();
            doc.Append("abc");
            DocumentReader reader = doc.CreateReader();
            char[] buf = new char[2];
            int count = reader.Read(buf,1,2);
            Assert.IsTrue(buf[0] == 'b' && buf[1] == 'c');
            Assert.IsTrue(count == 2);
            Assert.IsTrue(reader.Peek() == -1);
        }

        [TestMethod]
        public void GetLinesText()
        {
            Document doc = new Document();
            doc.Append("a\nb\nc");
            var result = doc.GetLines(0, doc.Length - 1).ToArray();
            Assert.AreEqual("a\n", result[0]);
            Assert.AreEqual("b\n", result[1]);
            Assert.AreEqual("c", result[2]);
        }

        [TestMethod]
        public void IndexOfText()
        {
            StringBuffer buf = new StringBuffer();
            string str = "this is a pen";
            buf.Replace(0, 0, str, str.Length);
            
            int index = buf.IndexOf("is", 0);
            Assert.IsTrue(index == 2);
            
            index = buf.IndexOf("is", 4);
            Assert.IsTrue(index == 5);
            
            index = buf.IndexOf("xy", 0);
            Assert.IsTrue(index == -1);

            index = buf.IndexOf("Is", 0,true);
            Assert.IsTrue(index == 2);

            str = "xABC";
            buf.Clear();
            buf.Replace(0, 0, str, str.Length);
            index = buf.IndexOf("ABC", 0);
            Assert.IsTrue(index == 1);

            index = buf.IndexOf("abc", 0,true);
            Assert.IsTrue(index == 1);

            index = buf.IndexOf("abc", 0);
            Assert.IsTrue(index == -1);
        }

        [TestMethod]
        public void ReplaceAllTest()
        {
            StringBuffer buf = new StringBuffer();
            string str = "this is a pen";
            buf.Replace(0, 0, str, str.Length);
            buf.Replace("is", "aaa");
            string excpect = str.Replace("is", "aaa");
            for (int i = 0; i < excpect.Length; i++)
                Assert.IsTrue(buf[i] == excpect[i]);
        }

        [TestMethod]
        public void MarkerTest()
        {
            Document doc = new Document();
            doc.Append("this is a pen");
            doc.SetMarker(MarkerIDs.Defalut, Marker.Create(0, 4, HilightType.Sold));

            var markers = doc.Markers.Get(MarkerIDs.Defalut);
            foreach(var m in markers)
                Assert.IsTrue(m.start == 0 && m.length == 4);

            doc.SetMarker(MarkerIDs.Defalut, Marker.Create(5, 2, HilightType.Sold));
            doc.RemoveMarker(MarkerIDs.Defalut, 0, 4);
            markers = doc.Markers.Get(MarkerIDs.Defalut);
            foreach (var m in markers)
                Assert.IsTrue(m.start == 5 && m.length == 2);

            doc.Insert(5, "a");
            markers = doc.Markers.Get(MarkerIDs.Defalut, 0);
            foreach (var m in markers)
                Assert.IsTrue(m.start == 6 && m.length == 2);

            doc.Insert(10, "a");
            markers = doc.Markers.Get(MarkerIDs.Defalut, 0);
            foreach (var m in markers)
                Assert.IsTrue(m.start == 6 && m.length == 2);

            doc.SetMarker(MarkerIDs.URL, Marker.Create(0, 4, HilightType.Sold));
            doc.Markers.Clear(MarkerIDs.Defalut);
            foreach (int id in doc.Markers.IDs)
            {
                markers = doc.Markers.Get(id, 0);
                foreach (var m in markers)
                    Assert.IsTrue(m.start == 0 && m.length == 4);
            }
        }

        [TestMethod]
        public void WatchDogTest()
        {
            RegexWatchDog dog = new RegexWatchDog(new Regex("h[a-z]+"), HilightType.Url);
            List<Marker> result = new List<Marker>(){
                Marker.Create(0,4,HilightType.Url),
                Marker.Create(5,4,HilightType.Url)
            };
            string str = "html haml";
            var actual = dog.Mark(0, str);
            this.AreEqual(result, actual);

            Document doc = new Document();
            DummyRender render = new DummyRender();
            DummyView view = new DummyView(doc, render);
            view.LayoutLines.WacthDogPattern.Add(MarkerIDs.Defalut, dog);
            doc.Clear();
            doc.Append(str);
            actual = doc.Markers.Get(MarkerIDs.Defalut);
            view.LayoutLines.GetLayout(0);
            this.AreEqual(result, actual);
        }

        void AreEqual<T>(IEnumerable<T> t1, IEnumerable<T> t2)
        {
            Assert.AreEqual(t1.Count(), t2.Count());

            IEnumerator<T> e1 = t1.GetEnumerator();
            IEnumerator<T> e2 = t2.GetEnumerator();

            while (e1.MoveNext() && e2.MoveNext())
            {
                Assert.AreEqual(e1.Current, e2.Current);
            }
        }
    }
}
