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

#include <windows.h>

#include "cmFileLock.h"
#include "cmSystemTools.h"

static unsigned long const LOCK_LEN = static_cast<unsigned long>(-1);

cmFileLock::cmFileLock()
  : Overlapped(cm::make_unique<OVERLAPPED>())
{
  ZeroMemory(this->Overlapped.get(), sizeof(*this->Overlapped));
}

cmFileLockResult cmFileLock::Release()
{
  if (this->Filename.empty()) {
    return cmFileLockResult::MakeOk();
  }
  const DWORD reserved = 0;
  ZeroMemory(this->Overlapped.get(), sizeof(*this->Overlapped));

  const BOOL unlockResult =
    UnlockFileEx(File, reserved, LOCK_LEN, LOCK_LEN, this->Overlapped.get());

  this->Filename = "";

  CloseHandle(this->File);

  this->File = INVALID_HANDLE_VALUE;

  if (unlockResult) {
    return cmFileLockResult::MakeOk();
  } else {
    return cmFileLockResult::MakeSystem();
  }
}

cmFileLockResult cmFileLock::OpenFile()
{
  const DWORD access = GENERIC_READ | GENERIC_WRITE;
  const DWORD shareMode = FILE_SHARE_READ | FILE_SHARE_WRITE;
  const PSECURITY_ATTRIBUTES security = nullptr;
  const DWORD attr = 0;
  const HANDLE templ = nullptr;
  this->File = CreateFileW(
    cmSystemTools::ConvertToWindowsExtendedPath(this->Filename).c_str(),
    access, shareMode, security, OPEN_EXISTING, attr, templ);
  if (this->File == INVALID_HANDLE_VALUE) {
    return cmFileLockResult::MakeSystem();
  } else {
    return cmFileLockResult::MakeOk();
  }
}

cmFileLockResult cmFileLock::LockWithoutTimeout()
{
  cmFileLockResult lock_result = cmFileLockResult::MakeOk();
  if (!this->LockFile(LOCKFILE_EXCLUSIVE_LOCK)) {
    lock_result = cmFileLockResult::MakeSystem();
  }
  CloseHandle(this->Overlapped->hEvent);
  return lock_result;
}

cmFileLockResult cmFileLock::LockWithTimeout(unsigned long seconds)
{
  cmFileLockResult lock_result = cmFileLockResult::MakeOk();
  const DWORD flags = LOCKFILE_EXCLUSIVE_LOCK | LOCKFILE_FAIL_IMMEDIATELY;
  bool in_time = true;
  while (in_time && !this->LockFile(flags)) {
    switch (GetLastError()) {
      case ERROR_INVALID_HANDLE:
        lock_result = cmFileLockResult::MakeSystem();
        break;
      case ERROR_LOCK_VIOLATION:
        if (seconds == 0) {
          in_time = false;
          lock_result = cmFileLockResult::MakeTimeout();
          continue;
        }
        --seconds;
        cmSystemTools::Delay(1000);
        continue;
      case ERROR_IO_PENDING:
        switch (
          WaitForSingleObject(this->Overlapped->hEvent, seconds * 1000)) {
          case WAIT_OBJECT_0:
            break;
          case WAIT_TIMEOUT:
            lock_result = cmFileLockResult::MakeTimeout();
            break;
          default:
            lock_result = cmFileLockResult::MakeSystem();
            break;
        }
        break;
      default:
        lock_result = cmFileLockResult::MakeSystem();
        break;
    }
  }
  CloseHandle(this->Overlapped->hEvent);
  return lock_result;
}

int cmFileLock::LockFile(int flags)
{
  const DWORD reserved = 0;

  this->Overlapped->hEvent = CreateEvent(nullptr, TRUE, FALSE, nullptr);
  if (this->Overlapped->hEvent == nullptr) {
    return false;
  }
  return LockFileEx(this->File, flags, reserved, LOCK_LEN, LOCK_LEN,
                    this->Overlapped.get());
}
