/**
 *   Copyright 2011-2015 Quickstep Technologies LLC.
 *   Copyright 2015 Pivotal Software, Inc.
 *
 *   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
 *
 *       http://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.
 **/

#define __STDC_FORMAT_MACROS

#include "storage/FileManagerWindows.hpp"

#define WIN32_LEAN_AND_MEAN
#include <io.h>
#include <stdio.h>
#include <windows.h>

#include <cerrno>
#include <cinttypes>
#include <cstddef>
#include <cstdint>
#include <cstring>
#include <string>

#include "storage/StorageBlockInfo.hpp"
#include "storage/StorageConstants.hpp"
#include "storage/StorageErrors.hpp"
#include "utility/Macros.hpp"
#include "utility/StringUtil.hpp"

using std::size_t;
using std::strerror;
using std::string;
using std::uint64_t;

namespace quickstep {

block_id_counter FileManagerWindows::getMaxUsedBlockCounter(const block_id_domain block_domain) const {
  const string block_domain_str(ToZeroPaddedString(block_domain, kBlockIdDomainLengthInDigits));

  string glob_pattern(storage_path_);
  glob_pattern.append("qsblk_");
  glob_pattern.append(block_domain_str);
  glob_pattern.append("_*.qsb");

  WIN32_FIND_DATA find_data;
  HANDLE find_handle = INVALID_HANDLE_VALUE;
  DWORD error_code = 0;

  find_handle = FindFirstFile(glob_pattern.c_str(), &find_data);
  if (find_handle == INVALID_HANDLE_VALUE) {
    error_code = GetLastError();
    if (error_code != ERROR_FILE_NOT_FOUND) {
      LOG_WARNING("Failed to retrieve blockfiles with error_code: " << error_code);
    }
    return 0;
  }

  string filename_pattern("qsblk_");
  filename_pattern.append(block_domain_str);
  filename_pattern.append("_%");
  filename_pattern.append(SCNu64);
  filename_pattern.append(".qsb");

  block_id_counter counter_max = 0, counter;
  do {
    if (sscanf(find_data.cFileName, filename_pattern.c_str(), &counter) == 1
        && counter > counter_max) {
      counter_max = counter;
    }
  } while (FindNextFile(find_handle, &find_data) != 0);

  error_code = GetLastError();
  if (error_code != ERROR_NO_MORE_FILES) {
    LOG_WARNING("Failed to FindNextFile with error_code: " << error_code);
  }

  if (FindClose(find_handle) == 0) {
    LOG_WARNING("Failed to close the file with error_code: " << GetLastError());
  }

  return counter_max;
}

size_t FileManagerWindows::numSlots(const block_id block) const {
  string filename(blockFilename(block));
  WIN32_FILE_ATTRIBUTE_DATA file_stat;

  if (!GetFileAttributesEx(filename.c_str(), GetFileExInfoStandard, &file_stat)) {
    DWORD error_code = GetLastError();
    if (error_code != ERROR_FILE_NOT_FOUND) {
      LOG_WARNING("Failed to retrieve info about file " << filename << " with error_code: " << error_code);
    }
    return 0;
  }

  uint64_t file_size = (static_cast<uint64_t>(file_stat.nFileSizeHigh) << 32) | file_stat.nFileSizeLow;

  if ((file_size % kSlotSizeBytes) != 0) {
    LOG(FATAL) << "The file " << filename << " was corrupted.";
  }

  return static_cast<size_t>(file_size / kSlotSizeBytes);
}

bool FileManagerWindows::deleteBlockOrBlob(const block_id block) {
  string filename(blockFilename(block));

  if ((DeleteFile(filename.c_str()) != 0) || (GetLastError() == ERROR_FILE_NOT_FOUND)) {
    return true;
  } else {
    LOG_WARNING("Failed to delete file " << filename << " with error_code: " << GetLastError());
  }
}

bool FileManagerWindows::readBlockOrBlob(const block_id block,
                                         void *buffer,
                                         const size_t length) {
  DEBUG_ASSERT(buffer);
  DEBUG_ASSERT(length % kSlotSizeBytes == 0);

  string filename(blockFilename(block));

  FILE *file = fopen(filename.c_str(), "rb");
  if (file == nullptr) {
    // Note: On most, but not all, library implementations, the errno variable
    //       is set to a system-specific error code on failure.
    LOG_WARNING("Failed to open file " << filename << " with error: " << strerror(errno));
    return false;
  }

  const size_t bytes = std::fread(buffer, sizeof(char), length, file);
  const bool result_is_ok = (bytes == length);
  if (!result_is_ok) {
    if (std::feof(file)) {
      LOG_WARNING("Failed to read file " << filename << " since EOF was reached unexpectedly");
    } else {
      LOG_WARNING("Failed to read file " << filename << " with error: " << strerror(ferror(file)));
      clearerr(file);
    }
  }

  if (fclose(file)) {
    // Note: fclose does not set errno on failure.
    LOG_WARNING("Failed to close file " << filename);
  }

  return result_is_ok;
}

bool FileManagerWindows::writeBlockOrBlob(const block_id block,
                                          const void *buffer,
                                          const size_t length) {
  DEBUG_ASSERT(buffer);
  DEBUG_ASSERT(length % kSlotSizeBytes == 0);

  string filename(blockFilename(block));

  FILE *file = fopen(filename.c_str(), "wb");
  if (file == nullptr) {
    // Note: On most, but not all, library implementations, the errno variable
    //       is set to a system-specific error code on failure.
    LOG_WARNING("Failed to open file " << filename << " with error: " << strerror(errno));
    return false;
  }

  const size_t bytes = std::fwrite(buffer, sizeof(char), length, file);
  const bool result_is_ok = (bytes == length);
  if (!result_is_ok) {
    LOG_WARNING("Failed to write file " << filename << " with error: " << strerror(ferror(file)));
    clearerr(file);
  }

  if (fflush(file)) {
    LOG_WARNING("Failed to flush file " << filename << " with error: " << strerror(ferror(file)));
  }

  if (!FlushFileBuffers(reinterpret_cast<HANDLE>(_get_osfhandle(_fileno(file))))) {
    LOG_WARNING("Failed to re-flush file " << filename << " with error: " << strerror(ferror(file)));
  }

  if (fclose(file)) {
    // Note: fclose does not set errno on failure.
    LOG_WARNING("Failed to close file " << filename);
  }

  return result_is_ok;
}

}  // namespace quickstep
