//===-- 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"

using namespace lldb_vscode;
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, 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;
    }
  }
}

Optional<ProgressEvent> ProgressEvent::Create(uint64_t progress_id,
                                              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 None;
  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 None;

  if (prev_event && prev_event->EqualsForIDE(event))
    return None;

  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 {
  if (m_event_type == progressStart)
    return "progressStart";
  else if (m_event_type == progressEnd)
    return "progressEnd";
  else
    return "progressUpdate";
}

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;
  progress_id_strm.flush();
  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 (Optional<ProgressEvent> event = ProgressEvent::Create(
          progress_id, None, 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 (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);
  }
}
