// Copyright 2023 Google LLC
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     https://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

#include "mpact/sim/generic/component.h"

#include <string>
#include <utility>

#include "absl/log/log.h"

namespace mpact {
namespace sim {
namespace generic {

using ::mpact::sim::proto::ComponentData;
using ::mpact::sim::proto::ComponentValueEntry;

// The Get[ChildComponent, Counter, Config] methods are all identical except
// for the element data type. This template static function factors out the
// commonalities.
template <typename M, typename T>
static T *GetMapEntry(const M &map, absl::string_view name) {
  auto ptr = map.find(name);
  return (ptr == map.end()) ? nullptr : ptr->second;
}

// The Add[ChildComponent,Counter,Config] methods are all identical except
// for the element data type. This template static function factors out the
// commonalities.
template <typename M, typename T>
static absl::Status AddMapEntry(absl::string_view name, T *entry, M *map) {
  if (entry == nullptr) return absl::InvalidArgumentError("entry is nullptr");
  auto ptr = map->find(name);
  if (ptr != map->end()) {
    return absl::InternalError(
        absl::StrCat("entry with name '", name, "' already inserted"));
  }
  map->emplace(name, entry);
  return absl::OkStatus();
}

// Constructors.
Component::Component(std::string name) : component_name_(std::move(name)) {}

Component::Component(std::string name, Component *parent)
    : component_name_(std::move(name)) {
  if (parent != nullptr) {
    auto status = parent->AddChildComponent(*this);
    if (!status.ok()) {
      LOG(ERROR) << absl::StrCat(
          "Failed to add child component '", component_name_, "' to parent: '",
          parent->component_name(), "': ", status.message());
    }
  }
}

// Call the generic static function to Add the element.
absl::Status Component::AddChildComponent(Component &child) {
  auto status = AddMapEntry(child.component_name(), &child, &child_map_);
  if (!status.ok()) return status;
  child.SetParent(this);
  return absl::OkStatus();
}
absl::Status Component::AddCounter(CounterBaseInterface *counter) {
  if (!counter->IsInitialized()) {
    return absl::InvalidArgumentError("Counter has not been initialized");
  }
  return AddMapEntry(counter->GetName(), counter, &counter_map_);
}
absl::Status Component::AddConfig(ConfigBase *config) {
  return AddMapEntry(config->name(), config, &config_map_);
}

// Call the generic static function to Get the element.
Component *Component::GetChildComponent(absl::string_view name) const {
  return GetMapEntry<ComponentMap, Component>(child_map_, name);
}
absl::Status Component::RemoveChildComponent(absl::string_view name) {
  auto iter = child_map_.find(name);
  if (iter == child_map_.end())
    return absl::NotFoundError(
        absl::StrCat("No such child component '", name, "'"));
  child_map_.erase(iter);
  return absl::OkStatus();
}
CounterBaseInterface *Component::GetCounter(absl::string_view name) const {
  return GetMapEntry<CounterMap, CounterBaseInterface>(counter_map_, name);
}
ConfigBase *Component::GetConfig(absl::string_view name) const {
  return GetMapEntry<ConfigMap, ConfigBase>(config_map_, name);
}

// Import information from the component data proto.
absl::Status Component::Import(const ComponentData &component_data) {
  // Checking that the proto name matches. Recursive calls will not generate
  // this error, but need to check at the top level.
  if (!component_data.has_name() ||
      (component_name() != component_data.name())) {
    return absl::InternalError(absl::StrCat(
        "Name mismatch on import '", component_name(), "' != '",
        (component_data.has_name() ? component_data.name() : ""), "'"));
  }
  // First import self - as this may cause new child components to be created
  // based on the values of the configuration entries.
  auto status = ImportSelf(component_data);
  if (!status.ok()) return status;
  // Then import for the child components.
  status = ImportChildren(component_data);
  if (!status.ok()) return status;
  return absl::OkStatus();
}

absl::Status Component::ImportSelf(const ComponentData &component_data) {
  for (auto const &entry : component_data.configuration()) {
    if (!entry.has_name()) {
      // The proto is malformed.
      return absl::InternalError("Missing name in component value");
    }
    ConfigBase *config = GetConfig(entry.name());
    // It's not an error if there are proto values for config entries that
    // aren't registered. Just skip and continue.
    if (config == nullptr) continue;

    auto status = config->Import(&entry);
    if (!status.ok()) return status;
  }
  return absl::OkStatus();
}

absl::Status Component::ImportChildren(const ComponentData &component_data) {
  for (auto const &child_data : component_data.component_data()) {
    if (!child_data.has_name()) {
      return absl::InternalError("Unnamed child component");
    }
    Component *child = GetChildComponent(child_data.name());
    if (child == nullptr) continue;
    auto status = child->Import(child_data);
    if (!status.ok()) return status;
  }
  return absl::OkStatus();
}

void Component::ImportDone() const {
  // Propagate down the component hierarchy.
  for (auto const &[unused, child] : child_map_) {
    child->ImportDone();
  }
  // Notify through callbacks.
  for (auto const &callback : callback_vec_) {
    callback();
  }
}

// Export the information reachable from this component to the mutable
// component data proto.
absl::Status Component::Export(ComponentData *component_data) {
  if (component_data == nullptr) {
    return absl::InvalidArgumentError("Component data is null");
  }
  component_data->set_name(component_name());
  // Export the configuration values.
  for (auto const &[unused, config_pair] : config_map_) {
    ComponentValueEntry *entry = component_data->add_configuration();
    auto status = config_pair->Export(entry);
    if (!status.ok()) return status;
  }
  // Export the counter values.
  for (auto const &[unused, counter_pair] : counter_map_) {
    ComponentValueEntry *entry = component_data->add_statistics();
    auto status = counter_pair->Export(entry);
    if (!status.ok()) return status;
  }
  // Recursively export child component data.
  for (auto const &[unused, child_pair] : child_map_) {
    ComponentData *child_data = component_data->add_component_data();
    auto status = child_pair->Export(child_data);
    if (!status.ok()) return status;
  }
  return absl::OkStatus();
}

}  // namespace generic
}  // namespace sim
}  // namespace mpact
