#pragma once

#include <cstdint>
#include <memory>
#include <optional>
#include <span>
#include <vector>

#include "application/actions/UiActionDispatcher.h"
#include "application/config/ConfigCommandProcessor.h"
#include "application/config/ConfigDiagnostics.h"
#include "application/config/ConfigOwner.h"
#include "application/config/ConfigPersistence.h"
#include "application/config/ConfigRegistry.h"
#include "application/config/values/KeybindValue.h"
#include "application/config/values/TextValues.h"
#include "application/contracts/ILocaleController.h"
#include "application/contracts/ConfigUiTypes.h"
#include "foundation/concurrency/CommandQueue.h"
#include "foundation/concurrency/CopySnapshotPublisher.h"
#include "foundation/concurrency/SharedSnapshotPublisher.h"

namespace ta::application::config
{
    struct ConfigSettingsSnapshot final
    {
        int menu_key = 0x2D;
    };

    class ConfigService final : public ConfigOwner
    {
    public:
        ConfigService(std::span<ConfigOwner* const> owners,
                      ta::application::IConfigPersistence& persistence,
                      ta::application::ILocaleController& locale,
                      ta::application::UiActionDispatcher& actions);

        void initialize();
        void update();
        void submit(ta::ui::ConfigCommand command);
        void apply_pending_commands();

        [[nodiscard]] std::optional<ConfigSettingsSnapshot> latest_settings() const;
        [[nodiscard]] std::shared_ptr<const ta::ui::ConfigUiSnapshot> latest_ui_snapshot() const noexcept;
        [[nodiscard]] ConfigDiagnosticsSnapshot diagnostics_snapshot() const noexcept { return diagnostics_.snapshot(); }

    private:
        void apply_language();
        void publish_settings();
        void publish_ui();

        RegisteredConfigValue<KeybindValue> menu_key_;
        RegisteredConfigValue<SelectValue> language_;
        std::vector<ConfigOwner*> owners_;
        ta::application::ILocaleController& locale_;
        ConfigDiagnostics diagnostics_;
        ConfigRegistry registry_;
        ConfigCommandProcessor command_processor_;
        ConfigPersistence persistence_;
        ta::foundation::CommandQueue<ta::ui::ConfigCommand> commands_;
        ta::foundation::CopySnapshotPublisher<ConfigSettingsSnapshot> settings_snapshot_;
        ta::foundation::SharedSnapshotPublisher<ta::ui::ConfigUiSnapshot> ui_snapshot_;
        int saved_language_index_ = 0;
        std::optional<int> published_menu_key_;
        std::uint64_t saved_revision_ = 0;
        std::uint64_t published_ui_revision_ = 0;
        bool ui_snapshot_published_ = false;
        bool persistence_save_error_logged_ = false;
    };
}
