using Voile.Utils;

namespace Voile.VFS;

/// <summary>
/// A file in the OS file system.
/// </summary>
public class FileSystemFile : VirtualFile
{
    public FileSystemFile(string path)
    {
        _fsPath = path;
    }

    public override Stream GetStream()
    {
        return new FileStream(_fsPath, FileMode.Open, FileAccess.Read, FileShare.ReadWrite | FileShare.Delete);
    }

    private string _fsPath;
}

/// <summary>
/// A <see cref="IVirtualMountPoint"/> implementation for an OS file system.
/// </summary>
public class FileSystemMountPoint : IVirtualMountPoint
{
    public int Order => int.MaxValue;

    public FileSystemMountPoint(string path)
    {
        _fsPath = path;
    }

    public void Mount()
    {
        _logger.Info($"Mounting from file system path \"{_fsPath}\".");

        int rootLength = _fsPath.Length;
        var files =
            Directory.GetFiles(_fsPath, "*", SearchOption.AllDirectories)
                .Select(p => p.Remove(0, rootLength))
                .ToList();

        foreach (string file in files)
        {
            var relativePath = NormalizePath(file);
            var fullPath = NormalizePath(Path.Combine(_fsPath, file));
            _files[relativePath] = new FileSystemFile(fullPath);
        }
    }

    public VirtualFile GetFile(string path) => _files[path];

    public IDictionary<string, VirtualFile> GetFiles() => _files;

    public bool HasFile(string path) => _files.ContainsKey(path);

    private string NormalizePath(string path)
    {
        return path
            .Replace(@"\\", @"\")
            .Replace(@"\", @"/");
    }

    private Logger _logger = new(nameof(FileSystemMountPoint));
    private string _fsPath;
    private Dictionary<string, VirtualFile> _files = new();
}