/* 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 <assert.h>

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

cmFileLockPool::cmFileLockPool() = default;

cmFileLockPool::~cmFileLockPool()
{
  cmDeleteAll(this->FunctionScopes);
  cmDeleteAll(this->FileScopes);
}

void cmFileLockPool::PushFunctionScope()
{
  this->FunctionScopes.push_back(new ScopePool());
}

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

void cmFileLockPool::PushFileScope()
{
  this->FileScopes.push_back(new ScopePool());
}

void cmFileLockPool::PopFileScope()
{
  assert(!this->FileScopes.empty());
  delete this->FileScopes.back();
  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()
{
  cmDeleteAll(this->Locks);
}

cmFileLockResult cmFileLockPool::ScopePool::Lock(const std::string& filename,
                                                 unsigned long timeoutSec)
{
  cmFileLock* lock = new cmFileLock();
  const cmFileLockResult result = lock->Lock(filename, timeoutSec);
  if (result.IsOk()) {
    this->Locks.push_back(lock);
    return cmFileLockResult::MakeOk();
  }
  delete lock;
  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
{
  for (auto const& lock : this->Locks) {
    if (lock->IsLocked(filename)) {
      return true;
    }
  }
  return false;
}
