using NUnit.Framework;

namespace Jovian.TagSystem.Tests {
    public class TestJovianTagsContainer {
        private JovianTagsContainer container;

        [SetUp]
        public void Setup() {
            JovianTagsHandler.Initialize();
            JovianTagsHandler.RegisterTag("A.B.C.D");
            JovianTagsHandler.RegisterTag("A.B.E");
            JovianTagsHandler.RegisterTag("X.Y");
            container = new JovianTagsContainer(8);
        }

        [TearDown]
        public void TearDown() {
            JovianTagsHandler.Reset();
        }

        [Test]
        public void GivenEmptyContainer_WhenAdd_ThenContainsTag() {
            var tag = JovianTagsHandler.GetTag("A.B");
            container.Add(tag);
            Assert.IsTrue(container.Contains(tag));
            Assert.AreEqual(1, container.Count);
        }

        [Test]
        public void GivenContainer_WhenAddDuplicate_ThenNotAdded() {
            var tag = JovianTagsHandler.GetTag("A.B");
            container.Add(tag);
            container.Add(tag);
            Assert.AreEqual(1, container.Count);
        }

        [Test]
        public void GivenContainer_WhenRemove_ThenNotContained() {
            var tag = JovianTagsHandler.GetTag("A.B");
            container.Add(tag);
            container.Remove(tag);
            Assert.IsFalse(container.Contains(tag));
        }

        [Test]
        public void GivenContainer_WhenClear_ThenEmpty() {
            container.Add(JovianTagsHandler.GetTag("A"));
            container.Add(JovianTagsHandler.GetTag("A.B"));
            container.Clear();
            Assert.AreEqual(0, container.Count);
        }

        [Test]
        public void GivenContainer_WhenIndexer_ThenCorrectTag() {
            var tagA = JovianTagsHandler.GetTag("A");
            var tagB = JovianTagsHandler.GetTag("A.B");
            container.Add(tagA);
            container.Add(tagB);
            Assert.AreEqual(tagA, container[0]);
            Assert.AreEqual(tagB, container[1]);
        }

        [Test]
        public void GivenContainerWithChild_WhenContainsDescendantOf_ThenTrue() {
            var parent = JovianTagsHandler.GetTag("A.B");
            container.Add(JovianTagsHandler.GetTag("A.B.C.D"));
            container.Add(JovianTagsHandler.GetTag("X.Y"));
            Assert.IsTrue(container.ContainsDescendantOf(parent));
        }

        [Test]
        public void GivenContainerWithParent_WhenContainsAncestorOf_ThenTrue() {
            var child = JovianTagsHandler.GetTag("A.B.C");
            container.Add(JovianTagsHandler.GetTag("A.B"));
            container.Add(JovianTagsHandler.GetTag("X.Y"));
            Assert.IsTrue(container.ContainsAncestorOf(child));
        }

        [Test]
        public void GivenContainerWithSibling_WhenContainsSibling_ThenTrue() {
            var tag = JovianTagsHandler.GetTag("A.B.C");
            container.Add(JovianTagsHandler.GetTag("A.B.E")); // sibling of C (both under A.B)
            Assert.IsTrue(container.ContainsSibling(tag));
        }

        [Test]
        public void GivenContainerWithoutSibling_WhenContainsSibling_ThenFalse() {
            var tag = JovianTagsHandler.GetTag("A.B.C");
            container.Add(JovianTagsHandler.GetTag("X.Y")); // unrelated
            Assert.IsFalse(container.ContainsSibling(tag));
        }
    }
}
