using DotNetEx.IO;

namespace NUnitTest
{
    [NUnit.Framework.TestFixture]
    public class PathTest
    {
        [NUnit.Framework.Test]
        public void SelfSetTest()
        {
            System.Reflection.Assembly assembly = System.Reflection.Assembly.GetCallingAssembly();
            Path test = assembly.Location;
            test = test.Parent;
        }

        [NUnit.Framework.Test]
        public void EmptyEqualChecker()
        {
            NUnit.Framework.Assert.AreEqual(true, (Path.Empty == new Path()));
            NUnit.Framework.Assert.AreEqual(true, Path.Empty.Equals(new Path()));
            NUnit.Framework.Assert.AreEqual(true, Path.Empty.CompareTo(new Path()) == 0);
        }

        [NUnit.Framework.Test]
        public void SimpleNameCheck()
        {
            Path test = "hoge";
            StatusChecker checker = new StatusChecker();
            checker.expectRoot = System.String.Empty;
            checker.expectPath = "hoge";
            checker.expectRelation = "hoge";
            checker.expectName = "hoge";
            checker.expectSingleExtention = System.String.Empty;
            checker.expectMultiExtention = System.String.Empty;
            checker.Check(test);
        }

        [NUnit.Framework.Test]
        public void SimpleRootCheck()
        {
            System.String drvs = "abcdefghijklmnopqrstuvwxyz";
            for (int index = 0; index < drvs.Length; index++)
            {
                System.String drv = drvs.Substring(index, 1) + ":\\";
                PathInitializeStatusCheck(
                    drv,
                    drv,
                    drv,
                    System.String.Empty,
                    System.String.Empty,
                    System.String.Empty,
                    System.String.Empty
                    );
                Path test = drv;
                NUnit.Framework.Assert.AreEqual(true, test.Equals(drv.ToUpper()));
                NUnit.Framework.Assert.AreEqual(false, test.Equals(drvs.Substring(index, 1) + drv));
                NUnit.Framework.Assert.AreEqual(true, test.Root.Equals(drv.ToUpper()));
                NUnit.Framework.Assert.AreEqual(false, test.Root.Equals(drvs.Substring(index, 1) + drv));
            }
        }

        [NUnit.Framework.Test]
        public void SimpleUNCCheck()
        {
            for (int index = 0; index < 2; index++)
            {
                System.String drv = "\\\\";
                if (index == 1) drv = "//";
                PathInitializeStatusCheck(
                    drv,
                    drv,
                    drv,
                    System.String.Empty,
                    System.String.Empty,
                    System.String.Empty,
                    System.String.Empty
                    );
                Path test = drv;
                NUnit.Framework.Assert.AreEqual(true, test.Equals(drv.ToUpper()));
                NUnit.Framework.Assert.AreEqual(false, test.Equals("/" + drv));
                NUnit.Framework.Assert.AreEqual(true, test.Root.Equals(drv.ToUpper()));
                NUnit.Framework.Assert.AreEqual(false, test.Root.Equals("/" + drv));
            }
        }

        [NUnit.Framework.Test]
        public void RootAndRelativeTest()
        {
            PathInitializeStatusCheck(
                "C:\\ hoge \\",
                "C:\\hoge",
                "C:\\",
                "hoge",
                "hoge",
                System.String.Empty,
                System.String.Empty
                );
            PathInitializeStatusCheck(
                "\\\\hoge\\ /hoge\\",
                "\\\\hoge\\hoge",
                "\\\\",
                "hoge\\hoge",
                "hoge",
                System.String.Empty,
                System.String.Empty
                );
            PathInitializeStatusCheck(
                "C:\\ . .hoge. . .",
                "C:\\. .hoge",
                "C:\\",
                ". .hoge",
                ". .hoge",
                ".hoge",
                ". .hoge"
                );
            PathInitializeStatusCheck(
                "C:\\ . . . . .",
                "C:\\.",
                "C:\\",
                ".",
                ".",
                System.String.Empty,
                System.String.Empty
                );
            PathInitializeStatusCheck(
                "file:///c:/document/test.txt",
                "file:///c:/document/test.txt",
                "file:///c:/",
                "document/test.txt",
                "test.txt",
                ".txt",
                ".txt"
                );
            PathInitializeStatusCheck(
                "user:/document/test.txt",
                "user:/document/test.txt",
                "user:/",
                "document/test.txt",
                "test.txt",
                ".txt",
                ".txt"
                );
            PathInitializeStatusCheck(
                "//document/test.txt",
                "//document/test.txt",
                "//",
                "document/test.txt",
                "test.txt",
                ".txt",
                ".txt"
                );
            PathInitializeStatusCheck(
                "/document/test.txt",
                "/document/test.txt",
                "/",
                "document/test.txt",
                "test.txt",
                ".txt",
                ".txt"
                );
        }

