// Copyright chenyy 2026. Licensed under the MIT License.
// Async detector for armor_yolo_detect
//
// Uses a separate processing thread with an async queue to reduce data blocking.
// Combined with ROI cache to reduce YOLO inference frequency.
//
// Copyright (C) FYT Vision Group. All rights reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

#ifndef ARMOR_YOLO_DETECT_ASYNC_DETECTOR_HPP_
#define ARMOR_YOLO_DETECT_ASYNC_DETECTOR_HPP_

#include <memory>
#include <string>
#include <vector>
#include <deque>
#include <mutex>
#include <condition_variable>
#include <thread>
#include <atomic>

#include <opencv2/core.hpp>
// project
#include "armor_yolo_detect/armor_yolo_detector.hpp"
#include "armor_detector/types.hpp"

namespace armor_yolo_detect {

struct AsyncFrame {
  cv::Mat img;
  uint64_t frame_id;
  std::chrono::steady_clock::time_point timestamp;
};

class AsyncDetector {
public:
  AsyncDetector();
  ~AsyncDetector();

  // Initialize with a existing detector
  void init(std::shared_ptr<Detector> detector, int queue_size = 3);

  // Start async processing thread
  void start();

  // Stop async processing thread
  void stop();

  // Enqueue a frame for async processing
  void enqueue(const cv::Mat& img);

  // Get latest detection result (non-blocking)
  std::vector<fyt::auto_aim::Armor> getLatestResult();

  // Check if processing is running
  bool isRunning() const { return running_; }

  // Get queue size
  size_t queueSize() const {
    std::lock_guard<std::mutex> lock(queue_mutex_);
    return frame_queue_.size();
  }

private:
  void processingLoop();

  // Shared detector pointer
  std::shared_ptr<Detector> detector_;

  // Frame queue
  std::deque<AsyncFrame> frame_queue_;
  size_t max_queue_size_ = 3;

  // Processing thread
  std::thread processing_thread_;
  std::atomic<bool> running_{false};

  // Synchronization
  std::mutex queue_mutex_;
  std::condition_variable queue_cv_;

  // Latest result
  std::vector<fyt::auto_aim::Armor> latest_result_;
  std::mutex result_mutex_;
};

}  // namespace armor_yolo_detect

#endif  // ARMOR_YOLO_DETECT_ASYNC_DETECTOR_HPP_
