/* Distributed under the OSI-approved BSD 3-Clause License.  See accompanying
   file Copyright.txt or https://cmake.org/licensing for details.  */
#include "cmFileLockPool.h"

#include <algorithm>
#include <cassert>
#include <utility>

#include "cmFileLock.h"
#include "cmFileLockResult.h"

cmFileLockPool::cmFileLockPool() = default;

cmFileLockPool::~cmFileLockPool() = default;

void cmFileLockPool::PushFunctionScope()
{
  this->FunctionScopes.emplace_back();
}

void cmFileLockPool::PopFunctionScope()
{
  assert(!this->FunctionScopes.empty());
  this->FunctionScopes.pop_back();
}

void cmFileLockPool::PushFileScope()
{
  this->FileScopes.emplace_back();
}

void cmFileLockPool::PopFileScope()
{
  assert(!this->FileScopes.empty());
  this->FileScopes.pop_back();
}

cmFileLockResult cmFileLockPool::LockFunctionScope(const std::string& filename,
                                                   unsigned long timeoutSec)
{
  if (this->IsAlreadyLocked(filename)) {
    return cmFileLockResult::MakeAlreadyLocked();
  }
  if (this->FunctionScopes.empty()) {
    return cmFileLockResult::MakeNoFunction();
  }
  return this->FunctionScopes.back().Lock(filename, timeoutSec);
}

cmFileLockResult cmFileLockPool::LockFileScope(const std::string& filename,
                                               unsigned long timeoutSec)
{
  if (this->IsAlreadyLocked(filename)) {
    return cmFileLockResult::MakeAlreadyLocked();
  }
  assert(!this->FileScopes.empty());
  return this->FileScopes.back().Lock(filename, timeoutSec);
}

cmFileLockResult cmFileLockPool::LockProcessScope(const std::string& filename,
                                                  unsigned long timeoutSec)
{
  if (this->IsAlreadyLocked(filename)) {
    return cmFileLockResult::MakeAlreadyLocked();
  }
  return this->ProcessScope.Lock(filename, timeoutSec);
}

cmFileLockResult cmFileLockPool::Release(const std::string& filename)
{
  for (auto& funcScope : this->FunctionScopes) {
    const cmFileLockResult result = funcScope.Release(filename);
    if (!result.IsOk()) {
      return result;
    }
  }

  for (auto& fileScope : this->FileScopes) {
    const cmFileLockResult result = fileScope.Release(filename);
    if (!result.IsOk()) {
      return result;
    }
  }

  return this->ProcessScope.Release(filename);
}

bool cmFileLockPool::IsAlreadyLocked(const std::string& filename) const
{
  for (auto const& funcScope : this->FunctionScopes) {
    const bool result = funcScope.IsAlreadyLocked(filename);
    if (result) {
      return true;
    }
  }

  for (auto const& fileScope : this->FileScopes) {
    const bool result = fileScope.IsAlreadyLocked(filename);
    if (result) {
      return true;
    }
  }

  return this->ProcessScope.IsAlreadyLocked(filename);
}

cmFileLockPool::ScopePool::ScopePool() = default;

cmFileLockPool::ScopePool::~ScopePool() = default;

cmFileLockPool::ScopePool::ScopePool(ScopePool&&) noexcept = default;

cmFileLockPool::ScopePool& cmFileLockPool::ScopePool::operator=(
  ScopePool&& other) noexcept
{
  if (this != &other) {
    this->Locks = std::move(other.Locks);
  }

  return *this;
}

cmFileLockResult cmFileLockPool::ScopePool::Lock(const std::string& filename,
                                                 unsigned long timeoutSec)
{
  cmFileLock lock;
  const cmFileLockResult result = lock.Lock(filename, timeoutSec);
  if (result.IsOk()) {
    this->Locks.push_back(std::move(lock));
    return cmFileLockResult::MakeOk();
  }
  return result;
}

cmFileLockResult cmFileLockPool::ScopePool::Release(
  const std::string& filename)
{
  for (auto& lock : this->Locks) {
    if (lock.IsLocked(filename)) {
      return lock.Release();
    }
  }
  return cmFileLockResult::MakeOk();
}

bool cmFileLockPool::ScopePool::IsAlreadyLocked(
  const std::string& filename) const
{
  return std::any_of(this->Locks.begin(), this->Locks.end(),
                     [&filename](cmFileLock const& lock) -> bool {
                       return lock.IsLocked(filename);
                     });
}
