#pragma once

#include <atomic>
#include <utility>
#include <vector>

#include "application/contracts/IApplicationTick.h"
#include "application/contracts/IGameTick.h"
#include "features/items/contracts/IItemCommands.h"
#include "features/items/contracts/IItemQueries.h"
#include "features/items/dependencies/IItemGateway.h"
#include "features/items/dependencies/IItemSettings.h"
#include "features/items/ItemDiagnostics.h"
#include "foundation/concurrency/CoalescingCommandSlot.h"
#include "foundation/concurrency/CommandQueue.h"
#include "features/common/SettingsCache.h"

namespace ta::features::items
{
    class ItemFeature final : public ta::application::IApplicationTick,
                              public ta::application::IGameTick,
                              public contracts::IItemQueries,
                              public contracts::IItemCommands
    {
    public:
        ItemFeature(dependencies::IItemGateway& gateway, dependencies::IItemSettings& settings) noexcept
            : gateway_(gateway), settings_(settings)
        {
        }

        void initialize();
        void on_application_tick() override;
        void on_game_tick() override;
        void reset_session() noexcept;

        [[nodiscard]] std::shared_ptr<const ta::features::items::contracts::ItemCatalogSnapshot> catalog() const noexcept override;
        [[nodiscard]] bool in_raid() const noexcept override;
        [[nodiscard]] std::uint64_t navigation_revision() const noexcept override;
        void open_selector() override;
        void set_selector_active(bool active) override;
        void submit_selector(ta::features::items::contracts::ItemSelectorCommand command) override;
        void request_action(ta::features::items::contracts::ItemActionCommand command) override;
        [[nodiscard]] ItemDiagnosticsSnapshot diagnostics_snapshot() const noexcept { return diagnostics_.snapshot(); }

    private:
        [[nodiscard]] ta::features::items::contracts::ItemSettings current_settings() const;
        [[nodiscard]] std::vector<ta::features::items::contracts::ItemSelectorCommand> drain_selector_commands();

        dependencies::IItemGateway& gateway_;
        dependencies::IItemSettings& settings_;
        ta::features::SettingsCache<ta::features::items::contracts::ItemSettings> settings_cache_;
        ta::foundation::CommandQueue<ta::features::items::contracts::ItemSelectorCommand> selector_commands_;
        ta::foundation::CoalescingCommandSlot<ta::features::items::contracts::ItemActionCommand> action_commands_;
        std::atomic<std::uint64_t> navigation_revision_{0};
        ItemDiagnostics diagnostics_;
    };
}
