#pragma once

#include <atomic>
#include <memory>
#include <span>
#include <string>
#include <unordered_map>
#include <vector>

#include "processor_interface.hpp"
#include "processing_live_config.hpp"
#include "run_config.hpp"
#include "shm_ring.hpp"

namespace radar::processing {

using ProcessorRegistry = std::unordered_map<std::string, std::unique_ptr<ProcessorInterface>>;

class DataProcessor {
  public:
    DataProcessor(
        const config::RunConfig& config,
        ipc::ShmRing& preprocessed_ring,
        ipc::ShmRing& results_ring,
        ProcessorRegistry processors
    );

    void run(const std::atomic<bool>& stop_requested);

  private:
    [[nodiscard]] auto process_collection(
        const ipc::PreprocessedCollection& preprocessed,
        std::span<const ipc::PreprocessedCollection> previous_collections,
        ProcessorInterface& processor,
        const ProcessingLiveConfig& live_config
    ) -> ipc::ResultCollection;

    [[nodiscard]] auto resolve_processor(const ProcessingLiveConfig& live_config) -> ProcessorInterface&;
    [[nodiscard]] auto should_replay_entire_history(const ProcessingLiveConfig& live_config) const -> bool;

    const config::RunConfig& config_;
    ipc::ShmRing& preprocessed_ring_;
    ipc::ShmRing& results_ring_;
    ProcessorRegistry processors_{};
    std::string default_processor_mode_{};
    ProcessingLiveConfigLoader live_config_loader_;
};

[[nodiscard]] auto create_default_processors() -> ProcessorRegistry;

}  // namespace radar::processing
