//  Copyright (c) 2011-present, Facebook, Inc.  All rights reserved.
//  This source code is licensed under both the GPLv2 (found in the
//  COPYING file in the root directory) and Apache 2.0 License
//  (found in the LICENSE.Apache file in the root directory).
//
// Copyright (c) 2011 The LevelDB Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file. See the AUTHORS file for names of contributors.
#pragma once

#include <stdint.h>
#include <mutex>
#include <string>

#include "rocksdb/status.h"
#include "rocksdb/env.h"
#include "util/aligned_buffer.h"

#include <windows.h>


namespace rocksdb {
namespace port {

std::string GetWindowsErrSz(DWORD err);

inline Status IOErrorFromWindowsError(const std::string& context, DWORD err) {
  return ((err == ERROR_HANDLE_DISK_FULL) || (err == ERROR_DISK_FULL))
             ? Status::NoSpace(context, GetWindowsErrSz(err))
             : Status::IOError(context, GetWindowsErrSz(err));
}

inline Status IOErrorFromLastWindowsError(const std::string& context) {
  return IOErrorFromWindowsError(context, GetLastError());
}

inline Status IOError(const std::string& context, int err_number) {
  return (err_number == ENOSPC)
             ? Status::NoSpace(context, strerror(err_number))
             : Status::IOError(context, strerror(err_number));
}

// Note the below two do not set errno because they are used only here in this
// file
// on a Windows handle and, therefore, not necessary. Translating GetLastError()
// to errno
// is a sad business
inline int fsync(HANDLE hFile) {
  if (!FlushFileBuffers(hFile)) {
    return -1;
  }

  return 0;
}

SSIZE_T pwrite(HANDLE hFile, const char* src, size_t numBytes, uint64_t offset);

SSIZE_T pread(HANDLE hFile, char* src, size_t numBytes, uint64_t offset);

Status fallocate(const std::string& filename, HANDLE hFile, uint64_t to_size);

Status ftruncate(const std::string& filename, HANDLE hFile, uint64_t toSize);

size_t GetUniqueIdFromFile(HANDLE hFile, char* id, size_t max_size);

class WinFileData {
 protected:
  const std::string filename_;
  HANDLE hFile_;
  // If ture,  the I/O issued would be direct I/O which the buffer
  // will need to be aligned (not sure there is a guarantee that the buffer
  // passed in is aligned).
  const bool use_direct_io_;

 public:
  // We want this class be usable both for inheritance (prive
  // or protected) and for containment so __ctor and __dtor public
  WinFileData(const std::string& filename, HANDLE hFile, bool direct_io)
      : filename_(filename), hFile_(hFile), use_direct_io_(direct_io) {}

  virtual ~WinFileData() { this->CloseFile(); }

  bool CloseFile() {
    bool result = true;

    if (hFile_ != NULL && hFile_ != INVALID_HANDLE_VALUE) {
      result = ::CloseHandle(hFile_);
      assert(result);
      hFile_ = NULL;
    }
    return result;
  }

  const std::string& GetName() const { return filename_; }

  HANDLE GetFileHandle() const { return hFile_; }

  bool use_direct_io() const { return use_direct_io_; }

  WinFileData(const WinFileData&) = delete;
  WinFileData& operator=(const WinFileData&) = delete;
};

class WinSequentialFile : protected WinFileData, public SequentialFile {

  // Override for behavior change when creating a custom env
  virtual SSIZE_T PositionedReadInternal(char* src, size_t numBytes,
    uint64_t offset) const;

public:
  WinSequentialFile(const std::string& fname, HANDLE f,
    const EnvOptions& options);

  ~WinSequentialFile();

  WinSequentialFile(const WinSequentialFile&) = delete;
  WinSequentialFile& operator=(const WinSequentialFile&) = delete;

  virtual Status Read(size_t n, Slice* result, char* scratch) override;
  virtual Status PositionedRead(uint64_t offset, size_t n, Slice* result,
    char* scratch) override;

  virtual Status Skip(uint64_t n) override;

  virtual Status InvalidateCache(size_t offset, size_t length) override;

  virtual bool use_direct_io() const override { return WinFileData::use_direct_io(); }
};

// mmap() based random-access
class WinMmapReadableFile : private WinFileData, public RandomAccessFile {
  HANDLE hMap_;

  const void* mapped_region_;
  const size_t length_;

 public:
  // mapped_region_[0,length-1] contains the mmapped contents of the file.
  WinMmapReadableFile(const std::string& fileName, HANDLE hFile, HANDLE hMap,
                      const void* mapped_region, size_t length);

  ~WinMmapReadableFile();

