#pragma once
#include <memory>
#include <vector>
#include <shared_mutex>
#include "../protocol/protocol.hpp"
#include "../provider/base/interface.hpp"

namespace lsp::core
{

    class RequestDispatcher
    {
    public:
        RequestDispatcher();
        ~RequestDispatcher() = default;

        void SetRequestScheduler(scheduler::AsyncExecutor* scheduler);
        void SetSeviceRegistry(service::Registry* service_registry);

        void RegisterRequestProvider(std::shared_ptr<provider::IRequestProvider> provider);
        void RegisterNotificationProvider(std::shared_ptr<provider::INotificationProvider> provider);

        void RegisterLifecycleCallback(provider::LifecycleCallback callback);

        std::string Dispatch(const protocol::RequestMessage& request);
        void Dispatch(const protocol::NotificationMessage& notification);

        bool SupportsRequest(const std::string& method) const;
        bool SupportsNotification(const std::string& method) const;
        std::vector<std::string> GetSupportedRequests() const;
        std::vector<std::string> GetSupportedNotifications() const;
        std::vector<std::string> GetAllSupportedMethods() const;

    private:
        void NotifyAllLifecycleListeners(provider::ServerLifecycleEvent event);
        std::string HandleUnknownRequest(const protocol::RequestMessage& request);
        void HandleUnknownNotification(const protocol::NotificationMessage& notification);

    private:
        mutable std::shared_mutex providers_mutex_;
        std::unordered_map<std::string, std::shared_ptr<provider::IRequestProvider>> providers_;

        mutable std::shared_mutex notification_providers_mutex_;
        std::unordered_map<std::string, std::shared_ptr<provider::INotificationProvider>> notification_providers_;

        std::mutex callbacks_mutex_;
        std::vector<provider::LifecycleCallback> lifecycle_callbacks_;

        provider::LifecycleCallback context_lifecycle_callback_;

        // 服务引用
        scheduler::AsyncExecutor* async_executor_ = nullptr;
        service::Registry* service_registry_ = nullptr;
    };
}
