// 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 <algorithm>
#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) {
  wchar_t buffer[MAX_PATH] = {0};
  const DWORD buffer_size = ::GetFinalPathNameByHandle(
      handle.get(), buffer, MAX_PATH, FILE_NAME_NORMALIZED);
  if (buffer_size == 0) {
    FML_DLOG(ERROR) << "Could not get file handle path. "
                    << GetLastErrorMessage();
    return {};
  }
  return WideStringToString({buffer, buffer_size});
}

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};
  }
  FML_DLOG(ERROR) << "Could not get temporary directory path. "
                  << GetLastErrorMessage();
  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";
    return {};
  }

  RPC_WSTR uuid_string;
  status = UuidToString(&uuid, &uuid_string);
  if (status != RPC_S_OK) {
    FML_DLOG(ERROR) << "Could not create UUID to string.";
    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 FD. "
                    << 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) {
    FML_DLOG(ERROR) << "Could not open file. " << GetLastErrorMessage();
    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) {
    FML_DLOG(ERROR) << "Could not open file. " << GetLastErrorMessage();
    return {};
  }

  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)) {
    FML_DLOG(ERROR) << "Could not get file information. "
                    << GetLastErrorMessage();
    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
