// Copyright 2018 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/logger/internal_metrics.h"

#include <memory>
#include <string>
#include <utility>

#include "src/logger/internal_metrics_config.cb.h"
#include "src/logging.h"

namespace cobalt::logger {

std::unique_ptr<InternalMetrics> InternalMetrics::NewWithLogger(LoggerInterface* logger) {
  if (logger) {
    return std::make_unique<InternalMetricsImpl>(logger);
  }
  return std::make_unique<NoOpInternalMetrics>();
}

InternalMetricsImpl::InternalMetricsImpl(LoggerInterface* logger) : logger_(logger) {
  CHECK(logger_);
}

void InternalMetricsImpl::LoggerCalled(PerProjectLoggerCallsMadeMetricDimensionLoggerMethod method,
                                       const Project& project) {
  fields_.lock()->queued_lambdas.emplace_back([this, method, project] {
    auto status = logger_->LogEventCount(kLoggerCallsMadeMetricId, method, "", 0, 1);

    if (status != kOK) {
      VLOG(1) << "InternalMetricsImpl::LoggerCalled: LogEventCount() returned status=" << status;
    }

    std::ostringstream component;
    component << project.customer_name() << '/' << project.project_name();
    status =
        logger_->LogEventCount(kPerProjectLoggerCallsMadeMetricId, method, component.str(), 0, 1);

    if (status != kOK) {
      VLOG(1) << "InternalMetricsImpl::LoggerCalled: LogEventCount() returned status=" << status;
    }
  });
}

void InternalMetricsImpl::BytesUploaded(PerDeviceBytesUploadedMetricDimensionStatus upload_status,
                                        int64_t byte_count) {
  fields_.lock()->queued_lambdas.emplace_back([this, upload_status, byte_count] {
    Status status =
        logger_->LogEventCount(kPerDeviceBytesUploadedMetricId, upload_status, "", 0, byte_count);

    if (status != kOK) {
      VLOG(1) << "InternalMetricsImpl::BytesUploaded: LogEventCount() returned "
              << "status=" << status;
    }

    status = logger_->LogOccurrence(kBytesUploadedMetricId, byte_count, {upload_status});

    if (status != kOK) {
      VLOG(1) << "InternalMetricsImpl::BytesUploaded: LogOccurrence() returned "
              << "status=" << status;
    }
  });
}

void InternalMetricsImpl::BytesUploaded(PerProjectBytesUploadedMetricDimensionStatus upload_status,
                                        int64_t byte_count, uint32_t customer_id,
                                        uint32_t project_id) {
  fields_.lock()->queued_lambdas.emplace_back(
      [this, upload_status, byte_count, customer_id, project_id] {
        std::ostringstream component;
        component << customer_id << '/' << project_id;

        auto status = logger_->LogEventCount(kPerProjectBytesUploadedMetricId, upload_status,
                                             component.str(), 0, byte_count);

        if (status != kOK) {
          VLOG(1) << "InternalMetricsImpl::BytesUploaded: LogEventCount() returned "
                  << "status=" << status;
        }
      });
}

void InternalMetricsImpl::BytesStored(PerProjectBytesStoredMetricDimensionStatus upload_status,
                                      int64_t byte_count, uint32_t customer_id,
                                      uint32_t project_id) {
  fields_.lock()->queued_lambdas.emplace_back([this, upload_status, byte_count, customer_id,
                                               project_id] {
    std::ostringstream component;
    component << customer_id << '/' << project_id;

    auto status = logger_->LogMemoryUsage(kPerProjectBytesStoredMetricId, upload_status,
                                          component.str(), byte_count);

    if (status != kOK) {
      VLOG(1) << "InternalMetricsImpl::BytesStored: LogMemoryUsage() returned status=" << status;
    }
  });
}

void InternalMetricsImpl::IdleObservationUpload(
    IdleObservationUploadMetricDimensionDeviceState state) {
  fields_.lock()->queued_lambdas.emplace_back([this, state] {
    auto status = logger_->LogEventCount(kIdleObservationUploadMetricId, state, "", 0, 1);
    if (status != kOK) {
      VLOG(1) << "InternalMetricsImpl::IdleObservationUpload: LogEventCount() returned status="
              << status;
    }
  });
}

void InternalMetricsImpl::InaccurateClockEventsCached(int64_t event_count, uint32_t customer_id,
                                                      uint32_t project_id) {
  fields_.lock()->queued_lambdas.emplace_back([this, event_count, customer_id, project_id] {
    std::ostringstream component;
    component << customer_id << '/' << project_id;

    auto status = logger_->LogEventCount(kInaccurateClockEventsCachedMetricId, {}, component.str(),
                                         0, event_count);

    if (status != kOK) {
      VLOG(1)
          << "InternalMetricsImpl::InaccurateClockEventsCached: LogEventCount() returned status="
          << status;
    }
  });
}

void InternalMetricsImpl::InaccurateClockEventsDropped(int64_t event_count, uint32_t customer_id,
                                                       uint32_t project_id) {
  fields_.lock()->queued_lambdas.emplace_back([this, event_count, customer_id, project_id] {
    std::ostringstream component;
    component << customer_id << '/' << project_id;

    auto status = logger_->LogEventCount(kInaccurateClockEventsDroppedMetricId, {}, component.str(),
                                         0, event_count);

    if (status != kOK) {
      VLOG(1)
          << "InternalMetricsImpl::InaccurateClockEventsDropped: LogEventCount() returned status="
          << status;
    }
  });
}

void InternalMetricsImpl::SetSoftwareDistributionInfoCalled(
    SetSoftwareDistributionInfoCalledEventCodes event_codes) {
  fields_.lock()->queued_lambdas.emplace_back([this, event_codes] {
    auto status = logger_->LogEventCount(kSetSoftwareDistributionInfoCalledMetricId,
                                         event_codes.ToVector(), "", 0, 1);

    if (status != kOK) {
      VLOG(1) << "InternalMetricsImpl::SetSoftwareDistributionInfoCalled: LogEventCount() returned "
                 "status="
              << status;
    }
  });
}

const float kPerMilleMultiplier = 1000.0;
void InternalMetricsImpl::TrackDiskUsage(StorageClass storage_class, int64_t bytes,
                                         int64_t max_bytes) {
  fields_.lock()->queued_lambdas.emplace_back([this, storage_class, bytes, max_bytes] {
    // N.B. This method may only include Cobalt 1.1 metrics. Using Cobalt 1.0 metrics here have the
    // potential to cause logging loops.
    auto status = logger_->LogInteger(kStoreUsageMetricId, bytes, {storage_class});
    if (status != kOK) {
      VLOG(1) << "InternalMetricsImpl::TrackDiskUsage: LogInteger(disk_usage) returned status="
              << status;
    }

    if (max_bytes >= 0) {
      auto fullness_per_mille = static_cast<uint32_t>(
          (static_cast<float>(bytes) / static_cast<float>(max_bytes)) * kPerMilleMultiplier);
      status = logger_->LogInteger(kStoreFullnessMetricId, fullness_per_mille, {storage_class});
      if (status != kOK) {
        VLOG(1) << "InternalMetricsImpl::TrackDiskUsage: LogInteger(disk_fullness) returned status="
                << status;
      }
    }
  });
}

void InternalMetricsImpl::Flush() {
  std::vector<std::function<void()>> queued;
  fields_.lock()->queued_lambdas.swap(queued);

  for (const auto& task : queued) {
    task();
  }
}

}  // namespace cobalt::logger
