// 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.

#ifndef MPACT_SIM_GENERIC_COMPONENT_H_
#define MPACT_SIM_GENERIC_COMPONENT_H_

#include <functional>
#include <string>
#include <vector>

#include "absl/container/btree_map.h"
#include "absl/status/status.h"
#include "absl/strings/string_view.h"
#include "mpact/sim/generic/config.h"
#include "mpact/sim/generic/counters_base.h"
#include "mpact/sim/proto/component_data.pb.h"

namespace mpact {
namespace sim {
namespace generic {

// A Component represents an abstraction of a hierarchical block of the
// simulated architecture. It may, but is not required to correspond to a block
// in the actual hardware design. By itself it has no real functionality in the
// simulation, but acts as a named entity that can have configurations and/or
// counter instrumentation instances associated with it, as well as zero or more
// Component instances as children. In general, it is expected that there is
// only one root instance of a Component.
class Component {
 public:
  // Using btree_map to ensure proto exports are done in name order.
  using ComponentMap = absl::btree_map<std::string, Component*>;
  using CounterMap = absl::btree_map<std::string, CounterBaseInterface*>;
  using ConfigMap = absl::btree_map<std::string, ConfigBase*>;
  // Type alias for import done callback function.
  using CallbackFunction = std::function<void()>;
  // Create a Component with no parent.
  explicit Component(std::string name);
  // Create a Component under the given parent. Adds the component to the
  // parent's child components.
  Component(std::string name, Component* parent);
  Component() = delete;
  Component(const Component&) = delete;
  Component operator=(const Component&) = delete;
  virtual ~Component() = default;

  // Methods to add and access child components, counters and config entries.
  absl::Status AddChildComponent(Component& child);
  absl::Status AddCounter(CounterBaseInterface* counter);
  absl::Status AddConfig(ConfigBase* config);
  Component* GetChildComponent(absl::string_view name) const;
  absl::Status RemoveChildComponent(absl::string_view name);
  CounterBaseInterface* GetCounter(absl::string_view name) const;
  ConfigBase* GetConfig(absl::string_view name) const;

  // Imports the ComponentData proto into the current Component, registered
  // child component instances, and registered ConfigBase instances. No values
  // are imported into counters. This method may be overridden.
  virtual absl::Status Import(
      const mpact::sim::proto::ComponentData& component_data);

  // This method is called when all imports are done. Can be overridden.
  virtual void ImportDone() const;

  // Register a callback function to be called when import is done.
  template <typename F>
  void AddImportDoneCallback(const F& callback) {
    callback_vec_.push_back(callback);
  }

  // Exports the data from the current Component instance, its' registered child
  // components, registered ConfigBase instances, and registered CounterBase
  // instances.
  absl::Status Export(proto::ComponentData* component_data);

  // Accessors.
  const std::string& component_name() const { return component_name_; }
  Component* parent() const { return parent_; }

  // Map accessors.
  const ComponentMap& child_map() const { return child_map_; }
  const CounterMap& counter_map() const { return counter_map_; }
  const ConfigMap& config_map() const { return config_map_; }

 protected:
  // The Import method is divided into import self and import children. Each
  // can be individually overridden.
  virtual absl::Status ImportSelf(
      const mpact::sim::proto::ComponentData& component_data);
  virtual absl::Status ImportChildren(
      const mpact::sim::proto::ComponentData& component_data);

 private:
  // Private accessor.
  void SetParent(Component* parent) { parent_ = parent; }

  std::string component_name_;
  Component* parent_ = nullptr;

  // None of the objects pointed to by these maps are owned by this object.
  ComponentMap child_map_;
  CounterMap counter_map_;
  ConfigMap config_map_;
  std::vector<CallbackFunction> callback_vec_;
};

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

#endif  // MPACT_SIM_GENERIC_COMPONENT_H_
