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

#include <string>

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

namespace mpact {
namespace sim {
namespace generic {

// Initialize the bitmap and set the bit specified by index.
SimpleResource::SimpleResource(absl::string_view name, int index,
                               SimpleResourcePool* pool)
    : name_(name), index_(index), pool_(pool) {
  resource_bit_.Resize(pool_->width());
  resource_bit_.Set(index);
}

// Just call into the pool to reserve/free/check.
void SimpleResource::Acquire() { pool_->Acquire(this); }

void SimpleResource::Release() { pool_->Release(this); }

bool SimpleResource::IsFree() const { return pool_->IsFree(this); }

SimpleResourceSet::SimpleResourceSet(SimpleResourcePool* pool) : pool_(pool) {
  resource_vector_.Resize(pool_->width());
}

// Verify that the resource comes from the same pool. If so, add it (union with)
// the bitmap. Return appropriate status.
absl::Status SimpleResourceSet::AddResource(SimpleResource* resource) {
  // If the resource is nullptr, just return ok status.
  if (resource == nullptr) return absl::OkStatus();
  // Make sure it belongs to the same pool as the resource set.
  if (resource->pool() != pool_) {
    return absl::Status(
        absl::StatusCode::kInternal,
        "SimpleResourceSet: Attempt to add resource from different pool");
  }
  resource_vector_.Or(resource->resource_bit());
  return absl::OkStatus();
}

// If the resource doesn't exist, add it to the resource pool, before adding it
// to the resource set.
absl::Status SimpleResourceSet::AddResource(absl::string_view name) {
  SimpleResource* resource = pool_->GetResource(name);
  if (nullptr == resource) {
    auto status = pool_->AddResource(name);
    if (!status.ok()) return status;
    resource = pool_->GetResource(name);
  }
  auto status = AddResource(resource);
  if (!status.ok()) return status;
  return absl::OkStatus();
}

// Call into the pool to reserve/free/check.
void SimpleResourceSet::Acquire() { pool_->Acquire(this); }

void SimpleResourceSet::Release() { pool_->Release(this); }

bool SimpleResourceSet::IsFree() const { return pool_->IsFree(this); }

std::string SimpleResourceSet::AsString() const {
  std::string out = "[";
  std::string sep;
  for (int index = 0; resource_vector_.FindNextSetBit(&index); ++index) {
    auto* resource = pool_->GetResource(index);
    if (resource == nullptr) {
      LOG(ERROR) << absl::StrCat("Cannot find resource (", index, ") in pool '",
                                 pool_->name(), "'");
      continue;
    }
    absl::StrAppend(&out, sep, resource->name());
    sep = ", ";
  }
  absl::StrAppend(&out, "]");
  return out;
}

SimpleResourcePool::SimpleResourcePool(absl::string_view name, int width)
    : name_(name), width_(width) {
  resource_vector_.Resize(width_);
}

SimpleResourcePool::~SimpleResourcePool() {
  for (const auto& entry : resource_name_map_) {
    delete entry.second;
  }
  resource_name_map_.clear();
  for (auto entry : resource_sets_) {
    delete entry;
  }
  resource_sets_.clear();
}

// Add named resource to the pool. If the pool has reached maximum size, return
// an error.
absl::StatusOr<SimpleResource*> SimpleResourcePool::AddResourceInternal(
    absl::string_view name) {
  if (resource_name_map_.size() == width_) {
    return absl::InternalError(absl::StrCat(
        "SimpleResourcePool: Attempted to add too many resources to pool '",
        name_, "'"));
  }
  if (resource_name_map_.contains(name)) {
    return absl::AlreadyExistsError(
        absl::StrCat("SimpleResourcePool: Resource '", name,
                     "' already exists in pool '", name_, "'"));
  }
  int index = resource_name_map_.size();
  SimpleResource* resource = new SimpleResource(name, index, this);
  resource_name_map_.emplace(name, resource);
  resources_.push_back(resource);
  return resource;
}

absl::Status SimpleResourcePool::AddResource(absl::string_view name) {
  auto result = AddResourceInternal(name);
  if (result.ok()) return absl::OkStatus();

  return result.status();
}

SimpleResource* SimpleResourcePool::GetResource(unsigned index) const {
  if ((index < 0) || (index >= resources_.size())) return nullptr;
  return resources_[index];
}

SimpleResource* SimpleResourcePool::GetResource(absl::string_view name) const {
  auto ptr = resource_name_map_.find(name);
  if (ptr == resource_name_map_.end()) return nullptr;
  return ptr->second;
}

SimpleResource* SimpleResourcePool::GetOrAddResource(absl::string_view name) {
  auto* resource = GetResource(name);
  if (resource != nullptr) return resource;

  auto result = AddResourceInternal(name);
  if (!result.ok()) {
    LOG(ERROR) << "Unable to add resource '" << name
               << "' to resource pool: " << result.status().message();
    return nullptr;
  }

  return result.value();
}

SimpleResourceSet* SimpleResourcePool::CreateResourceSet() {
  resource_sets_.push_front(new SimpleResourceSet(this));
  return resource_sets_.front();
}

// Bitmap operations to reserve, free and check resources. Union with a bitmap
// from a resource or resource set to reserve (set), difference to free (clear),
// and non-empty intersection (non-zero and) to check.
bool SimpleResourcePool::IsFree(const SimpleResourceSet* resource_set) const {
  return !resource_vector_.IsIntersectionNonEmpty(
      resource_set->resource_vector());
}

bool SimpleResourcePool::IsFree(const SimpleResource* resource) const {
  return !resource_vector_.IsIntersectionNonEmpty(resource->resource_bit());
}

void SimpleResourcePool::Acquire(const SimpleResourceSet* resource_set) {
  resource_vector_.Or(resource_set->resource_vector());
}

void SimpleResourcePool::Acquire(const SimpleResource* resource) {
  resource_vector_.Or(resource->resource_bit());
}

void SimpleResourcePool::Release(const SimpleResourceSet* resource_set) {
  resource_vector_.AndNot(resource_set->resource_vector());
}

void SimpleResourcePool::Release(const SimpleResource* resource) {
  resource_vector_.AndNot(resource->resource_bit());
}

std::string SimpleResourcePool::ReservedAsString() const {
  std::string out = "[";
  std::string sep;
  for (int index = 0; resource_vector_.FindNextSetBit(&index); ++index) {
    auto* resource = resources_[index];
    if (resource == nullptr) {
      LOG(ERROR) << absl::StrCat("Cannot find resource (", index, ") in pool '",
                                 name(), "'");
      continue;
    }
    absl::StrAppend(&out, sep, resource->name());
    sep = ", ";
  }
  absl::StrAppend(&out, "]");
  return out;
}

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