  WinMmapReadableFile(const WinMmapReadableFile&) = delete;
  WinMmapReadableFile& operator=(const WinMmapReadableFile&) = delete;

  virtual Status Read(uint64_t offset, size_t n, Slice* result,
                      char* scratch) const override;

  virtual Status InvalidateCache(size_t offset, size_t length) override;

  virtual size_t GetUniqueId(char* id, size_t max_size) const override;
};

// We preallocate and use memcpy to append new
// data to the file.  This is safe since we either properly close the
// file before reading from it, or for log files, the reading code
// knows enough to skip zero suffixes.
class WinMmapFile : private WinFileData, public WritableFile {
 private:
  HANDLE hMap_;

  const size_t page_size_;  // We flush the mapping view in page_size
  // increments. We may decide if this is a memory
  // page size or SSD page size
  const size_t
      allocation_granularity_;  // View must start at such a granularity

  size_t reserved_size_;  // Preallocated size

  size_t mapping_size_;  // The max size of the mapping object
  // we want to guess the final file size to minimize the remapping
  size_t view_size_;  // How much memory to map into a view at a time

  char* mapped_begin_;  // Must begin at the file offset that is aligned with
  // allocation_granularity_
  char* mapped_end_;
  char* dst_;  // Where to write next  (in range [mapped_begin_,mapped_end_])
  char* last_sync_;  // Where have we synced up to

  uint64_t file_offset_;  // Offset of mapped_begin_ in file

  // Do we have unsynced writes?
  bool pending_sync_;

  // Can only truncate or reserve to a sector size aligned if
  // used on files that are opened with Unbuffered I/O
  Status TruncateFile(uint64_t toSize);

  Status UnmapCurrentRegion();

  Status MapNewRegion();

  virtual Status PreallocateInternal(uint64_t spaceToReserve);

 public:
  WinMmapFile(const std::string& fname, HANDLE hFile, size_t page_size,
              size_t allocation_granularity, const EnvOptions& options);

  ~WinMmapFile();

  WinMmapFile(const WinMmapFile&) = delete;
  WinMmapFile& operator=(const WinMmapFile&) = delete;

  virtual Status Append(const Slice& data) override;

  // Means Close() will properly take care of truncate
  // and it does not need any additional information
  virtual Status Truncate(uint64_t size) override;

  virtual Status Close() override;

  virtual Status Flush() override;

  // Flush only data
  virtual Status Sync() override;

  /**
  * Flush data as well as metadata to stable storage.
  */
  virtual Status Fsync() override;

  /**
  * Get the size of valid data in the file. This will not match the
  * size that is returned from the filesystem because we use mmap
  * to extend file by map_size every time.
  */
  virtual uint64_t GetFileSize() override;

  virtual Status InvalidateCache(size_t offset, size_t length) override;

  virtual Status Allocate(uint64_t offset, uint64_t len) override;

  virtual size_t GetUniqueId(char* id, size_t max_size) const override;
};

class WinRandomAccessImpl {
 protected:
  WinFileData* file_base_;
  size_t       alignment_;

  // Override for behavior change when creating a custom env
  virtual SSIZE_T PositionedReadInternal(char* src, size_t numBytes,
                                         uint64_t offset) const;

  WinRandomAccessImpl(WinFileData* file_base, size_t alignment,
                      const EnvOptions& options);

  virtual ~WinRandomAccessImpl() {}

  Status ReadImpl(uint64_t offset, size_t n, Slice* result,
                  char* scratch) const;

  size_t GetAlignment() const { return alignment_; }

 public:

  WinRandomAccessImpl(const WinRandomAccessImpl&) = delete;
  WinRandomAccessImpl& operator=(const WinRandomAccessImpl&) = delete;
};

// pread() based random-access
class WinRandomAccessFile
    : private WinFileData,
      protected WinRandomAccessImpl,  // Want to be able to override
                                      // PositionedReadInternal
      public RandomAccessFile {
 public:
  WinRandomAccessFile(const std::string& fname, HANDLE hFile, size_t alignment,
                      const EnvOptions& options);

  ~WinRandomAccessFile();

  virtual Status Read(uint64_t offset, size_t n, Slice* result,
                      char* scratch) const override;

  virtual size_t GetUniqueId(char* id, size_t max_size) const override;

  virtual bool use_direct_io() const override { return WinFileData::use_direct_io(); }

  virtual Status InvalidateCache(size_t offset, size_t length) override;

  virtual size_t GetRequiredBufferAlignment() const override;
};

// This is a sequential write class. It has been mimicked (as others) after
// the original Posix class. We add support for unbuffered I/O on windows as
// well
// we utilize the original buffer as an alignment buffer to write directly to
// file with no buffering.
// No buffering requires that the provided buffer is aligned to the physical
// sector size (SSD page size) and
// that all SetFilePointer() operations to occur with such an alignment.
// We thus always write in sector/page size increments to the drive and leave
// the tail for the next write OR for Close() at which point we pad with zeros.
// No padding is required for
// buffered access.
class WinWritableImpl {
 protected:
  WinFileData* file_data_;
  const uint64_t alignment_;
  uint64_t next_write_offset_; // Needed because Windows does not support O_APPEND
  uint64_t reservedsize_;  // how far we have reserved space

