using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using FluentAssertions;
using MontoyaTech.Rest.Net;
using Xunit;

namespace MontoyaTech.Rest.Net.Tests
{
    public class ServeFileTests
    {
        public string BaseDirectory = null;

        public string TestDirectory = null;

        public string TestFile = null;

        public string IndexFile = null;

        public ServeFileTests()
        {
            this.BaseDirectory = Path.Combine(Environment.CurrentDirectory, "test");

            if (!Directory.Exists(this.BaseDirectory))
                Directory.CreateDirectory(this.BaseDirectory);

            this.TestDirectory = Path.Combine(this.BaseDirectory, "test2");

            if (!Directory.Exists(this.TestDirectory))
                Directory.CreateDirectory(this.TestDirectory);

            this.TestFile = Path.Combine(this.BaseDirectory, "test.html");

            if (!File.Exists(this.TestFile))
                File.WriteAllText(this.TestFile, "hello world");

            this.IndexFile = Path.Combine(this.BaseDirectory, "index.html");

            if (!File.Exists(this.IndexFile))
                File.WriteAllText(this.IndexFile, "hello world");
        }

        [Fact]
        public void ServeMultiple_File_ShouldWork()
        {
            HttpListenerResponseExtensions.ResolveMultiPagePath(this.BaseDirectory, null, "/test.html", "index.html", out string resolvedPath, out bool isDirectory).Should().BeTrue();

            isDirectory.Should().BeFalse();

            resolvedPath.Should().BeEquivalentTo(this.TestFile);
        }

        [Fact]
        public void ServeMultiple_Directory_ShouldWork()
        {
            HttpListenerResponseExtensions.ResolveMultiPagePath(this.BaseDirectory, null, "/test2", "index.html", out string resolvedPath, out bool isDirectory).Should().BeTrue();

            isDirectory.Should().BeTrue();

            resolvedPath.Should().BeEquivalentTo(this.TestDirectory);
        }

        [Fact]
        public void ServeMultiple_NavigatingUp_Should_NotWork()
        {
            HttpListenerResponseExtensions.ResolveMultiPagePath(this.BaseDirectory, null, "../test.html", "index.html", out string resolvedPath, out bool isDirectory).Should().BeFalse();
        }

        [Fact]
        public void ServeMultiple_Correct_NavigatingUp_Should_Work()
        {
            HttpListenerResponseExtensions.ResolveMultiPagePath(this.BaseDirectory, null, "a/b/../../test.html", "index.html", out string resolvedPath, out bool isDirectory).Should().BeTrue();

            isDirectory.Should().BeFalse();

            resolvedPath.Should().BeEquivalentTo(this.TestFile);
        }

        [Fact]
        public void ServeMultiple_NavigatingUp_Multiple_Should_NotWork()
        {
            HttpListenerResponseExtensions.ResolveMultiPagePath(this.BaseDirectory, null, "test/../../test.html", "index.html", out string resolvedPath, out bool isDirectory).Should().BeFalse();
        }

        [Fact]
        public void ServeSingle_Empty_Should_Work()
        {
            HttpListenerResponseExtensions.ResolveSinglePagePath(this.BaseDirectory, null, "", "index.html", out string resolvedPath, out bool isDirectory).Should().BeTrue();

            isDirectory.Should().BeFalse();

            resolvedPath.Should().BeEquivalentTo(this.IndexFile);
        }

        [Fact]
        public void ServeSingle_File_Should_Work()
        {
            HttpListenerResponseExtensions.ResolveSinglePagePath(this.BaseDirectory, null, "/test.html", "index.html", out string resolvedPath, out bool isDirectory).Should().BeTrue();

            isDirectory.Should().BeFalse();

            resolvedPath.Should().BeEquivalentTo(this.TestFile);
        }

        [Fact]
        public void ServeSingle_Directory_Should_Work()
        {
            HttpListenerResponseExtensions.ResolveSinglePagePath(this.BaseDirectory, null, "/test2", "index.html", out string resolvedPath, out bool isDirectory).Should().BeTrue();

            isDirectory.Should().BeTrue();

            resolvedPath.Should().BeEquivalentTo(this.TestDirectory);
        }

        [Fact]
        public void ServeSingle_File_Route_Should_Work()
        {
            HttpListenerResponseExtensions.ResolveSinglePagePath(this.BaseDirectory, null, "/a/b/test.html", "index.html", out string resolvedPath, out bool isDirectory).Should().BeTrue();

            isDirectory.Should().BeFalse();

            resolvedPath.Should().BeEquivalentTo(this.TestFile);
        }

        [Fact]
        public void ServeSingle_Directory_Route_Should_Work()
        {
            HttpListenerResponseExtensions.ResolveSinglePagePath(this.BaseDirectory, null, "/a/b/test2", "index.html", out string resolvedPath, out bool isDirectory).Should().BeTrue();

            isDirectory.Should().BeTrue();

            resolvedPath.Should().BeEquivalentTo(this.TestDirectory);
        }

        [Fact]
        public void ServeSingle_File_Route_Invalid_Should_Work()
        {
            HttpListenerResponseExtensions.ResolveSinglePagePath(this.BaseDirectory, null, "/a/b/c", "index.html", out string resolvedPath, out bool isDirectory).Should().BeTrue();

            isDirectory.Should().BeFalse();

            resolvedPath.Should().BeEquivalentTo(this.IndexFile);
        }

        [Fact]
        public void ServeSingle_File_WithoutExtension_Should_Work()
        {
            HttpListenerResponseExtensions.ResolveSinglePagePath(this.BaseDirectory, null, "/test", "index.html", out string resolvedPath, out bool isDirectory).Should().BeTrue();

            isDirectory.Should().BeFalse();

            resolvedPath.Should().BeEquivalentTo(this.TestFile);
        }

        [Fact]
        public void ServeSingle_File_Route_WithoutExtension_Should_Work()
        {
            HttpListenerResponseExtensions.ResolveSinglePagePath(this.BaseDirectory, null, "/a/b/c/test", "index.html", out string resolvedPath, out bool isDirectory).Should().BeTrue();

            isDirectory.Should().BeFalse();

            resolvedPath.Should().BeEquivalentTo(this.TestFile);
        }

        [Fact]
        public void ServeSingle_File_StartPath_Should_Work()
        {
            HttpListenerResponseExtensions.ResolveSinglePagePath(this.BaseDirectory, "/test", "test/test.html", "index.html", out string resolvedPath, out bool isDirectory).Should().BeTrue();

            isDirectory.Should().BeFalse();

            resolvedPath.Should().BeEquivalentTo(this.TestFile);
        }
    }
}