#pragma once
#include <cstdint>
#include <limits>
#include <optional>
#include <string>
#include <map>
#include <type_traits>
#include <variant>
#include <vector>

namespace lsp::protocol
{

    using integer = std::int32_t;
    using uinteger = std::uint32_t;
    using decimal = double;
    using boolean = bool;
    using string = std::string;

    // LSPAny 这样设计是为了glaz序列化
    // export type LSPAny = LSPObject | LSPArray | string | integer | uinteger | decimal | boolean | null;
    struct LSPAny;
    using LSPObject = std::map<string, LSPAny>;
    using LSPArray = std::vector<LSPAny>;

    struct LSPAny
    {
        using LSPAnyVariant = std::variant<
            LSPObject,
            LSPArray,
            string,
            integer,
            uinteger,
            decimal,
            boolean,
            std::nullptr_t>;

        LSPAnyVariant value;

        // 默认构造函数
        LSPAny();

        // 拷贝和移动构造函数
        LSPAny(const LSPAny& other);
        LSPAny(LSPAny&& other) noexcept;

        // 容器类型的构造函数
        LSPAny(const LSPObject& val);
        LSPAny(LSPObject&& val);
        LSPAny(const LSPArray& val);
        LSPAny(LSPArray&& val);

        // 字符串类型的构造函数
        LSPAny(const string& val);
        LSPAny(string&& val);
        LSPAny(const char* val);

        // 浮点类型的构造函数 -- decimal
        LSPAny(float val);
        LSPAny(double val);
        LSPAny(long double val);

        // 布尔和空值
        LSPAny(boolean val);
        LSPAny(std::nullptr_t);

        // 单个模板处理所有整数类型
        template<typename T, typename = std::enable_if_t<std::is_integral_v<T> && !std::is_same_v<T, bool> && !std::is_same_v<std::decay_t<T>, char>>>
        LSPAny(T val);

        // 赋值操作符
        LSPAny& operator=(const LSPAny& other);
        LSPAny& operator=(LSPAny&& other) noexcept;
        LSPAny& operator=(const LSPObject& val);
        LSPAny& operator=(LSPObject&& val);
        LSPAny& operator=(const LSPArray& val);
        LSPAny& operator=(LSPArray&& val);

        LSPAny& operator=(const string& val);
        LSPAny& operator=(string&& val);
        LSPAny& operator=(const char* val);

        LSPAny& operator=(float val);
        LSPAny& operator=(double val);
        LSPAny& operator=(long double val);

        LSPAny& operator=(boolean val);
        LSPAny& operator=(std::nullptr_t);

        // 整数类型赋值 - 使用模板避免类型冲突
        template<typename T, typename = std::enable_if_t<std::is_integral_v<T> && !std::is_same_v<T, bool> && !std::is_same_v<std::decay_t<T>, char>>>
        LSPAny& operator=(T val);

        // 类型检查辅助函数
        template<typename T>
        bool Is() const;

        template<typename T>
        T& Get();

        template<typename T>
        const T& Get() const;

        // 访问操作符
        template<typename Visitor>
        auto Visit(Visitor&& visitor) const;

        template<typename Visitor>
        auto Visit(Visitor&& visitor);
    };

    using ProgressToken = std::variant<integer, string>;

    template<typename T>
    struct ProgressParams
    {
        ProgressToken token;
        T value;
    };

    using DocumentUri = string;
    using URI = string;

    struct Position
    {
        uinteger line;
        uinteger character;
    };

    using PositionEncodingKind = std::string_view;
    namespace PositionEncodingKindLiterals
    {
        inline constexpr PositionEncodingKind UTF8 = "utf-8";
        inline constexpr PositionEncodingKind UTF16 = "utf-16";
        inline constexpr PositionEncodingKind UTF32 = "utf-32";
    }

    struct Range
    {
        Position start;
        Position end;
    };

    struct DocumentFilter
    {
        string language;
        string scheme;
        std::optional<string> pattern;
    };

    using DocumentSelector = std::vector<DocumentFilter>;

    struct TextEdit
    {
        Range range;
        string newText;
    };

    struct ChangeAnnotation
    {
        string label;
        boolean needsConfirmation;
        string description;
    };

    using ChangeAnnotationIdentifier = string;

    struct AnnotatedTextEdit : TextEdit
    {
        ChangeAnnotationIdentifier annotationId;
    };

    struct Location
    {
        DocumentUri uri;
        Range range;
    };

    struct LocationLink
    {
        Range originSelectionRange;
        DocumentUri targetUri;
        Range targetRange;
        Range targetSelectionRange;
    };

    struct Command
    {
        string title;
        string command;
        std::optional<LSPAny> arguments;
    };

    struct StringValue
    {
        string kind;
        string value;
    };

    struct SnippetTextEdit
    {
        Range range;
        StringValue snippet;
        std::optional<ChangeAnnotationIdentifier> annotationId;
    };

    enum class ApplyKind
    {
        Replace = 1,
        Merge = 2
    };

    using MarkupKind = std::string_view;
    namespace MarkupKindLiterals
    {
        inline constexpr MarkupKind PlainText = "plaintext";
        inline constexpr MarkupKind Markdown = "markdown";
    };

    struct MarkupContent
    {
        MarkupKind kind;
        string value;
    };

    struct RegularExpressionsClientCapabilities
    {
        string engine;
        std::optional<string> version;
    };

    struct MarkdownClientCapabilities
    {
        string parser;
        std::optional<string> version;
        std::optional<std::vector<string>> allowedTags;
    };

    // LSP模板方法
    template<typename T, typename>
    LSPAny::LSPAny(T val)
    {
        if constexpr (std::is_signed_v<T>)
        {
            // 有符号整数
            if (val >= std::numeric_limits<integer>::min() && val <= std::numeric_limits<integer>::max())
                value = static_cast<integer>(val);
            else
                value = static_cast<decimal>(val); // 超出 int32 范围，转为 decimal（可能丢失精度）
        }
        else
        {
            // 无符号整数
            if (val <= std::numeric_limits<uinteger>::max())
                value = static_cast<uinteger>(val);
            else
                value = static_cast<decimal>(val); // 超出 uint32 范围，转为 decimal（可能丢失精度）
        }
    }

    template<typename T, typename>
    LSPAny& LSPAny::operator=(T val)
    {
        if constexpr (std::is_signed_v<T>)
        {
            // 有符号整数
            if (val >= std::numeric_limits<integer>::min() && val <= std::numeric_limits<integer>::max())
                value = static_cast<integer>(val);
            else
                value = static_cast<decimal>(val);
        }
        else
        {
            if (val <= std::numeric_limits<uinteger>::max())
                value = static_cast<uinteger>(val);
            else
                value = static_cast<decimal>(val);
        }
        return *this;
    }

    template<typename T>
    bool LSPAny::Is() const
    {
        return std::holds_alternative<T>(value);
    }

    template<typename T>
    T& LSPAny::Get()
    {
        return std::get<T>(value);
    }

    template<typename T>
    const T& LSPAny::Get() const
    {
        return std::get<T>(value);
    }

    // 访问操作符
    template<typename Visitor>
    auto LSPAny::Visit(Visitor&& visitor) const
    {
        return std::visit(std::forward<Visitor>(visitor), value);
    }

    template<typename Visitor>
    auto LSPAny::Visit(Visitor&& visitor)
    {
        return std::visit(std::forward<Visitor>(visitor), value);
    }

}

#include "./lsp_any.inl"
