//===-- ProgressEvent.cpp ---------------------------------------*- C++ -*-===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//

#include "ProgressEvent.h"

#include "JSONUtils.h"
#include "llvm/Support/ErrorHandling.h"
#include <optional>

using namespace lldb_dap;
using namespace llvm;

// The minimum duration of an event for it to be reported
const std::chrono::duration<double> kStartProgressEventReportDelay =
    std::chrono::seconds(1);
// The minimum time interval between update events for reporting. If multiple
// updates fall within the same time interval, only the latest is reported.
const std::chrono::duration<double> kUpdateProgressEventReportDelay =
    std::chrono::milliseconds(250);

ProgressEvent::ProgressEvent(uint64_t progress_id,
                             std::optional<StringRef> message,
                             uint64_t completed, uint64_t total,
                             const ProgressEvent *prev_event)
    : m_progress_id(progress_id) {
  if (message)
    m_message = message->str();

  const bool calculate_percentage = total != UINT64_MAX;
  if (completed == 0) {
    // Start event
    m_event_type = progressStart;
    // Wait a bit before reporting the start event in case in completes really
    // quickly.
    m_minimum_allowed_report_time =
        m_creation_time + kStartProgressEventReportDelay;
    if (calculate_percentage)
      m_percentage = 0;
  } else if (completed == total) {
    // End event
    m_event_type = progressEnd;
    // We should report the end event right away.
    m_minimum_allowed_report_time = std::chrono::seconds::zero();
    if (calculate_percentage)
      m_percentage = 100;
  } else {
    // Update event
    m_event_type = progressUpdate;
    m_percentage = std::min(
        (uint32_t)((double)completed / (double)total * 100.0), (uint32_t)99);
    if (prev_event->Reported()) {
      // Add a small delay between reports
      m_minimum_allowed_report_time =
          prev_event->m_minimum_allowed_report_time +
          kUpdateProgressEventReportDelay;
    } else {
      // We should use the previous timestamp, as it's still pending
      m_minimum_allowed_report_time = prev_event->m_minimum_allowed_report_time;
    }
  }
}

std::optional<ProgressEvent>
ProgressEvent::Create(uint64_t progress_id, std::optional<StringRef> message,
                      uint64_t completed, uint64_t total,
                      const ProgressEvent *prev_event) {
  // If it's an update without a previous event, we abort
  if (completed > 0 && completed < total && !prev_event)
    return std::nullopt;
  ProgressEvent event(progress_id, message, completed, total, prev_event);
  // We shouldn't show unnamed start events in the IDE
  if (event.GetEventType() == progressStart && event.GetEventName().empty())
    return std::nullopt;

  if (prev_event && prev_event->EqualsForIDE(event))
    return std::nullopt;

  return event;
}

bool ProgressEvent::EqualsForIDE(const ProgressEvent &other) const {
  return m_progress_id == other.m_progress_id &&
         m_event_type == other.m_event_type &&
         m_percentage == other.m_percentage;
}

ProgressEventType ProgressEvent::GetEventType() const { return m_event_type; }

StringRef ProgressEvent::GetEventName() const {
  switch (m_event_type) {
  case progressStart:
    return "progressStart";
  case progressUpdate:
    return "progressUpdate";
  case progressEnd:
    return "progressEnd";
  }
  llvm_unreachable("All cases handled above!");
}

json::Value ProgressEvent::ToJSON() const {
  llvm::json::Object event(CreateEventObject(GetEventName()));
  llvm::json::Object body;

  std::string progress_id_str;
  llvm::raw_string_ostream progress_id_strm(progress_id_str);
  progress_id_strm << m_progress_id;
  body.try_emplace("progressId", progress_id_str);

  if (m_event_type == progressStart) {
    EmplaceSafeString(body, "title", m_message);
    body.try_emplace("cancellable", false);
  }

  std::string timestamp(llvm::formatv("{0:f9}", m_creation_time.count()));
  EmplaceSafeString(body, "timestamp", timestamp);

  if (m_percentage)
    body.try_emplace("percentage", *m_percentage);

  event.try_emplace("body", std::move(body));
  return json::Value(std::move(event));
}

bool ProgressEvent::Report(ProgressEventReportCallback callback) {
  if (Reported())
    return true;
  if (std::chrono::system_clock::now().time_since_epoch() <
      m_minimum_allowed_report_time)
    return false;

  m_reported = true;
  callback(*this);
  return true;
}

bool ProgressEvent::Reported() const { return m_reported; }

ProgressEventManager::ProgressEventManager(
    const ProgressEvent &start_event,
    ProgressEventReportCallback report_callback)
    : m_start_event(start_event), m_finished(false),
      m_report_callback(report_callback) {}

bool ProgressEventManager::ReportIfNeeded() {
  // The event finished before we were able to report it.
  if (!m_start_event.Reported() && Finished())
    return true;

  if (!m_start_event.Report(m_report_callback))
    return false;

  if (m_last_update_event)
    m_last_update_event->Report(m_report_callback);
  return true;
}

const ProgressEvent &ProgressEventManager::GetMostRecentEvent() const {
  return m_last_update_event ? *m_last_update_event : m_start_event;
}

void ProgressEventManager::Update(uint64_t progress_id, uint64_t completed,
                                  uint64_t total) {
  if (std::optional<ProgressEvent> event = ProgressEvent::Create(
          progress_id, std::nullopt, completed, total, &GetMostRecentEvent())) {
    if (event->GetEventType() == progressEnd)
      m_finished = true;

    m_last_update_event = *event;
    ReportIfNeeded();
  }
}

bool ProgressEventManager::Finished() const { return m_finished; }

ProgressEventReporter::ProgressEventReporter(
    ProgressEventReportCallback report_callback)
    : m_report_callback(report_callback) {
  m_thread_should_exit = false;
  m_thread = std::thread([&] {
    while (!m_thread_should_exit) {
      std::this_thread::sleep_for(kUpdateProgressEventReportDelay);
      ReportStartEvents();
    }
  });
}

ProgressEventReporter::~ProgressEventReporter() {
  m_thread_should_exit = true;
  m_thread.join();
}

void ProgressEventReporter::ReportStartEvents() {
  std::lock_guard<std::mutex> locker(m_mutex);

  while (!m_unreported_start_events.empty()) {
    ProgressEventManagerSP event_manager = m_unreported_start_events.front();
    if (event_manager->Finished())
      m_unreported_start_events.pop();
    else if (event_manager->ReportIfNeeded())
      m_unreported_start_events
          .pop(); // we remove it from the queue as it started reporting
                  // already, the Push method will be able to continue its
                  // reports.
    else
      break; // If we couldn't report it, then the next event in the queue won't
             // be able as well, as it came later.
  }
}

void ProgressEventReporter::Push(uint64_t progress_id, const char *message,
                                 uint64_t completed, uint64_t total) {
  std::lock_guard<std::mutex> locker(m_mutex);

  auto it = m_event_managers.find(progress_id);
  if (it == m_event_managers.end()) {
    if (std::optional<ProgressEvent> event = ProgressEvent::Create(
            progress_id, StringRef(message), completed, total)) {
      ProgressEventManagerSP event_manager =
          std::make_shared<ProgressEventManager>(*event, m_report_callback);
      m_event_managers.insert({progress_id, event_manager});
      m_unreported_start_events.push(event_manager);
    }
  } else {
    it->second->Update(progress_id, completed, total);
    if (it->second->Finished())
      m_event_managers.erase(it);
  }
}
