// 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 "src/public/lib/registry_identifiers.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()) {
    lib::CustomerIdentifier customer_identifier(customer.customer_id());
    customers_by_id_[customer_identifier] = &customer;
    customers_by_name_[customer.customer_name()] = &customer;
    for (const auto& project : customer.projects()) {
      lib::ProjectIdentifier project_identifier =
          customer_identifier.ForProject(project.project_id());
      projects_by_id_[project_identifier] = &project;
      projects_by_name_[std::make_tuple(customer.customer_name(), project.project_name())] =
          &project;
      for (const auto& metric : project.metrics()) {
        lib::MetricIdentifier metric_identifier = project_identifier.ForMetric(metric.id());
        metrics_by_id_[metric_identifier] = &metric;
        for (const auto& report : metric.reports()) {
          reports_by_id_[metric_identifier.ForReport(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(lib::CustomerIdentifier customer) const {
  auto iter = customers_by_id_.find(customer);
  if (iter == customers_by_id_.end()) {
    return nullptr;
  }
  return iter->second;
}

const ProjectConfig* ProjectConfigs::GetProjectConfig(lib::ProjectIdentifier project) const {
  auto iter = projects_by_id_.find(project);
  if (iter == projects_by_id_.end()) {
    return nullptr;
  }
  return iter->second;
}

const MetricDefinition* ProjectConfigs::GetMetricDefinition(lib::MetricIdentifier metric) const {
  auto iter = metrics_by_id_.find(metric);
  if (iter == metrics_by_id_.end()) {
    return nullptr;
  }
  return iter->second;
}

const ReportDefinition* ProjectConfigs::GetReportDefinition(lib::ReportIdentifier report) const {
  auto iter = reports_by_id_.find(report);
  if (iter == reports_by_id_.end()) {
    return nullptr;
  }
  return iter->second;
}

std::vector<lib::ProjectIdentifier> ProjectConfigs::ListProjects() {
  std::vector<lib::ProjectIdentifier> out;
  out.reserve(projects_by_id_.size());

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

  return out;
}

}  // namespace cobalt::config