        [NUnit.Framework.Test]
        public void RemoveTrailExtentionSeparatorTest()
        {
            PathInitializeStatusCheck(
                "C:\\... .",
                "C:\\..",
                "C:\\",
                "..",
                "..",
                System.String.Empty,
                System.String.Empty
                );

            PathInitializeStatusCheck(
                "\\\\..hoge. . .\\.test...txt..jpeg. . . ..",
                "\\\\..hoge\\.test...txt..jpeg",
                "\\\\",
                "..hoge\\.test...txt..jpeg",
                ".test...txt..jpeg",
                ".jpeg",
                ".test...txt..jpeg"
                );
        }

        [NUnit.Framework.Test]
        public void RelationResolveTest()
        {
            RelationResolveCheck(
                "C:\\./Item.txt",
                "C:\\./Item.txt",
                "C:\\",
                "./Item.txt",
                "Item.txt",
                ".txt",
                ".txt",
                "C:\\Item.txt"
                );

            RelationResolveCheck(
            src: "C:\\./../.Item.txt",
            expectPath: "C:\\./../.Item.txt",
            expectRoot: "C:\\",
            expectRelation: "./../.Item.txt",
            expectName: ".Item.txt",
            expectSingleExtention: ".txt",
            expectMultiExtention: ".Item.txt",
            expectResolved: "C:\\.Item.txt"
            );

            RelationResolveCheck(
            src: "C:\\./hoge/../.Item.txt",
            expectPath: "C:\\./hoge/../.Item.txt",
            expectRoot: "C:\\",
            expectRelation: "./hoge/../.Item.txt",
            expectName: ".Item.txt",
            expectSingleExtention: ".txt",
            expectMultiExtention: ".Item.txt",
            expectResolved: "C:\\.Item.txt"
            );

            RelationResolveCheck(
            src: "C:\\./hoge/hoge/../.Item.txt",
            expectPath: "C:\\./hoge/hoge/../.Item.txt",
            expectRoot: "C:\\",
            expectRelation: "./hoge/hoge/../.Item.txt",
            expectName: ".Item.txt",
            expectSingleExtention: ".txt",
            expectMultiExtention: ".Item.txt",
            expectResolved: "C:\\hoge/.Item.txt"
            );
        }

        [NUnit.Framework.Test]
        public void CombineTest()
        {
            Path test1 = "C:\\hoge/item.txt";
            StatusChecker checker = new StatusChecker();
            checker.expectRoot = "C:\\";
            checker.expectPath = "C:\\hoge/item.txt";
            checker.expectRelation = "hoge/item.txt";
            checker.expectName = "item.txt";
            checker.expectSingleExtention = ".txt";
            checker.expectMultiExtention = ".txt";
            checker.Check(test1);

            Path Combined;
            Combined = test1 + "hoge";
            checker.expectRoot = "C:\\";
            checker.expectPath = "C:\\hoge/item.txt/hoge";
            checker.expectRelation = "hoge/item.txt/hoge";
            checker.expectName = "hoge";
            checker.expectSingleExtention = System.String.Empty;
            checker.expectMultiExtention = System.String.Empty;
            checker.Check(Combined);
        }

