// Copyright 2013 The Flutter Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "flutter/fml/file.h"

#include <Fileapi.h>
#include <Shlwapi.h>
#include <fcntl.h>
#include <limits.h>
#include <sys/stat.h>
#include <string>

#include <algorithm>
#include <climits>
#include <cstring>
#include <optional>
#include <sstream>

#include "flutter/fml/build_config.h"
#include "flutter/fml/mapping.h"
#include "flutter/fml/platform/win/errors_win.h"
#include "flutter/fml/platform/win/wstring_conversion.h"

namespace fml {

static std::string GetFullHandlePath(const fml::UniqueFD& handle) {
  // Although the documentation claims that GetFinalPathNameByHandle is
  // supported for UWP apps, turns out it returns ACCESS_DENIED in this case
  // hence the need to workaround it by maintaining a map of file handles to
  // absolute paths populated by fml::OpenDirectory.
#ifdef WINUWP
  std::optional<fml::internal::os_win::DirCacheEntry> found =
      fml::internal::os_win::UniqueFDTraits::GetCacheEntry(handle.get());

  if (found) {
    FILE_ID_INFO info;

    BOOL result = GetFileInformationByHandleEx(
        handle.get(), FILE_INFO_BY_HANDLE_CLASS::FileIdInfo, &info,
        sizeof(FILE_ID_INFO));

    // Assuming it was possible to retrieve fileinfo, compare the id field.  The
    // handle hasn't been reused if the file identifier is the same as when it
    // was cached
    if (result && memcmp(found.value().id.Identifier, info.FileId.Identifier,
                         sizeof(FILE_ID_INFO))) {
      return WideStringToString(found.value().filename);
    } else {
      fml::internal::os_win::UniqueFDTraits::RemoveCacheEntry(handle.get());
    }
  }

  return std::string();
#else
  wchar_t buffer[MAX_PATH] = {0};
  const DWORD buffer_size = ::GetFinalPathNameByHandle(
      handle.get(), buffer, MAX_PATH, FILE_NAME_NORMALIZED);
  if (buffer_size == 0) {
    return {};
  }
  return WideStringToString({buffer, buffer_size});
#endif
}

static std::string GetAbsolutePath(const fml::UniqueFD& base_directory,
                                   const char* subpath) {
  std::stringstream stream;
  stream << GetFullHandlePath(base_directory) << "\\" << subpath;
  auto path = stream.str();
  std::replace(path.begin(), path.end(), '/', '\\');
  return path;
}

static std::wstring GetTemporaryDirectoryPath() {
  wchar_t wchar_path[MAX_PATH];
  auto result_size = ::GetTempPath(MAX_PATH, wchar_path);
  if (result_size > 0) {
    return {wchar_path, result_size};
  }
  return {};
}

static DWORD GetDesiredAccessFlags(FilePermission permission) {
  switch (permission) {
    case FilePermission::kRead:
      return GENERIC_READ;
    case FilePermission::kWrite:
      return GENERIC_WRITE;
    case FilePermission::kReadWrite:
      return GENERIC_READ | GENERIC_WRITE;
  }
  return GENERIC_READ;
}

static DWORD GetShareFlags(FilePermission permission) {
  switch (permission) {
    case FilePermission::kRead:
      return FILE_SHARE_READ;
    case FilePermission::kWrite:
      return FILE_SHARE_WRITE;
    case FilePermission::kReadWrite:
      return FILE_SHARE_READ | FILE_SHARE_WRITE;
  }
  return FILE_SHARE_READ;
}

static DWORD GetFileAttributesForUtf8Path(const char* absolute_path) {
  return ::GetFileAttributes(StringToWideString(absolute_path).c_str());
}

static DWORD GetFileAttributesForUtf8Path(const fml::UniqueFD& base_directory,
                                          const char* path) {
  std::string full_path = GetFullHandlePath(base_directory) + "\\" + path;
  return GetFileAttributesForUtf8Path(full_path.c_str());
}

std::string CreateTemporaryDirectory() {
  // Get the system temporary directory.
  auto temp_dir_container = GetTemporaryDirectoryPath();
  if (temp_dir_container.size() == 0) {
    FML_DLOG(ERROR) << "Could not get system temporary directory.";
    return {};
  }

  // Create a UUID.
  UUID uuid;
  RPC_STATUS status = UuidCreateSequential(&uuid);
  if (status != RPC_S_OK && status != RPC_S_UUID_LOCAL_ONLY) {
    FML_DLOG(ERROR) << "Could not create UUID for temporary directory.";
    return {};
  }

  RPC_WSTR uuid_string;
  status = UuidToString(&uuid, &uuid_string);
  if (status != RPC_S_OK) {
    FML_DLOG(ERROR) << "Could not map UUID to string for temporary directory.";
    return {};
  }

  std::wstring uuid_str(reinterpret_cast<wchar_t*>(uuid_string));
  RpcStringFree(&uuid_string);

  // Join the two and create a path to the new temporary directory.

  std::wstringstream stream;
  stream << temp_dir_container << "\\" << uuid_str;
  auto temp_dir = stream.str();

  auto dir_fd = OpenDirectory(WideStringToString(temp_dir).c_str(), true,
                              FilePermission::kReadWrite);
  if (!dir_fd.is_valid()) {
    FML_DLOG(ERROR) << "Could not get temporary directory file descriptor. "
                    << GetLastErrorMessage();
    return {};
  }

  return WideStringToString(std::move(temp_dir));
}

fml::UniqueFD OpenFile(const fml::UniqueFD& base_directory,
                       const char* path,
                       bool create_if_necessary,
                       FilePermission permission) {
  return OpenFile(GetAbsolutePath(base_directory, path).c_str(),
                  create_if_necessary, permission);
}

fml::UniqueFD OpenFile(const char* path,
                       bool create_if_necessary,
                       FilePermission permission) {
  if (path == nullptr || strlen(path) == 0) {
    return {};
  }

  auto file_name = StringToWideString({path});

  if (file_name.size() == 0) {
    return {};
  }

  const DWORD creation_disposition =
      create_if_necessary ? CREATE_NEW : OPEN_EXISTING;

  const DWORD flags = FILE_ATTRIBUTE_NORMAL;

  auto handle =
      CreateFile(file_name.c_str(),                  // lpFileName
                 GetDesiredAccessFlags(permission),  // dwDesiredAccess
                 GetShareFlags(permission),          // dwShareMode
                 nullptr,                            // lpSecurityAttributes  //
                 creation_disposition,               // dwCreationDisposition //
                 flags,   // dwFlagsAndAttributes                  //
                 nullptr  // hTemplateFile                         //
      );

  if (handle == INVALID_HANDLE_VALUE) {
    return {};
  }

  return fml::UniqueFD{handle};
}

fml::UniqueFD OpenDirectory(const fml::UniqueFD& base_directory,
                            const char* path,
                            bool create_if_necessary,
                            FilePermission permission) {
  return OpenDirectory(GetAbsolutePath(base_directory, path).c_str(),
                       create_if_necessary, permission);
}

fml::UniqueFD OpenDirectory(const char* path,
                            bool create_if_necessary,
                            FilePermission permission) {
  if (path == nullptr || strlen(path) == 0) {
    return {};
  }

  auto file_name = StringToWideString({path});

  if (file_name.size() == 0) {
    return {};
  }

  if (create_if_necessary) {
    if (!::CreateDirectory(file_name.c_str(), nullptr)) {
      if (GetLastError() != ERROR_ALREADY_EXISTS) {
        FML_DLOG(ERROR) << "Could not create directory. "
                        << GetLastErrorMessage();
        return {};
      }
    }
  }

  const DWORD creation_disposition = OPEN_EXISTING;

  const DWORD flags = FILE_ATTRIBUTE_NORMAL | FILE_FLAG_BACKUP_SEMANTICS;

  auto handle =
      CreateFile(file_name.c_str(),                  // lpFileName
                 GetDesiredAccessFlags(permission),  // dwDesiredAccess
                 GetShareFlags(permission),          // dwShareMode
                 nullptr,                            // lpSecurityAttributes  //
                 creation_disposition,               // dwCreationDisposition //
                 flags,   // dwFlagsAndAttributes                  //
                 nullptr  // hTemplateFile                         //
      );

  if (handle == INVALID_HANDLE_VALUE) {
    return {};
  }

#ifdef WINUWP
  FILE_ID_INFO info;

  BOOL result = GetFileInformationByHandleEx(
      handle, FILE_INFO_BY_HANDLE_CLASS::FileIdInfo, &info,
      sizeof(FILE_ID_INFO));

  // Only cache if it is possible to get valid a fileinformation to extract the
  // fileid to ensure correct handle versioning.
  if (result) {
    fml::internal::os_win::DirCacheEntry fc{file_name, info.FileId};

    fml::internal::os_win::UniqueFDTraits::StoreCacheEntry(handle, fc);
  }
#endif

  return fml::UniqueFD{handle};
}

fml::UniqueFD Duplicate(fml::UniqueFD::element_type descriptor) {
  if (descriptor == INVALID_HANDLE_VALUE) {
    return fml::UniqueFD{};
  }

  HANDLE duplicated = INVALID_HANDLE_VALUE;

  if (!::DuplicateHandle(
          GetCurrentProcess(),  // source process
          descriptor,           // source handle
          GetCurrentProcess(),  // target process
          &duplicated,          // target handle
          0,      // desired access (ignored because DUPLICATE_SAME_ACCESS)
          FALSE,  // inheritable
          DUPLICATE_SAME_ACCESS)  // options
  ) {
    return fml::UniqueFD{};
  }

  return fml::UniqueFD{duplicated};
}

bool IsDirectory(const fml::UniqueFD& directory) {
  BY_HANDLE_FILE_INFORMATION info;
  if (!::GetFileInformationByHandle(directory.get(), &info)) {
    return false;
  }
  return info.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY;
}

bool IsDirectory(const fml::UniqueFD& base_directory, const char* path) {
  return GetFileAttributesForUtf8Path(base_directory, path) &
         FILE_ATTRIBUTE_DIRECTORY;
}

bool IsFile(const std::string& path) {
  DWORD attributes = GetFileAttributesForUtf8Path(path.c_str());
  if (attributes == INVALID_FILE_ATTRIBUTES) {
    return false;
  }
  return !(attributes &
           (FILE_ATTRIBUTE_DIRECTORY | FILE_ATTRIBUTE_REPARSE_POINT));
}

bool UnlinkDirectory(const char* path) {
  if (!::RemoveDirectory(StringToWideString(path).c_str())) {
    FML_DLOG(ERROR) << "Could not remove directory: '" << path << "'. "
                    << GetLastErrorMessage();
    return false;
  }
  return true;
}

bool UnlinkDirectory(const fml::UniqueFD& base_directory, const char* path) {
  if (!::RemoveDirectory(
          StringToWideString(GetAbsolutePath(base_directory, path)).c_str())) {
    FML_DLOG(ERROR) << "Could not remove directory: '" << path << "'. "
                    << GetLastErrorMessage();
    return false;
  }
  return true;
}

bool UnlinkFile(const char* path) {
  if (!::DeleteFile(StringToWideString(path).c_str())) {
    FML_DLOG(ERROR) << "Could not remove file: '" << path << "'. "
                    << GetLastErrorMessage();
    return false;
  }
  return true;
}

bool UnlinkFile(const fml::UniqueFD& base_directory, const char* path) {
  if (!::DeleteFile(
          StringToWideString(GetAbsolutePath(base_directory, path)).c_str())) {
    FML_DLOG(ERROR) << "Could not remove file: '" << path << "'. "
                    << GetLastErrorMessage();
    return false;
  }
  return true;
}

bool TruncateFile(const fml::UniqueFD& file, size_t size) {
  LARGE_INTEGER large_size;
  large_size.QuadPart = size;
  large_size.LowPart = SetFilePointer(file.get(), large_size.LowPart,
                                      &large_size.HighPart, FILE_BEGIN);
  if (large_size.LowPart == INVALID_SET_FILE_POINTER &&
      GetLastError() != NO_ERROR) {
    FML_DLOG(ERROR) << "Could not update file size. " << GetLastErrorMessage();
    return false;
  }

  if (!::SetEndOfFile(file.get())) {
    FML_DLOG(ERROR) << "Could not commit file size update. "
                    << GetLastErrorMessage();
    return false;
  }
  return true;
}

bool FileExists(const fml::UniqueFD& base_directory, const char* path) {
  return GetFileAttributesForUtf8Path(base_directory, path) !=
         INVALID_FILE_ATTRIBUTES;
}

bool WriteAtomically(const fml::UniqueFD& base_directory,
                     const char* file_name,
                     const Mapping& mapping) {
  if (file_name == nullptr) {
    return false;
  }

  auto file_path = GetAbsolutePath(base_directory, file_name);
  std::stringstream stream;
  stream << file_path << ".temp";
  auto temp_file_path = stream.str();

  auto temp_file =
      OpenFile(temp_file_path.c_str(), true, FilePermission::kReadWrite);

  if (!temp_file.is_valid()) {
    FML_DLOG(ERROR) << "Could not create temporary file.";
    return false;
  }

  if (!TruncateFile(temp_file, mapping.GetSize())) {
    FML_DLOG(ERROR) << "Could not truncate the file to the correct size. "
                    << GetLastErrorMessage();
    return false;
  }

  {
    FileMapping temp_file_mapping(temp_file, {FileMapping::Protection::kRead,
                                              FileMapping::Protection::kWrite});
    if (temp_file_mapping.GetSize() != mapping.GetSize()) {
      FML_DLOG(ERROR) << "Temporary file mapping size was incorrect. Is "
                      << temp_file_mapping.GetSize() << ". Should be "
                      << mapping.GetSize() << ".";
      return false;
    }

    if (temp_file_mapping.GetMutableMapping() == nullptr) {
      FML_DLOG(ERROR) << "Temporary file does not have a mutable mapping.";
      return false;
    }

    ::memcpy(temp_file_mapping.GetMutableMapping(), mapping.GetMapping(),
             mapping.GetSize());

    if (!::FlushViewOfFile(temp_file_mapping.GetMutableMapping(),
                           mapping.GetSize())) {
      FML_DLOG(ERROR) << "Could not flush file view. " << GetLastErrorMessage();
      return false;
    }

    if (!::FlushFileBuffers(temp_file.get())) {
      FML_DLOG(ERROR) << "Could not flush file buffers. "
                      << GetLastErrorMessage();
      return false;
    }

    // File mapping is detroyed.
  }

  temp_file.reset();

  if (!::MoveFile(StringToWideString(temp_file_path).c_str(),
                  StringToWideString(file_path).c_str())) {
    FML_DLOG(ERROR)
        << "Could not replace temp file at correct path. File path: "
        << file_path << ". Temp file path: " << temp_file_path << " "
        << GetLastErrorMessage();
    return false;
  }

  return true;
}

bool VisitFiles(const fml::UniqueFD& directory, const FileVisitor& visitor) {
  std::string search_pattern = GetFullHandlePath(directory) + "\\*";
  WIN32_FIND_DATA find_file_data;
  HANDLE find_handle = ::FindFirstFile(
      StringToWideString(search_pattern).c_str(), &find_file_data);

  if (find_handle == INVALID_HANDLE_VALUE) {
    FML_DLOG(ERROR) << "Can't open the directory. Error: "
                    << GetLastErrorMessage();
    return true;  // continue to visit other files
  }

  do {
    std::string filename = WideStringToString(find_file_data.cFileName);
    if (filename != "." && filename != "..") {
      if (!visitor(directory, filename)) {
        ::FindClose(find_handle);
        return false;
      }
    }
  } while (::FindNextFile(find_handle, &find_file_data));
  ::FindClose(find_handle);
  return true;
}

}  // namespace fml
