
#pragma once
#include "./basic_types.hpp"
#include "./workspace.hpp"

namespace lsp::protocol
{
    using FileOperationPatternKind = std::string_view;
    namespace FileOperationPatternKindLiterals
    {
        inline constexpr FileOperationPatternKind File = "file";
        inline constexpr FileOperationPatternKind Folder = "folder";
    }

    struct FileOperationPatternOptions
    {
        std::optional<boolean> ignoreCase;
    };

    struct FileOperationPattern
    {
        string glob;
        std::optional<FileOperationPatternKind> matches;
        std::optional<FileOperationPatternOptions> options;
    };

    struct FileOperationFilter
    {
        std::optional<string> scheme;
        FileOperationPattern pattern;
    };

    struct FileCreate
    {
        string uri;
    };

    struct CreateFilesParams
    {
        std::vector<FileCreate> files;
    };

    struct FileOperationRegistrationOptions
    {
        std::vector<FileOperationFilter> filters;
    };

    struct FileRename
    {
        string oldUri;
        string newUri;
    };

    struct RenameFilesParams
    {
        std::vector<FileRename> files;
    };

    struct FileDelete
    {
        string uri;
    };

    struct DeleteFilesParams
    {
        std::vector<FileDelete> files;
    };

    // File Watching
    struct DidChangeWatchedFilesClientCapabilities
    {
        std::optional<boolean> dynamicRegistration;
        std::optional<boolean> relativePatternSupport;
    };

    using Pattern = string;

    struct RelativePattern
    {
        std::variant<WorkspaceFolder, URI> baseUri;
        Pattern pattern;
    };

    using GlobPattern = std::variant<Pattern, RelativePattern>;

    enum class WatchKind
    {
        Create = 1,
        Change = 2,
        Delete = 4
    };

    struct FileSystemWatcher
    {
        GlobPattern globPattern;
        std::optional<WatchKind> kind;
    };

    struct DidChangeWatchedFilesRegistrationOptions
    {
        std::vector<FileSystemWatcher> watchers;
    };

    enum class FileChangeType
    {
        Created = 1,
        Changed = 2,
        Deleted = 3
    };

    struct FileEvent
    {
        DocumentUri uri;
        FileChangeType type;
    };

    struct DidChangeWatchedFilesParams
    {
        std::vector<FileEvent> changes;
    };

}
