//===----------------------------------------------------------------------===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//

#include "lldb/Host/windows/FileWindows.h"

#include "lldb/Host/windows/windows.h"

#include <climits>
#include <io.h>
#include <mutex>
#include <stdio.h>

#include "lldb/Utility/Status.h"
#include "llvm/Support/raw_ostream.h"

using namespace lldb_private;

NativeFileWindows::NativeFileWindows(FILE *fh, OpenOptions options,
                                     bool transfer_ownership)
    : NativeFileBase(fh, options, transfer_ownership) {
  HANDLE h = INVALID_HANDLE_VALUE;
  if (fh == stdin)
    h = ::GetStdHandle(STD_INPUT_HANDLE);
  else if (fh == stdout)
    h = ::GetStdHandle(STD_OUTPUT_HANDLE);
  else if (fh == stderr)
    h = ::GetStdHandle(STD_ERROR_HANDLE);
  m_is_windows_console =
      h != INVALID_HANDLE_VALUE && ::GetFileType(h) == FILE_TYPE_CHAR;
}

NativeFileWindows::NativeFileWindows(int fd, OpenOptions options,
                                     bool transfer_ownership)
    : NativeFileBase(fd, options, transfer_ownership) {
  HANDLE h = INVALID_HANDLE_VALUE;
  if (fd == STDIN_FILENO)
    h = ::GetStdHandle(STD_INPUT_HANDLE);
  else if (fd == STDOUT_FILENO)
    h = ::GetStdHandle(STD_OUTPUT_HANDLE);
  else if (fd == STDERR_FILENO)
    h = ::GetStdHandle(STD_ERROR_HANDLE);
  m_is_windows_console =
      h != INVALID_HANDLE_VALUE && ::GetFileType(h) == FILE_TYPE_CHAR;
}

void NativeFileWindows::CalculateInteractiveAndTerminal() {
  const int fd = GetDescriptor();
  if (!File::DescriptorIsValid(fd)) {
    m_is_interactive = eLazyBoolNo;
    m_is_real_terminal = eLazyBoolNo;
    m_supports_colors = eLazyBoolNo;
    return;
  }
  m_is_interactive = eLazyBoolNo;
  m_is_real_terminal = eLazyBoolNo;
  if (_isatty(fd)) {
    m_is_interactive = eLazyBoolYes;
    m_is_real_terminal = eLazyBoolYes;
#if defined(ENABLE_VIRTUAL_TERMINAL_PROCESSING)
    m_supports_colors = eLazyBoolYes;
#endif
  }
}

int NativeFileWindows::Fileno(FILE *fh) const { return ::_fileno(fh); }

int NativeFileWindows::Dup(int fd) const { return ::_dup(fd); }

IOObject::WaitableHandle NativeFileWindows::GetWaitableHandle() {
  return (HANDLE)_get_osfhandle(GetDescriptor());
}

Status NativeFileWindows::Sync() {
  Status error;
  if (ValueGuard descriptor_guard = DescriptorIsValid()) {
    if (FlushFileBuffers((HANDLE)_get_osfhandle(m_descriptor)) == 0)
      error = Status::FromErrorString("unknown error");
  } else {
    error = Status::FromErrorString("invalid file handle");
  }
  return error;
}

bool NativeFileWindows::TryWriteStreamUnlocked(const void *buf,
                                               size_t &num_bytes,
                                               Status &error) {
  if (!m_is_windows_console)
    return false;
  // Bypass fwrite for console output: use raw_fd_ostream so that the Windows
  // console renders non-ASCII characters via its UTF-16 path.
  llvm::raw_fd_ostream(_fileno(m_stream), false)
      .write((const char *)buf, num_bytes);
  return true;
}

Status NativeFileWindows::Read(void *buf, size_t &num_bytes, off_t &offset) {
  Status error;

  int fd = GetDescriptor();
  if (fd != kInvalidDescriptor) {
    // Win32 has no pread(); emulate it by saving the current offset, seeking,
    // reading, and restoring.
    std::lock_guard<std::mutex> guard(offset_access_mutex);
    long cur = ::lseek(m_descriptor, 0, SEEK_CUR);
    SeekFromStart(offset);
    error = NativeFileBase::Read(buf, num_bytes);
    if (!error.Fail())
      SeekFromStart(cur);
  } else {
    num_bytes = 0;
    error = Status::FromErrorString("invalid file handle");
  }
  return error;
}

Status NativeFileWindows::Write(const void *buf, size_t &num_bytes,
                                off_t &offset) {
  Status error;

  int fd = GetDescriptor();
  if (fd != kInvalidDescriptor) {
    // Win32 has no pwrite(); same trick as Read above, but the post-write
    // file position is what the caller wants reported back via `offset`.
    std::lock_guard<std::mutex> guard(offset_access_mutex);
    long cur = ::lseek(m_descriptor, 0, SEEK_CUR);
    SeekFromStart(offset);
    error = NativeFileBase::Write(buf, num_bytes);
    long after = ::lseek(m_descriptor, 0, SEEK_CUR);

    if (!error.Fail())
      SeekFromStart(cur);

    offset = after;
  } else {
    num_bytes = 0;
    error = Status::FromErrorString("invalid file handle");
  }
  return error;
}

void NativeFileWindows::OnStreamOpened() {
  if ((m_options & OpenOptionsModeMask) == eOpenOptionReadOnly)
    setvbuf(m_stream, nullptr, _IONBF, 0);
}

char NativeFileWindows::ID = 0;
