// Copyright 2019 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/bin/device/metrics_reporter.h"

#include <lib/async/default.h>
#include <lib/sys/cpp/component_context.h>
#include <lib/syslog/cpp/macros.h>
#include <lib/trace/event.h>

namespace camera {
namespace {

std::mutex factory_mutex;
MetricsReporter* metrics_reporter;
MetricsReporter* metrics_reporter_nop;

inline constexpr const char kConfigurationInspectorActivePropertyName[] = "active";
inline constexpr const char kConfigurationInspectorNodeName[] = "configurations";
inline constexpr const char kFormatInspectorAspectRatioPropertyName[] = "aspect ratio";
inline constexpr const char kFormatInspectorColorSpacePropertyName[] = "color space";
inline constexpr const char kFormatInspectorDisplayResolutionPropertyName[] = "display resolution";
inline constexpr const char kFormatInspectorOutputResolutionPropertyName[] = "output resolution";
inline constexpr const char kFormatInspectorPixelformatPropertyName[] = "pixel format";
inline constexpr const char kStreamInspectorCropPropertyName[] = "supports crop region";
inline constexpr const char kStreamInspectorFrameratePropertyName[] = "frame rate";
inline constexpr const char kStreamInspectorFramesDroppedPropertyName[] = "frames dropped";
inline constexpr const char kStreamInspectorFramesReceivedPropertyName[] = "frames received";
inline constexpr const char kStreamInspectorImageFormatNodeName[] = "image format";
inline constexpr const char kStreamInspectorNodeName[] = "streams";
inline constexpr const char kStreamInspectorResolutionNodeName[] = "supported resolutions";

std::string ConvertPixelFormatToString(const fuchsia::sysmem::PixelFormat& format) {
  switch (format.type) {
    case fuchsia::sysmem::PixelFormatType::R8G8B8A8:
      return "R8G8B8A8";
    case fuchsia::sysmem::PixelFormatType::BGRA32:
      return "BGRA32";
    case fuchsia::sysmem::PixelFormatType::I420:
      return "I420";
    case fuchsia::sysmem::PixelFormatType::M420:
      return "M420";
    case fuchsia::sysmem::PixelFormatType::NV12:
      return "NV12";
    case fuchsia::sysmem::PixelFormatType::YUY2:
      return "YUY2";
    case fuchsia::sysmem::PixelFormatType::MJPEG:
      return "MJPEG";
    case fuchsia::sysmem::PixelFormatType::YV12:
      return "YV12";
    case fuchsia::sysmem::PixelFormatType::BGR24:
      return "BGR24";
    case fuchsia::sysmem::PixelFormatType::RGB565:
      return "RGB565";
    case fuchsia::sysmem::PixelFormatType::RGB332:
      return "RGB332";
    case fuchsia::sysmem::PixelFormatType::RGB2220:
      return "RGB2220";
    case fuchsia::sysmem::PixelFormatType::L8:
      return "L8";
    case fuchsia::sysmem::PixelFormatType::R8:
      return "R8";
    case fuchsia::sysmem::PixelFormatType::R8G8:
      return "R8G8";
    default:
      return "Unknown";
  }
}

std::string ConvertColorSpaceToString(const fuchsia::sysmem::ColorSpace& color_space) {
  switch (color_space.type) {
    case fuchsia::sysmem::ColorSpaceType::INVALID:
      return "INVALID";
    case fuchsia::sysmem::ColorSpaceType::SRGB:
      return "SRGB";
    case fuchsia::sysmem::ColorSpaceType::REC601_NTSC:
      return "REC601_NTSC";
    case fuchsia::sysmem::ColorSpaceType::REC601_NTSC_FULL_RANGE:
      return "REC601_NTSC_FULL_RANGE";
    case fuchsia::sysmem::ColorSpaceType::REC601_PAL:
      return "REC601_PAL";
    case fuchsia::sysmem::ColorSpaceType::REC601_PAL_FULL_RANGE:
      return "REC601_PAL_FULL_RANGE";
    case fuchsia::sysmem::ColorSpaceType::REC709:
      return "REC709";
    case fuchsia::sysmem::ColorSpaceType::REC2020:
      return "REC2020";
    case fuchsia::sysmem::ColorSpaceType::REC2100:
      return "REC2100";
    default:
      return "Unknown";
  }
}

std::string ConvertResolutionToString(size_t width, size_t height) {
  return std::to_string(width) + "x" + std::to_string(height);
}

std::string ConvertResolutionToString(size_t width, size_t height, size_t bpr) {
  std::string output = ConvertResolutionToString(width, height);
  if (bpr > 0) {
    output += ", stride = " + std::to_string(bpr);
  }

  return output;
}

cobalt::StreamType GetStreamType(uint32_t config_index, uint32_t stream_index) {
  switch (config_index) {
    case 0:
      switch (stream_index) {
        case 0:
          return cobalt::StreamType::kStream0;
        case 1:
          return cobalt::StreamType::kStream1;
        case 2:
          return cobalt::StreamType::kStream2;
        default:
          return cobalt::StreamType::kStreamUnknown;
      }
      break;

    case 1:
      switch (stream_index) {
        case 0:
          return cobalt::StreamType::kStream3;
        case 1:
          return cobalt::StreamType::kStream4;
        default:
          return cobalt::StreamType::kStreamUnknown;
      }
      break;

    default:
      return cobalt::StreamType::kStreamUnknown;
  }
}

}  // anonymous namespace

// MetricsReporter implementation
MetricsReporter& MetricsReporter::Get() {
  std::lock_guard<std::mutex> lock(factory_mutex);
  if (metrics_reporter) {
    return *metrics_reporter;
  } else {
    // If the reporter has not initialized yet, we're returning a nop version of it.
    FX_LOGS(WARNING) << "MetricsReporter is not initialized yet.";
    if (!metrics_reporter_nop) {
      metrics_reporter_nop = new MetricsReporter();
    }
    return *metrics_reporter_nop;
  }
}

void MetricsReporter::Initialize(sys::ComponentContext& context, bool enable_cobalt) {
  std::lock_guard<std::mutex> lock(factory_mutex);
  if (metrics_reporter) {
    FX_LOGS(DEBUG) << "MetricsReporter is initialized already.";
    return;
  }

  metrics_reporter = new MetricsReporter(context, enable_cobalt);
  FX_LOGS(INFO) << "MetricsReporter is initialized, enable_cobalt = " << enable_cobalt;
}

MetricsReporter::MetricsReporter(sys::ComponentContext& context, bool enable_cobalt)
    : impl_(std::make_unique<Impl>(context)) {
  InitInspector();
  if (enable_cobalt) {
    impl_->logger_ =
        std::make_unique<cobalt::Logger>(async_get_default_dispatcher(), impl_->context_.svc());
  }
}

void MetricsReporter::InitInspector() {
  // Initializes the inspector and creates the configuration node.
  impl_->inspector_ = std::make_unique<inspect::ComponentInspector>(async_get_default_dispatcher(),
                                                                    inspect::PublishOptions{});
  impl_->node_ = impl_->inspector_->root().CreateChild(kConfigurationInspectorNodeName);
}

MetricsReporter::Impl::Impl(sys::ComponentContext& context) : context_(context) {}

MetricsReporter::ConfigurationRecord::ConfigurationRecord(MetricsReporter::Impl& impl,
                                                          uint32_t index, size_t num_streams)
    : node_(impl.node_.CreateChild(std::to_string(index))),
      active_node_(node_.CreateBool(kConfigurationInspectorActivePropertyName, false)),
      stream_node_(node_.CreateChild(kStreamInspectorNodeName)) {
  // Creates the number of the stream records.
  for (size_t i = 0; i < num_streams; ++i) {
    stream_records_.emplace_back(impl, stream_node_, index, i);
  }
}

std::unique_ptr<MetricsReporter::ConfigurationRecord> MetricsReporter::CreateConfigurationRecord(
    uint32_t index, size_t num_streams) {
  std::lock_guard<std::mutex> lock(mutex_);
  return std::make_unique<ConfigurationRecord>(*impl_, index, num_streams);
}

std::unique_ptr<MetricsReporter::FailureTestRecord> MetricsReporter::CreateFailureTestRecord(
    FailureTestRecordType type, bool initial_failure, std::optional<uint32_t> config_index,
    std::optional<uint32_t> stream_index) {
  std::lock_guard<std::mutex> lock(mutex_);
  return std::make_unique<FailureTestRecord>(*impl_, type, initial_failure, config_index,
                                             stream_index);
}

MetricsReporter::StreamRecord::StreamRecord(MetricsReporter::Impl& impl, inspect::Node& parent,
                                            uint32_t config_index, uint32_t stream_index)
    : impl_(impl),
      node_(parent.CreateChild(std::to_string(stream_index))),
      frame_rate_(node_.CreateString(kStreamInspectorFrameratePropertyName, "")),
      supports_crop_region_(node_.CreateBool(kStreamInspectorCropPropertyName, false)),
      supported_resolutions_node_(node_.CreateChild(kStreamInspectorResolutionNodeName)),
      format_record_(node_),
      frames_received_(node_.CreateUint(kStreamInspectorFramesReceivedPropertyName, 0)),
      frames_dropped_(node_.CreateUint(kStreamInspectorFramesDroppedPropertyName, 0)),
      type_(GetStreamType(config_index, stream_index)) {}

void MetricsReporter::StreamRecord::SetProperties(
    const fuchsia::camera3::StreamProperties2& props) {
  frame_rate_.Set(std::to_string(props.frame_rate().numerator) + "/" +
                  std::to_string(props.frame_rate().denominator));
  supports_crop_region_.Set(props.supports_crop_region());
  supported_resolutions_.clear();
  for (const auto& resolution : props.supported_resolutions()) {
    supported_resolutions_.push_back(supported_resolutions_node_.CreateString(
        std::to_string(resolution.width) + "x" + std::to_string(resolution.height), ""));
  }

  format_record_.Set(props.image_format());
}

void MetricsReporter::StreamRecord::FrameReceived() {
  TRACE_INSTANT("camera", "StreamRecord::FrameReceived", TRACE_SCOPE_THREAD);
  frames_received_.Add(1);
}

void MetricsReporter::StreamRecord::FrameDropped(cobalt::FrameDropReason why) {
  TRACE_INSTANT("camera", "StreamRecord::FrameDropped", TRACE_SCOPE_THREAD, "reason",
                FrameDropReasonToString(why));

  frames_dropped_.Add(1);

  if (!impl_.logger_) {
    return;
  }

  impl_.logger_->LogOccurrence(kCameraFrameDropCountsPerStreamMetricId,
                               cobalt::Logger::BuildDimension(type_, why));
}

MetricsReporter::ImageFormatRecord::ImageFormatRecord(inspect::Node& parent)
    : node_(parent.CreateChild(kStreamInspectorImageFormatNodeName)),
      pixel_format_(node_.CreateString(kFormatInspectorPixelformatPropertyName, "")),
      output_resolution_(node_.CreateString(kFormatInspectorOutputResolutionPropertyName, "")),
      display_resolution_(node_.CreateString(kFormatInspectorDisplayResolutionPropertyName, "")),
      color_space_(node_.CreateString(kFormatInspectorColorSpacePropertyName, "")),
      pixel_aspect_ratio_(node_.CreateString(kFormatInspectorAspectRatioPropertyName, "")) {}

void MetricsReporter::ImageFormatRecord::Set(const fuchsia::sysmem::ImageFormat_2& format) {
  pixel_format_.Set(ConvertPixelFormatToString(format.pixel_format));
  output_resolution_.Set(
      ConvertResolutionToString(format.coded_width, format.coded_height, format.bytes_per_row));
  display_resolution_.Set(
      ConvertResolutionToString(format.display_width, format.display_height, format.display_width));
  color_space_.Set(ConvertColorSpaceToString(format.color_space));
  if (format.has_pixel_aspect_ratio) {
    pixel_aspect_ratio_.Set(ConvertResolutionToString(format.pixel_aspect_ratio_width,
                                                      format.pixel_aspect_ratio_height));
  }
}

static camera__metrics::CameraMetricDimensionConfigIndex ConfigIndexDimension(
    std::optional<uint32_t> index) {
  if (index) {
    switch (*index) {
      case 0:
        return camera__metrics::CameraMetricDimensionConfigIndex::Config0;
      case 1:
        return camera__metrics::CameraMetricDimensionConfigIndex::Config1;
      case 2:
        return camera__metrics::CameraMetricDimensionConfigIndex::Config2;
      default:
        FX_LOGS(ERROR) << "Invalid config index " << *index;
        break;
    }
  }
  return camera__metrics::CameraMetricDimensionConfigIndex::NotApplicable;
}

static camera__metrics::CameraMetricDimensionStreamIndex StreamIndexDimension(
    std::optional<uint32_t> index) {
  if (index) {
    switch (*index) {
      case 0:
        return camera__metrics::CameraMetricDimensionStreamIndex::Stream0;
      case 1:
        return camera__metrics::CameraMetricDimensionStreamIndex::Stream1;
      case 2:
        return camera__metrics::CameraMetricDimensionStreamIndex::Stream2;
      default:
        FX_LOGS(ERROR) << "Invalid stream index " << *index;
        break;
    }
  }
  return camera__metrics::CameraMetricDimensionStreamIndex::NotApplicable;
}

MetricsReporter::FailureTestRecord::FailureTestRecord(MetricsReporter::Impl& impl,
                                                      FailureTestRecordType type,
                                                      bool initial_failure,
                                                      std::optional<uint32_t> config_index,
                                                      std::optional<uint32_t> stream_index)
    : impl_{impl},
      type_{type},
      failed_{initial_failure},
      config_index_{ConfigIndexDimension(config_index)},
      stream_index_{StreamIndexDimension(stream_index)} {}

MetricsReporter::FailureTestRecord::~FailureTestRecord() {
  TRACE_INSTANT("camera", "FailureTestRecordLogged", TRACE_SCOPE_GLOBAL, "type", type_, "failed",
                failed_);

  if (!impl_.logger_) {
    return;
  }

  const auto failure_state = failed_
                                 ? camera__metrics::CameraMetricDimensionFailureTestResult::Failure
                                 : camera__metrics::CameraMetricDimensionFailureTestResult::Success;
  impl_.logger_->LogOccurrence(
      camera__metrics::kCameraFailureFrequencyMetricId,
      cobalt::Logger::BuildDimension(type_, failure_state, config_index_, stream_index_));
}

void MetricsReporter::FailureTestRecord::SetFailureState(bool failed) { failed_ = failed; }

}  // namespace camera