  virtual Status PreallocateInternal(uint64_t spaceToReserve);

  WinWritableImpl(WinFileData* file_data, size_t alignment);

  ~WinWritableImpl() {}

  uint64_t GetAlignement() const { return alignment_; }

  Status AppendImpl(const Slice& data);

  // Requires that the data is aligned as specified by
  // GetRequiredBufferAlignment()
  Status PositionedAppendImpl(const Slice& data, uint64_t offset);

  Status TruncateImpl(uint64_t size);

  Status CloseImpl();

  Status SyncImpl();

  uint64_t GetFileNextWriteOffset() {
    // Double accounting now here with WritableFileWriter
    // and this size will be wrong when unbuffered access is used
    // but tests implement their own writable files and do not use
    // WritableFileWrapper
    // so we need to squeeze a square peg through
    // a round hole here.
    return next_write_offset_;
  }

  Status AllocateImpl(uint64_t offset, uint64_t len);

 public:
  WinWritableImpl(const WinWritableImpl&) = delete;
  WinWritableImpl& operator=(const WinWritableImpl&) = delete;
};

class WinWritableFile : private WinFileData,
                        protected WinWritableImpl,
                        public WritableFile {
 public:
  WinWritableFile(const std::string& fname, HANDLE hFile, size_t alignment,
                  size_t capacity, const EnvOptions& options);

  ~WinWritableFile();

  virtual Status Append(const Slice& data) override;

  // Requires that the data is aligned as specified by
  // GetRequiredBufferAlignment()
  virtual Status PositionedAppend(const Slice& data, uint64_t offset) override;

  // Need to implement this so the file is truncated correctly
  // when buffered and unbuffered mode
  virtual Status Truncate(uint64_t size) override;

  virtual Status Close() override;

  // write out the cached data to the OS cache
  // This is now taken care of the WritableFileWriter
  virtual Status Flush() override;

  virtual Status Sync() override;

  virtual Status Fsync() override;

  // Indicates if the class makes use of direct I/O
  // Use PositionedAppend
  virtual bool use_direct_io() const override;

  virtual size_t GetRequiredBufferAlignment() const override;

  virtual uint64_t GetFileSize() override;

  virtual Status Allocate(uint64_t offset, uint64_t len) override;

  virtual size_t GetUniqueId(char* id, size_t max_size) const override;
};

class WinRandomRWFile : private WinFileData,
                        protected WinRandomAccessImpl,
                        protected WinWritableImpl,
                        public RandomRWFile {
 public:
  WinRandomRWFile(const std::string& fname, HANDLE hFile, size_t alignment,
                  const EnvOptions& options);

  ~WinRandomRWFile() {}

  // Indicates if the class makes use of direct I/O
  // If false you must pass aligned buffer to Write()
  virtual bool use_direct_io() const override;

  // Use the returned alignment value to allocate aligned
  // buffer for Write() when use_direct_io() returns true
  virtual size_t GetRequiredBufferAlignment() const override;

  // Write bytes in `data` at  offset `offset`, Returns Status::OK() on success.
  // Pass aligned buffer when use_direct_io() returns true.
  virtual Status Write(uint64_t offset, const Slice& data) override;

  // Read up to `n` bytes starting from offset `offset` and store them in
  // result, provided `scratch` size should be at least `n`.
  // Returns Status::OK() on success.
  virtual Status Read(uint64_t offset, size_t n, Slice* result,
                      char* scratch) const override;

  virtual Status Flush() override;

  virtual Status Sync() override;

  virtual Status Fsync() { return Sync(); }

  virtual Status Close() override;
};

class WinDirectory : public Directory {
 public:
  WinDirectory() {}

  virtual Status Fsync() override;
};

class WinFileLock : public FileLock {
 public:
  explicit WinFileLock(HANDLE hFile) : hFile_(hFile) {
    assert(hFile != NULL);
    assert(hFile != INVALID_HANDLE_VALUE);
  }

  ~WinFileLock();

 private:
  HANDLE hFile_;
};
}
}
