// 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"
#include "absl/status/status.h"
#include "absl/strings/str_cat.h"
#include "absl/strings/string_view.h"
#include "mpact/sim/generic/config.h"
#include "mpact/sim/generic/counters_base.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
