using System.Linq;

using Nitride.IO.Contents;

using Xunit;
using Xunit.Abstractions;

using Zio;

namespace Nitride.IO.Tests;

/// <summary>
/// Tests the functionality of the ReadFiles().
/// </summary>
public class ReadFilesTest : NitrideIOTestBase
{
    public ReadFilesTest(ITestOutputHelper output)
        : base(output)
    {
    }

    [Fact]
    public void ReadAllFiles()
    {
        // Set up the test and file system.
        using NitrideIOTestContext context = this.CreateContext();

        CreateFileSystem(context);

        // Set up the operation.
        ReadFiles op = context.Resolve<ReadFiles>();

        // Verify the paths.
        IOrderedEnumerable<string> paths = op.WithPattern("/**")
            .Run()
            .Select(x => x.Get<UPath>())
            .Select(x => (string)x)
            .OrderBy(x => x);

        Assert.Equal(
            new[]
            {
                "/a.txt",
                "/b1/b.md",
                "/c1/c.txt",
                "/c1/c2/e.md",
            },
            paths);
    }

    [Fact]
    public void ReadGlob()
    {
        // Set up the test and file system.
        using NitrideIOTestContext context = this.CreateContext();

        CreateFileSystem(context);

        // Set up the operation.
        ReadFiles op = context.Resolve<ReadFiles>().WithPattern("/*.txt");

        // Verify the paths.
        IOrderedEnumerable<string> paths = op.Run().Select(x => (string)x.Get<UPath>()).OrderBy(x => x);

        Assert.Equal(
            new[]
            {
                "/a.txt",
            },
            paths);
    }

    [Fact]
    public void ReadGlobWithSubdirectories()
    {
        // Set up the test and file system.
        using NitrideIOTestContext context = this.CreateContext();

        CreateFileSystem(context);

        // Set up the operation.
        ReadFiles op = context.Resolve<ReadFiles>().WithPattern("**/*.txt");

        // Verify the paths.
        IOrderedEnumerable<string> paths = op.Run().Select(x => (string)x.Get<UPath>()).OrderBy(x => x);

        Assert.Equal(
            new[]
            {
                "/a.txt",
                "/c1/c.txt",
            },
            paths);
    }

    private static void CreateFileSystem(NitrideIOTestContext context)
    {
        IFileSystem fileSystem = context.FileSystem;

        fileSystem.CreateDirectory("/b1");
        fileSystem.CreateDirectory("/c1");
        fileSystem.CreateDirectory("/c1/c2");
        fileSystem.CreateDirectory("/d1");
        fileSystem.WriteAllText("/a.txt", "File A");
        fileSystem.WriteAllText("/b1/b.md", "File B");
        fileSystem.WriteAllText("/c1/c.txt", "File C");
        fileSystem.WriteAllText("/c1/c2/e.md", "File C");
    }
}