// Copyright 2024 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
//
//     http://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/action_point_manager_base.h"

#include <cstdint>
#include <utility>

#include "absl/log/log.h"
#include "absl/status/status.h"
#include "absl/status/statusor.h"
#include "absl/strings/str_cat.h"

namespace mpact::sim::generic {

ActionPointManagerBase::ActionPointManagerBase(
    ActionPointMemoryInterface* ap_mem_interface)
    : ap_memory_interface_(ap_mem_interface) {}

ActionPointManagerBase::~ActionPointManagerBase() {
  for (auto& [unused, ap_ptr] : action_point_map_) {
    for (auto& [unused, ai_ptr] : ap_ptr->action_map) {
      ai_ptr->action_fcn = nullptr;
      delete ai_ptr;
    }
    ap_ptr->action_map.clear();
    delete ap_ptr;
  }
  action_point_map_.clear();
}

bool ActionPointManagerBase::HasActionPoint(uint64_t address) const {
  return action_point_map_.contains(address);
}

absl::StatusOr<int> ActionPointManagerBase::SetAction(uint64_t address,
                                                      ActionFcn action_fcn) {
  auto it = action_point_map_.find(address);
  ActionPointInfo* ap = nullptr;
  if (it == action_point_map_.end()) {
    // If the action point doesn't exist, create a new one.
    // First set the breakpoint instruction.
    auto status = ap_memory_interface_->WriteBreakpointInstruction(address);
    if (!status.ok()) return status;
    ap = new ActionPointInfo(address);
    action_point_map_.insert(std::make_pair(address, ap));
  } else {
    ap = it->second;
    // If there are no active actions, write out a breakpoint instruction.
    if (ap->num_active == 0) {
      auto status = ap_memory_interface_->WriteBreakpointInstruction(address);
      if (!status.ok()) return status;
    }
  }
  // Add the function as an enabled action.
  int id = ap->next_id++;
  auto* action_info =
      new ActionInfo(std::move(action_fcn), /*is_enabled=*/true);
  ap->action_map.insert(std::make_pair(id, action_info));
  ap->num_active++;
  return id;
}

absl::Status ActionPointManagerBase::ClearAction(uint64_t address, int id) {
  // Find the action point.
  auto it = action_point_map_.find(address);
  if (it == action_point_map_.end()) {
    return absl::NotFoundError(
        absl::StrCat("No action point found at: ", absl::Hex(address)));
  }
  // Find the action.
  auto* ap = it->second;
  auto action_it = ap->action_map.find(id);
  if (action_it == ap->action_map.end()) {
    return absl::NotFoundError(
        absl::StrCat("No action ", id, "found at: ", absl::Hex(address)));
  }
  // Remove the action.
  auto* action_info = action_it->second;
  ap->action_map.erase(action_it);
  ap->num_active -= action_info->is_enabled ? 1 : 0;
  delete action_info;
  // If there are no other active actions, write back the original instruction.
  if (ap->num_active == 0) {
    auto status = ap_memory_interface_->WriteOriginalInstruction(address);
    if (!status.ok()) return status;
  }
  return absl::OkStatus();
}

absl::Status ActionPointManagerBase::EnableAction(uint64_t address, int id) {
  // Find the action point.
  auto it = action_point_map_.find(address);
  if (it == action_point_map_.end()) {
    return absl::NotFoundError(
        absl::StrCat("No action point found at: ", absl::Hex(address)));
  }
  auto* ap = it->second;
  // Find the action.
  auto action_it = ap->action_map.find(id);
  if (action_it == ap->action_map.end()) {
    return absl::NotFoundError(
        absl::StrCat("No action ", id, "found at: ", absl::Hex(address)));
  }
  // If it is already enabled, return ok.
  if (action_it->second->is_enabled) return absl::OkStatus();
  action_it->second->is_enabled = true;
  ap->num_active++;
  // If there is only one active action (this), write a breakpoint instruction.
  if (ap->num_active == 1) {
    auto status = ap_memory_interface_->WriteBreakpointInstruction(address);
    if (!status.ok()) return status;
  }
  return absl::OkStatus();
}

absl::Status ActionPointManagerBase::DisableAction(uint64_t address, int id) {
  // Find the action point.
  auto it = action_point_map_.find(address);
  if (it == action_point_map_.end()) {
    return absl::NotFoundError(
        absl::StrCat("No action point found at: ", absl::Hex(address)));
  }
  // Find the action.
  auto* ap = it->second;
  auto action_it = ap->action_map.find(id);
  if (action_it == ap->action_map.end()) {
    return absl::NotFoundError(
        absl::StrCat("No action ", id, "found at: ", absl::Hex(address)));
  }
  // If it is already disabled, return ok.
  if (!action_it->second->is_enabled) return absl::OkStatus();
  // Disable the action.
  action_it->second->is_enabled = false;
  ap->num_active--;
  // If there are no active actions, write back the original instruction.
  if (ap->num_active == 0) {
    auto status = ap_memory_interface_->WriteOriginalInstruction(address);
    if (!status.ok()) return status;
  }
  return absl::OkStatus();
}

bool ActionPointManagerBase::IsActionPointActive(uint64_t address) const {
  // Find the action point.
  auto it = action_point_map_.find(address);
  if (it == action_point_map_.end()) return false;

  auto* ap = it->second;
  return ap->num_active > 0;
}

bool ActionPointManagerBase::IsActionEnabled(uint64_t address, int id) const {
  // Find the action point.
  auto it = action_point_map_.find(address);
  if (it == action_point_map_.end()) return false;

  auto* ap = it->second;
  // Find the action.
  auto action_it = ap->action_map.find(id);
  if (action_it == ap->action_map.end()) return false;
  return action_it->second->is_enabled;
}

void ActionPointManagerBase::ClearAllActionPoints() {
  for (auto& [address, ap_ptr] : action_point_map_) {
    for (auto& [unused, action_ptr] : ap_ptr->action_map) {
      delete action_ptr;
    }
    ap_ptr->action_map.clear();
    (void)ap_memory_interface_->WriteOriginalInstruction(ap_ptr->address);
    delete ap_ptr;
  }
  action_point_map_.clear();
}

void ActionPointManagerBase::PerformActions(uint64_t address) {
  auto it = action_point_map_.find(address);
  if (it == action_point_map_.end()) {
    LOG(ERROR) << absl::StrCat("No action point found at: ",
                               absl::Hex(address));
  }

  for (auto& [id, action_ptr] : it->second->action_map) {
    if (action_ptr->is_enabled) action_ptr->action_fcn(address, id);
  }
}

}  // namespace mpact::sim::generic
