text: // 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;
  }
  
  }  // namespace cobalt::config
  