        [NUnit.Framework.Test]
        public void IntersectTest()
        {
            Path test1 = "C:\\hoge/item.txt";
            StatusChecker checker = new StatusChecker();
            checker.expectRoot = "C:\\";
            checker.expectPath = "C:\\hoge/item.txt";
            checker.expectRelation = "hoge/item.txt";
            checker.expectName = "item.txt";
            checker.expectSingleExtention = ".txt";
            checker.expectMultiExtention = ".txt";
            checker.Check(test1);

            Path test2 = "A:\\item.txt";
            checker = new StatusChecker();
            checker.expectRoot = "A:\\";
            checker.expectPath = "A:\\item.txt";
            checker.expectRelation = "item.txt";
            checker.expectName = "item.txt";
            checker.expectSingleExtention = ".txt";
            checker.expectMultiExtention = ".txt";
            checker.Check(test2);

            Path intersected = test1.Intersect(test2);
            checker = new StatusChecker();
            checker.expectRoot = System.String.Empty;
            checker.expectPath = System.String.Empty;
            checker.expectRelation = System.String.Empty;
            checker.expectName = System.String.Empty;
            checker.expectSingleExtention = System.String.Empty;
            checker.expectMultiExtention = System.String.Empty;
            checker.Check(intersected);

            test2 = "C:\\";
            checker = new StatusChecker();
            checker.expectRoot = "C:\\";
            checker.expectPath = "C:\\";
            checker.expectRelation = System.String.Empty;
            checker.expectName = System.String.Empty;
            checker.expectSingleExtention = System.String.Empty;
            checker.expectMultiExtention = System.String.Empty;
            checker.Check(test2);

            intersected = test1.Intersect(test2);
            checker = new StatusChecker();
            checker.expectRoot = "C:\\";
            checker.expectPath = "C:\\";
            checker.expectRelation = System.String.Empty;
            checker.expectName = System.String.Empty;
            checker.expectSingleExtention = System.String.Empty;
            checker.expectMultiExtention = System.String.Empty;
            checker.Check(intersected);

            test2 = "C:\\HoGe/hoge.bin";
            intersected = test1.Intersect(test2);
            checker = new StatusChecker();
            checker.expectRoot = "C:\\";
            checker.expectPath = "C:\\hoge";
            checker.expectRelation = "hoge";
            checker.expectName = "hoge";
            checker.expectSingleExtention = System.String.Empty;
            checker.expectMultiExtention = System.String.Empty;
            checker.Check(intersected);

            test2 = test1 + "fuga.user.bin";
            checker = new StatusChecker();
            checker.expectRoot = "C:\\";
            checker.expectPath = "C:\\hoge/item.txt/fuga.user.bin";
            checker.expectRelation = "hoge/item.txt/fuga.user.bin";
            checker.expectName = "fuga.user.bin";
            checker.expectSingleExtention = ".bin";
            checker.expectMultiExtention = ".user.bin";
            checker.Check(test2);

            intersected = test1.Intersect(test2);
            checker = new StatusChecker();
            checker.expectRoot = "C:\\";
            checker.expectPath = "C:\\hoge/item.txt";
            checker.expectRelation = "hoge/item.txt";
            checker.expectName = "item.txt";
            checker.expectSingleExtention = ".txt";
            checker.expectMultiExtention = ".txt";
            checker.Check(intersected);

        }

        [NUnit.Framework.Test]
        public void RelationToTest()
        {
            Path test1 = "C:\\abcd/edfg/hijk/lmno/pqrs/tuvw/xyz";
            Path test2 = "C:\\hoge/fuga/item.txt";

            StatusChecker checker = new StatusChecker();
            checker.expectRoot = System.String.Empty;
            checker.expectPath = "../../../../../../../hoge/fuga/item.txt";
            checker.expectRelation = checker.expectPath;
            checker.expectName = "item.txt";
            checker.expectSingleExtention = ".txt";
            checker.expectMultiExtention = ".txt";
            checker.Check(test1.RelationTo(test2));

            test1 = "C:\\HOGE/edfg/hijk/lmno/pqrs/tuvw/xyz";
            checker = new StatusChecker();
            checker.expectRoot = System.String.Empty;
            checker.expectPath = "../../../../../../fuga/item.txt";
            checker.expectRelation = checker.expectPath;
            checker.expectName = "item.txt";
            checker.expectSingleExtention = ".txt";
            checker.expectMultiExtention = ".txt";
            checker.Check(test1.RelationTo(test2));
        }

