using NUnit.Framework;

namespace Jovian.TagSystem.Tests {
    public class TestJovianTag {

        [SetUp]
        public void Setup() {
            JovianTagsHandler.Initialize();
            JovianTagsHandler.RegisterTag("A.B.C.D");
            JovianTagsHandler.RegisterTag("A.B.E");
        }

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

        [Test]
        public void GivenTwoEqualTags_WhenCompared_ThenEqual() {
            var tag1 = JovianTagsHandler.GetTag("A.B");
            var tag2 = JovianTagsHandler.GetTag("A.B");
            Assert.AreEqual(tag1, tag2);
        }

        [Test]
        public void GivenNoneTag_WhenChecked_ThenIsNone() {
            Assert.IsTrue(JovianTagsHandler.emptyTag.IsNone());
        }

        [Test]
        public void GivenValidTag_WhenChecked_ThenIsValid() {
            var tag = JovianTagsHandler.GetTag("A.B");
            Assert.IsTrue(tag.IsValid());
        }

        [Test]
        public void GivenSameTag_WhenIsDescendantOf_ThenTrue() {
            var tag = JovianTagsHandler.GetTag("A.B");
            Assert.IsTrue(tag.IsDescendantOf(tag));
        }

        [Test]
        public void GivenChild_WhenIsDescendantOfParent_ThenTrue() {
            var parent = JovianTagsHandler.GetTag("A.B");
            var child = JovianTagsHandler.GetTag("A.B.C");
            Assert.IsTrue(child.IsDescendantOf(parent));
        }

        [Test]
        public void GivenGrandchild_WhenIsDescendantOfRoot_ThenTrue() {
            var root = JovianTagsHandler.GetTag("A");
            var grandchild = JovianTagsHandler.GetTag("A.B.C.D");
            Assert.IsTrue(grandchild.IsDescendantOf(root));
        }

        [Test]
        public void GivenParent_WhenIsDescendantOfChild_ThenFalse() {
            var parent = JovianTagsHandler.GetTag("A.B");
            var child = JovianTagsHandler.GetTag("A.B.C");
            Assert.IsFalse(parent.IsDescendantOf(child));
        }

        [Test]
        public void GivenParent_WhenIsAncestorOfChild_ThenTrue() {
            var parent = JovianTagsHandler.GetTag("A");
            var child = JovianTagsHandler.GetTag("A.B.C.D");
            Assert.IsTrue(parent.IsAncestorOf(child));
        }

        [Test]
        public void GivenChild_WhenIsAncestorOfParent_ThenFalse() {
            var parent = JovianTagsHandler.GetTag("A");
            var child = JovianTagsHandler.GetTag("A.B.C.D");
            Assert.IsFalse(child.IsAncestorOf(parent));
        }

        [Test]
        public void GivenSiblings_WhenIsSiblingTo_ThenTrue() {
            var c = JovianTagsHandler.GetTag("A.B.C");
            var e = JovianTagsHandler.GetTag("A.B.E");
            // Both have parent A.B
            Assert.IsTrue(c.IsSiblingTo(e));
            Assert.IsTrue(e.IsSiblingTo(c));
        }

        [Test]
        public void GivenNonSiblings_WhenIsSiblingTo_ThenFalse() {
            var d = JovianTagsHandler.GetTag("A.B.C.D");
            var e = JovianTagsHandler.GetTag("A.B.E");
            // D's parent is C, E's parent is B — not siblings
            Assert.IsFalse(d.IsSiblingTo(e));
        }

        [Test]
        public void GivenUnrelatedBranches_WhenCrossChecked_ThenFalse() {
            var c = JovianTagsHandler.GetTag("A.B.C");
            var e = JovianTagsHandler.GetTag("A.B.E");
            Assert.IsFalse(c.IsDescendantOf(e));
            Assert.IsFalse(e.IsDescendantOf(c));
        }

        [Test]
        public void GivenTwoDifferentTags_WhenCompared_ThenNotEqual() {
            var tag1 = JovianTagsHandler.GetTag("A.B.C");
            var tag2 = JovianTagsHandler.GetTag("A.B.E");
            Assert.AreNotEqual(tag1, tag2);
        }
    }
}
