#ifndef ORIGINCAR_BASE_LOG_HPP_
#define ORIGINCAR_BASE_LOG_HPP_

#include <chrono>
#include <cstdint>
#include <fstream>
#include <limits>
#include <string>
#include <unordered_map>

namespace origincar_base_logging
{
class ScanOdomTimingLogger
{
public:
  using Clock = std::chrono::steady_clock;
  using TimePoint = Clock::time_point;

  explicit ScanOdomTimingLogger(
      const std::string &node_name,
      const std::string &base_log_dir = "/home/sunrise/yiliao_ws/running_logs",
      TimePoint start_time = Clock::now());

  uint64_t startFrame(TimePoint now = Clock::now());
  bool finishFrame(uint64_t frame_id, TimePoint now = Clock::now());
  bool cancelFrame(uint64_t frame_id, const std::string &reason, TimePoint now = Clock::now());
  bool makeSummaryLineIfDue(TimePoint now, std::string *line);
  void setPrintToTerminal(bool enabled);
  bool printToTerminal() const;

  const std::string &logPath() const;
  bool isOpen() const;

private:
  struct Stats
  {
    uint64_t count{0};
    double total_ms{0.0};
    double min_ms{std::numeric_limits<double>::max()};
    double max_ms{0.0};
    double last_ms{0.0};
  };

  std::string makeLogPath(const std::string &node_name, const std::string &base_log_dir) const;
  void writeFinishedFrame(uint64_t frame_id, double duration_ms);
  void writeCanceledFrame(uint64_t frame_id, double elapsed_ms, const std::string &reason);
  std::string formatStatsLine(const std::string &prefix) const;

  std::unordered_map<uint64_t, TimePoint> active_frames_;
  uint64_t next_frame_id_{1};
  Stats stats_;
  TimePoint last_summary_time_;
  std::string log_path_;
  std::ofstream log_file_;
  bool print_to_terminal_{false};
};
}  // namespace origincar_base_logging

#endif  // ORIGINCAR_BASE_LOG_HPP_
