// 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/registry/project_configs.h"

#include "src/logging.h"
#include "third_party/abseil-cpp/absl/strings/escaping.h"

namespace cobalt::config {

std::unique_ptr<ProjectConfigs> ProjectConfigs::CreateFromCobaltRegistryBase64(
    const std::string& cobalt_registry_base64) {
  std::string cobalt_registry_bytes;
  if (!absl::Base64Unescape(cobalt_registry_base64, &cobalt_registry_bytes)) {
    LOG(ERROR) << "Unable to parse the provided string as base-64";
    return nullptr;
  }
  return CreateFromCobaltRegistryBytes(cobalt_registry_bytes);
}

std::unique_ptr<ProjectConfigs> ProjectConfigs::CreateFromCobaltRegistryBytes(
    const std::string& cobalt_registry_bytes) {
  auto cobalt_registry = std::make_unique<CobaltRegistry>();
  if (!cobalt_registry->ParseFromString(cobalt_registry_bytes)) {
    LOG(ERROR) << "Unable to parse a CobaltRegistry from the provided bytes.";
    return nullptr;
  }
  return CreateFromCobaltRegistryProto(std::move(cobalt_registry));
}

std::unique_ptr<ProjectConfigs> ProjectConfigs::CreateFromCobaltRegistryProto(
    std::unique_ptr<CobaltRegistry> cobalt_registry) {
  return std::make_unique<ProjectConfigs>(std::move(cobalt_registry));
}

ProjectConfigs::ProjectConfigs(std::unique_ptr<CobaltRegistry> cobalt_registry)
    : cobalt_registry_(std::move(cobalt_registry)) {
  is_empty_ = cobalt_registry_->customers_size() == 0;
  is_single_project_ = false;
  if (cobalt_registry_->customers_size() == 1) {
    auto customer = cobalt_registry_->customers(0);
    if (customer.projects_size() == 1) {
      const auto& project = customer.projects(0);
      is_single_project_ = true;
      single_customer_id_ = customer.customer_id();
      single_customer_name_ = customer.customer_name();
      single_project_id_ = project.project_id();
      single_project_name_ = project.project_name();
    }
  }
  for (const auto& customer : cobalt_registry_->customers()) {
    customers_by_id_[customer.customer_id()] = &customer;
    customers_by_name_[customer.customer_name()] = &customer;
    for (const auto& project : customer.projects()) {
      projects_by_id_[std::make_tuple(customer.customer_id(), project.project_id())] = &project;
      projects_by_name_[std::make_tuple(customer.customer_name(), project.project_name())] =
          &project;
      for (const auto& metric : project.metrics()) {
        metrics_by_id_[std::make_tuple(customer.customer_id(), project.project_id(), metric.id())] =
            &metric;
        for (const auto& report : metric.reports()) {
          reports_by_id_[std::make_tuple(customer.customer_id(), project.project_id(), metric.id(),
                                         report.id())] = &report;
        }
      }
    }
  }
}

std::unique_ptr<ProjectConfig> ProjectConfigs::TakeSingleProjectConfig() {
  if (!is_single_project_) {
    return nullptr;
  }
  is_empty_ = true;
  is_single_project_ = false;
  projects_by_name_.clear();
  projects_by_id_.clear();
  metrics_by_id_.clear();
  reports_by_id_.clear();
  auto project_config = std::make_unique<ProjectConfig>();
  CHECK(!cobalt_registry_->customers().empty());
  CHECK(!cobalt_registry_->customers(0).projects().empty());
  project_config->Swap(cobalt_registry_->mutable_customers(0)->mutable_projects(0));
  cobalt_registry_->mutable_customers(0)->mutable_projects()->Clear();
  return project_config;
}

const CustomerConfig* ProjectConfigs::GetCustomerConfig(uint32_t customer_id) const {
  auto iter = customers_by_id_.find(customer_id);
  if (iter == customers_by_id_.end()) {
    return nullptr;
  }
  return iter->second;
}

const ProjectConfig* ProjectConfigs::GetProjectConfig(uint32_t customer_id,
                                                      uint32_t project_id) const {
  auto iter = projects_by_id_.find(std::make_tuple(customer_id, project_id));
  if (iter == projects_by_id_.end()) {
    return nullptr;
  }
  return iter->second;
}

const MetricDefinition* ProjectConfigs::GetMetricDefinition(uint32_t customer_id,
                                                            uint32_t project_id,
                                                            uint32_t metric_id) const {
  auto iter = metrics_by_id_.find(std::make_tuple(customer_id, project_id, metric_id));
  if (iter == metrics_by_id_.end()) {
    return nullptr;
  }
  return iter->second;
}

const ReportDefinition* ProjectConfigs::GetReportDefinition(uint32_t customer_id,
                                                            uint32_t project_id, uint32_t metric_id,
                                                            uint32_t report_id) const {
  auto iter = reports_by_id_.find(std::make_tuple(customer_id, project_id, metric_id, report_id));
  if (iter == reports_by_id_.end()) {
    return nullptr;
  }
  return iter->second;
}

std::vector<std::tuple<uint32_t, uint32_t>> ProjectConfigs::ListProjects() {
  std::vector<std::tuple<uint32_t, uint32_t>> out;
  out.reserve(projects_by_id_.size());

  for (auto& project : projects_by_id_) {
    out.push_back(project.first);
  }

  return out;
}

}  // namespace cobalt::config
