// 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/breakpoint_manager.h"

#include <cstdint>
#include <utility>

#include "absl/functional/bind_front.h"
#include "absl/log/log.h"
#include "absl/status/status.h"
#include "absl/status/statusor.h"
#include "absl/strings/str_cat.h"
#include "mpact/sim/generic/action_point_manager_base.h"

namespace mpact {
namespace sim {
namespace generic {

BreakpointManager::BreakpointManager(
    ActionPointManagerBase* action_point_manager,
    RequestHaltFunction req_halt_function)
    : req_halt_function_(std::move(req_halt_function)),
      action_point_manager_(action_point_manager) {}

BreakpointManager::~BreakpointManager() {
  for (auto const& [unused, bp_ptr] : breakpoint_map_) {
    delete bp_ptr;
  }
  req_halt_function_ = nullptr;
  breakpoint_map_.clear();
}

bool BreakpointManager::HasBreakpoint(uint64_t address) {
  return breakpoint_map_.contains(address);
}

absl::Status BreakpointManager::SetBreakpoint(uint64_t address) {
  if (HasBreakpoint(address))
    return absl::AlreadyExistsError(
        absl::StrCat("Error SetBreakpoint: Breakpoint at ", absl::Hex(address),
                     " already exists"));

  auto result = action_point_manager_->SetAction(
      address, absl::bind_front(&BreakpointManager::DoBreakpointAction, this));
  if (!result.ok()) return result.status();
  auto id = result.value();

  auto* bp = new BreakpointInfo{address, id, /*is_active=*/true};
  breakpoint_map_.insert(std::make_pair(address, bp));

  return absl::OkStatus();
}

absl::Status BreakpointManager::ClearBreakpoint(uint64_t address) {
  // Lookup the breakpoint.
  auto iter = breakpoint_map_.find(address);
  if (iter == breakpoint_map_.end()) {
    auto msg = absl::StrCat("Error ClearBreakpoint: No breakpoint set for ",
                            absl::Hex(address));
    LOG(WARNING) << msg;
    return absl::NotFoundError(msg);
  }
  auto status = action_point_manager_->ClearAction(address, iter->second->id);
  if (!status.ok()) return status;

  auto* bp = iter->second;
  breakpoint_map_.erase(iter);
  delete bp;
  return absl::OkStatus();
}

absl::Status BreakpointManager::DisableBreakpoint(uint64_t address) {
  // Lookup the breakpoint.
  auto iter = breakpoint_map_.find(address);
  if (iter == breakpoint_map_.end()) {
    auto msg = absl::StrCat("Error DisableBreakpoint: No breakpoint set for ",
                            absl::Hex(address));
    LOG(WARNING) << msg;
    return absl::NotFoundError(msg);
  }

  auto status = action_point_manager_->DisableAction(address, iter->second->id);
  return status;
}

absl::Status BreakpointManager::EnableBreakpoint(uint64_t address) {
  auto iter = breakpoint_map_.find(address);
  if (iter == breakpoint_map_.end())
    return absl::NotFoundError(absl::StrCat(
        "Error EnableBreakpoint: No breakpoint set for ", absl::Hex(address)));

  auto status = action_point_manager_->EnableAction(address, iter->second->id);
  return status;
}

void BreakpointManager::ClearAllBreakpoints() {
  for (auto const& [unused, bp_ptr] : breakpoint_map_) {
    (void)action_point_manager_->ClearAction(bp_ptr->address, bp_ptr->id);
    delete bp_ptr;
  }
  breakpoint_map_.clear();
}

bool BreakpointManager::IsBreakpoint(uint64_t address) const {
  auto iter = breakpoint_map_.find(address);
  if (iter == breakpoint_map_.end()) return false;

  return action_point_manager_->IsActionEnabled(address, iter->second->id);
}

void BreakpointManager::DoBreakpointAction(uint64_t address, int) {
  last_breakpoint_address_ = address;
  req_halt_function_();
}

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