        public Path RelationResolveCheck(
            System.String src,
            System.String expectPath,
            System.String expectRoot,
            System.String expectRelation,
            System.String expectName,
            System.String expectSingleExtention,
            System.String expectMultiExtention,
            System.String expectResolved
            )
        {
            Path test = PathInitializeStatusCheck(src, expectPath, expectRoot, expectRelation, expectName, expectSingleExtention, expectMultiExtention);
            test.RelativeNormalize();
            NUnit.Framework.Assert.AreEqual(expectResolved, test.ToString());
            return test;
        }

        public Path PathInitializeStatusCheck(
            System.String src,
            System.String expectPath,
            System.String expectRoot,
            System.String expectRelation,
            System.String expectName,
            System.String expectSingleExtention,
            System.String expectMultiExtention
            )
        {
            return PathInitializeStatusCheck(
                src,
                expectPath,
                expectRoot,
                expectRelation,
                expectName,
                expectSingleExtention,
                expectMultiExtention,
                System.String.IsNullOrEmpty(expectPath),
                System.String.IsNullOrEmpty(expectRoot) && (System.String.IsNullOrEmpty(expectRelation) == false),
                (System.String.IsNullOrEmpty(expectRoot) == false) && System.String.IsNullOrEmpty(expectRelation)
                );
        }

        public Path PathInitializeStatusCheck(
            System.String src,
            Path path,
            System.String expectPath,
            System.String expectRoot,
            System.String expectRelation,
            System.String expectName,
            System.String expectSingleExtention,
            System.String expectMultiExtention
            )
        {
            NUnit.Framework.Assert.AreEqual(false, (path == null) && System.String.IsNullOrWhiteSpace(src), "null-parameter-exception");
            if (path == null) path = new Path(src);
            else if (System.String.IsNullOrWhiteSpace(src)) src = path.ToString();
            return PathInitializeStatusCheck(
                src,
                path,
                expectPath,
                expectRoot,
                expectRelation,
                expectName,
                expectSingleExtention,
                expectMultiExtention,
                System.String.IsNullOrEmpty(expectPath),
                System.String.IsNullOrEmpty(expectRoot) && (System.String.IsNullOrEmpty(expectRelation) == false),
                (System.String.IsNullOrEmpty(expectRoot) == false) && System.String.IsNullOrEmpty(expectRelation)
                );
        }
        
        public Path PathInitializeStatusCheck(
            System.String src,
            System.String expectPath,
            System.String expectRoot,
            System.String expectRelation,
            System.String expectName,
            System.String expectSingleExtention,
            System.String expectMultiExtention,
            bool expectIsEmpty,
            bool expectIsRelativeOnly,
            bool expectIsRootOnly
            )
        {
            return PathInitializeStatusCheck(src, null, expectPath, expectRoot, expectRelation, expectName, expectSingleExtention, expectMultiExtention, expectIsEmpty, expectIsRelativeOnly, expectIsRootOnly);
        }

        public Path PathInitializeStatusCheck(
            System.String src,
            Path path,
            System.String expectPath,
            System.String expectRoot,
            System.String expectRelation,
            System.String expectName,
            System.String expectSingleExtention,
            System.String expectMultiExtention,
            bool expectIsEmpty,
            bool expectIsRelativeOnly,
            bool expectIsRootOnly
            )
        {
            NUnit.Framework.Assert.AreEqual(false, (path == null) && System.String.IsNullOrWhiteSpace(src), "null-parameter-exception");
            if (path == null) path = new Path(src);
            else if (System.String.IsNullOrWhiteSpace(src)) src = path.ToString();
            NUnit.Framework.Assert.AreEqual(expectPath, path.ToString(), "on-path-checking: " + src);
            NUnit.Framework.Assert.AreEqual(expectRoot, path.Root.ToString(), "on-root-checking: " + src);
            NUnit.Framework.Assert.AreEqual(!System.String.IsNullOrEmpty(expectRoot), path.HasRoot, "on-hasRoot-checking: " + src);
            NUnit.Framework.Assert.AreEqual(expectRelation, path.Relation.ToString(), "on-relation-checking: " + src);
            NUnit.Framework.Assert.AreEqual(!System.String.IsNullOrEmpty(expectRelation), path.HasRelation, "on-hasRelation-checking: " + src);
            NUnit.Framework.Assert.AreEqual(expectName, path.Name.ToString(), "on-name-checking: " + src);
            NUnit.Framework.Assert.AreEqual(expectSingleExtention, path.SingleExtention.ToString(), "on-singleExt-checking: " + src);
            NUnit.Framework.Assert.AreEqual(expectMultiExtention, path.MultiExtention.ToString(), "on-multiExt-checking: " + src);
            NUnit.Framework.Assert.AreEqual(!System.String.IsNullOrEmpty(expectSingleExtention), path.HasExtention, "on-hasExt-checking: " + src);
            NUnit.Framework.Assert.AreEqual(expectIsEmpty, path.IsEmpty, "on-isEmpty-checking: " + src);
            NUnit.Framework.Assert.AreEqual(expectIsRelativeOnly, path.IsRelativeOnly, "on-isRelative-checking: " + src);
            NUnit.Framework.Assert.AreEqual(expectIsRootOnly, path.IsRootOnly, "on-isRootOnly-checking: " + src);
            return path;
        }

