// Copyright 2021 The Fuchsia Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "src/camera/lib/cobalt_logger/logger.h"

#include <lib/async/cpp/task.h>
#include <lib/syslog/cpp/macros.h>
#include <lib/zx/time.h>

#include <string>

#include "src/cobalt/bin/utils/error_utils.h"
#include "src/lib/fxl/strings/string_printf.h"

namespace camera::cobalt {
namespace {

using async::PostDelayedTask;
using ::cobalt::ErrorToString;
using fuchsia::metrics::MetricEventLoggerFactory;
using fxl::StringPrintf;

constexpr uint32_t kMaxPendingEvents = 100000u;

uint64_t CurrentTimeUSecs(const std::unique_ptr<timekeeper::Clock>& clock) {
  return zx::nsec(clock->Now().get()).to_usecs();
}

inline bool HasStreamProperty(fuchsia::camera2::CameraStreamType stream_type,
                              fuchsia::camera2::CameraStreamType target_type) {
  return (stream_type & target_type) == target_type;
}

}  // namespace

Logger::Logger(async_dispatcher_t* dispatcher, std::shared_ptr<sys::ServiceDirectory> services,
               std::unique_ptr<timekeeper::Clock> clock)
    : dispatcher_(dispatcher),
      services_(services),
      clock_(std::move(clock)),
      logger_reconnection_backoff_(/*initial_delay=*/zx::msec(100), /*retry_factor=*/2u,
                                   /*max_delay=*/zx::hour(1)) {
  logger_.set_error_handler([this](zx_status_t status) {
    FX_PLOGS(WARNING, status) << "Lost connection with MetricEventLogger";
    RetryConnectingToLogger();
  });

  auto logger_request = logger_.NewRequest();
  ConnectToLogger(std::move(logger_request));
}

void Logger::Shutdown() {
  shut_down_ = true;

  pending_events_.clear();
  timer_starts_usecs_.clear();

  reconnect_task_.Cancel();

  logger_factory_.Unbind();
  logger_.Unbind();
}

void Logger::ConnectToLogger(
    ::fidl::InterfaceRequest<fuchsia::metrics::MetricEventLogger> logger_request) {
  // Connect to the LoggerFactory.
  logger_factory_ = services_->Connect<fuchsia::metrics::MetricEventLoggerFactory>();

  logger_factory_.set_error_handler([](zx_status_t status) {
    FX_PLOGS(WARNING, status) << "Lost connection with MetricEventLoggerFactory";
  });

  fuchsia::metrics::ProjectSpec project;
  project.set_customer_id(kCustomerId);
  project.set_project_id(kProjectId);

  logger_factory_->CreateMetricEventLogger(
      std::move(project), std::move(logger_request),
      [this](fuchsia::metrics::MetricEventLoggerFactory_CreateMetricEventLogger_Result result) {
        // We don't need a long standing connection to the LoggerFactory so we unbind after
        // setting up the Logger.
        logger_factory_.Unbind();

        if (result.is_response()) {
          logger_reconnection_backoff_.Reset();
        } else if (result.err() == fuchsia::metrics::Error::SHUT_DOWN) {
          FX_LOGS(INFO) << "Stopping sending Cobalt events";
          logger_.Unbind();
        } else {
          FX_LOGS(WARNING) << "Failed to set up Cobalt: " << ErrorToString(result.err());
          logger_.Unbind();
          RetryConnectingToLogger();
        }
      });
}

void Logger::RetryConnectingToLogger() {
  if (logger_) {
    return;
  }

  // Bind |logger_| and immediately send the events that were not acknowledged by the server on the
  // previous connection.
  auto logger_request = logger_.NewRequest();
  SendAllPendingEvents();

  reconnect_task_.Reset([this, request = std::move(logger_request)]() mutable {
    ConnectToLogger(std::move(request));
  });

  PostDelayedTask(
      dispatcher_, [reconnect = reconnect_task_.callback()]() { reconnect(); },
      logger_reconnection_backoff_.GetNext());
}

void Logger::LogEvent(Event event) {
  FX_CHECK(!shut_down_);
  if (pending_events_.size() >= kMaxPendingEvents) {
    FX_LOGS(INFO) << StringPrintf("Dropping Cobalt event %s - too many pending events (%lu)",
                                  event.ToString().c_str(), pending_events_.size());
    return;
  }

  const uint64_t event_id = next_event_id_++;
  pending_events_.insert(std::make_pair(event_id, std::move(event)));
  SendEvent(event_id);
}

uint64_t Logger::StartTimer() {
  FX_CHECK(!shut_down_);

  const uint64_t timer_id = next_event_id_++;
  timer_starts_usecs_.insert(std::make_pair(timer_id, CurrentTimeUSecs(clock_)));
  return timer_id;
}

void Logger::SendEvent(uint64_t event_id) {
  if (!logger_) {
    return;
  }

  if (pending_events_.find(event_id) == pending_events_.end()) {
    return;
  }
  Event& event = pending_events_.at(event_id);

  auto callback = [this, event_id,
                   &event](fuchsia::metrics::MetricEventLogger_LogOccurrence_Result result) {
    if (result.is_err()) {
      FX_LOGS(ERROR) << StringPrintf("Cobalt logging error: status %s, event %s",
                                     ErrorToString(result.err()).c_str(), event.ToString().c_str());
    }

    // We don't retry events that have been acknowledged by the server, regardless of the return
    // status.
    pending_events_.erase(event_id);
  };

  switch (event.GetType()) {
    case EventType::kOccurrence:
      logger_->LogOccurrence(event.GetMetricId(), 1u, event.GetDimensions(), std::move(callback));
      break;

    default:
      FX_LOGS(WARNING) << "Ignores an event with unknown type.";
      break;
  }
}

void Logger::SendAllPendingEvents() {
  for (const auto& [event_id, _] : pending_events_) {
    SendEvent(event_id);
  }
}

uint64_t Logger::GetTimerDurationUSecs(uint64_t timer_id) const {
  FX_CHECK(timer_starts_usecs_.find(timer_id) != timer_starts_usecs_.end());

  return CurrentTimeUSecs(clock_) - timer_starts_usecs_.at(timer_id);
}

StreamType Logger::ConvertStreamType(fuchsia::camera2::CameraStreamType type) {
  if (HasStreamProperty(type, fuchsia::camera2::CameraStreamType::VIDEO_CONFERENCE)) {
    if (HasStreamProperty(type, fuchsia::camera2::CameraStreamType::EXTENDED_FOV)) {
      if (HasStreamProperty(type, fuchsia::camera2::CameraStreamType::FULL_RESOLUTION)) {
        return cobalt::StreamType::kStream5;
      } else {
        return cobalt::StreamType::kStream6;
      }
    } else {
      if (HasStreamProperty(type, fuchsia::camera2::CameraStreamType::FULL_RESOLUTION)) {
        return cobalt::StreamType::kStream3;
      } else {
        return cobalt::StreamType::kStream4;
      }
    }
  } else {
    if (HasStreamProperty(type, fuchsia::camera2::CameraStreamType::MONITORING)) {
      return cobalt::StreamType::kStream2;
    } else if (HasStreamProperty(type, fuchsia::camera2::CameraStreamType::FULL_RESOLUTION)) {
      return cobalt::StreamType::kStream0;
    } else {
      return cobalt::StreamType::kStream1;
    }
  }
}

}  // namespace camera::cobalt