        public class StatusChecker
        {
            public System.String expectPath;
            public System.String expectRoot;
            public System.String expectRelation;
            public System.String expectName;
            public System.String expectSingleExtention;
            public System.String expectMultiExtention;
            bool? expectIsEmpty;
            bool? expectIsRelativeOnly;
            bool? expectIsRootOnly;
            public Path Check(System.String checkPayload) { return Check(checkPayload, new Path(checkPayload)); }
            public Path Check(Path checkTarget) { return Check(checkTarget.ToString(), checkTarget); }
            public Path Check(System.String checkPayload, Path checkTarget)
            {
                if (expectIsEmpty.HasValue == false)
                    expectIsEmpty = System.String.IsNullOrEmpty(expectPath);

                if (expectIsRelativeOnly.HasValue == false)
                    expectIsRelativeOnly = System.String.IsNullOrEmpty(expectRoot) && (System.String.IsNullOrEmpty(expectRelation) == false);

                if (expectIsRootOnly.HasValue == false)
                    expectIsRootOnly = (System.String.IsNullOrEmpty(expectRoot) == false) && System.String.IsNullOrEmpty(expectRelation);

                NUnit.Framework.Assert.AreEqual(false, ((checkTarget == null) || (checkPayload == null)), "null-parameter-exception");
                NUnit.Framework.Assert.AreEqual(expectPath, checkTarget.ToString(), "on-checkTarget-checking: " + checkPayload);
                NUnit.Framework.Assert.AreEqual(expectRoot, checkTarget.Root.ToString(), "on-root-checking: " + checkPayload);
                NUnit.Framework.Assert.AreEqual(!System.String.IsNullOrEmpty(expectRoot), checkTarget.HasRoot, "on-hasRoot-checking: " + checkPayload);
                NUnit.Framework.Assert.AreEqual(expectRelation, checkTarget.Relation.ToString(), "on-relation-checking: " + checkPayload);
                NUnit.Framework.Assert.AreEqual(!System.String.IsNullOrEmpty(expectRelation), checkTarget.HasRelation, "on-hasRelation-checking: " + checkPayload);
                NUnit.Framework.Assert.AreEqual(expectName, checkTarget.Name.ToString(), "on-name-checking: " + checkPayload);
                NUnit.Framework.Assert.AreEqual(expectSingleExtention, checkTarget.SingleExtention.ToString(), "on-singleExt-checking: " + checkPayload);
                NUnit.Framework.Assert.AreEqual(expectMultiExtention, checkTarget.MultiExtention.ToString(), "on-multiExt-checking: " + checkPayload);
                NUnit.Framework.Assert.AreEqual(!System.String.IsNullOrEmpty(expectSingleExtention), checkTarget.HasExtention, "on-hasExt-checking: " + checkPayload);
                NUnit.Framework.Assert.AreEqual(expectIsEmpty.Value, checkTarget.IsEmpty, "on-isEmpty-checking: " + checkPayload);
                NUnit.Framework.Assert.AreEqual(expectIsRelativeOnly.Value, checkTarget.IsRelativeOnly, "on-isRelative-checking: " + checkPayload);
                NUnit.Framework.Assert.AreEqual(expectIsRootOnly.Value, checkTarget.IsRootOnly, "on-isRootOnly-checking: " + checkPayload);
                return checkTarget;
            }
        }

    }
}
