// Copyright 2017 The Bazel Authors. All rights reserved.
//
// 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.

#ifndef WIN32_LEAN_AND_MEAN
#define WIN32_LEAN_AND_MEAN
#endif
#include <string.h>
#include <windows.h>

#include <fstream>
#include <iostream>
#include <sstream>
#include <string>
#include <unordered_map>

#include "src/main/cpp/util/file_platform.h"
#include "src/main/cpp/util/path_platform.h"
#include "src/main/cpp/util/strings.h"
#include "src/main/native/windows/file.h"

using std::ifstream;
using std::string;
using std::stringstream;
using std::unordered_map;
using std::wstring;

#ifndef SYMBOLIC_LINK_FLAG_DIRECTORY
#define SYMBOLIC_LINK_FLAG_DIRECTORY 0x1
#endif

namespace {

const wchar_t* manifest_filename;
const wchar_t* runfiles_base_dir;

string GetLastErrorString() {
  DWORD last_error = GetLastError();
  if (last_error == 0) {
    return string();
  }

  char* message_buffer;
  size_t size = FormatMessageA(
      FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM |
          FORMAT_MESSAGE_IGNORE_INSERTS,
      nullptr, last_error, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
      (LPSTR)&message_buffer, 0, nullptr);

  stringstream result;
  result << "(error: " << last_error << "): " << message_buffer;
  LocalFree(message_buffer);
  return result.str();
}

void die(const wchar_t* format, ...) {
  va_list ap;
  va_start(ap, format);
  fputws(L"build-runfiles error: ", stderr);
  vfwprintf(stderr, format, ap);
  va_end(ap);
  fputwc(L'\n', stderr);
  fputws(L"manifest file name: ", stderr);
  fputws(manifest_filename, stderr);
  fputwc(L'\n', stderr);
  fputws(L"runfiles base directory: ", stderr);
  fputws(runfiles_base_dir, stderr);
  fputwc(L'\n', stderr);
  exit(1);
}

wstring AsAbsoluteWindowsPath(const wchar_t* path) {
  wstring wpath;
  string error;
  if (!blaze_util::AsAbsoluteWindowsPath(path, &wpath, &error)) {
    die(L"Couldn't convert %s to absolute Windows path: %hs", path,
        error.c_str());
  }
  return wpath;
}

bool DoesDirectoryPathExist(const wchar_t* path) {
  DWORD dwAttrib = GetFileAttributesW(AsAbsoluteWindowsPath(path).c_str());

  return (dwAttrib != INVALID_FILE_ATTRIBUTES &&
          (dwAttrib & FILE_ATTRIBUTE_DIRECTORY));
}

wstring GetParentDirFromPath(const wstring& path) {
  return path.substr(0, path.find_last_of(L"\\/"));
}

inline void Trim(wstring& str) {
  str.erase(0, str.find_first_not_of(' '));
  str.erase(str.find_last_not_of(' ') + 1);
}

bool ReadSymlink(const wstring& abs_path, wstring* target, wstring* error) {
  switch (bazel::windows::ReadSymlinkOrJunction(abs_path, target, error)) {
    case bazel::windows::ReadSymlinkOrJunctionResult::kSuccess:
      return true;
    case bazel::windows::ReadSymlinkOrJunctionResult::kAccessDenied:
      *error = L"access is denied";
      break;
    case bazel::windows::ReadSymlinkOrJunctionResult::kDoesNotExist:
      *error = L"path does not exist";
      break;
    case bazel::windows::ReadSymlinkOrJunctionResult::kNotALink:
      *error = L"path is not a link";
      break;
    case bazel::windows::ReadSymlinkOrJunctionResult::kUnknownLinkType:
      *error = L"unknown link type";
      break;
    default:
      // This is bazel::windows::ReadSymlinkOrJunctionResult::kError (1).
      // The JNI code puts a custom message in 'error'.
      break;
  }
  return false;
}

}  // namespace

class RunfilesCreator {
  typedef std::unordered_map<std::wstring, std::wstring> ManifestFileMap;

 public:
  RunfilesCreator(const wstring& manifest_path,
                  const wstring& runfiles_output_base)
      : manifest_path_(manifest_path),
        runfiles_output_base_(runfiles_output_base) {
    SetupOutputBase();
    if (!SetCurrentDirectoryW(runfiles_output_base_.c_str())) {
      die(L"SetCurrentDirectoryW failed (%s): %hs",
          runfiles_output_base_.c_str(), GetLastErrorString().c_str());
    }
  }

  void ReadManifest(bool allow_relative, bool ignore_metadata) {
    ifstream manifest_file(
        AsAbsoluteWindowsPath(manifest_path_.c_str()).c_str());

    if (!manifest_file) {
      die(L"Couldn't open MANIFEST file: %s", manifest_path_.c_str());
    }

    string line;
    int lineno = 0;
    while (getline(manifest_file, line)) {
      lineno++;
      // Skip metadata lines. They are used solely for
      // dependency checking.
      if (ignore_metadata && lineno % 2 == 0) {
        continue;
      }

      size_t space_pos = line.find_first_of(' ');
      wstring wline = blaze_util::CstringToWstring(line);
      wstring link, target;
      if (space_pos == string::npos) {
        link = wline;
        target = wstring();
      } else {
        link = wline.substr(0, space_pos);
        target = wline.substr(space_pos + 1);
      }

      // Removing leading and trailing spaces
      Trim(link);
      Trim(target);

      // We sometimes need to create empty files under the runfiles tree.
      // For example, for python binary, __init__.py is needed under every
      // directory. Storing an entry with an empty target indicates we need to
      // create such a file when creating the runfiles tree.
      if (!allow_relative && !target.empty() &&
          !blaze_util::IsAbsolute(target)) {
        die(L"Target cannot be relative path: %hs", line.c_str());
      }

      link = AsAbsoluteWindowsPath(link.c_str());
      if (!target.empty()) {
        target = AsAbsoluteWindowsPath(target.c_str());
      }

      manifest_file_map.insert(make_pair(link, target));
    }
  }

  void CreateRunfiles() {
    ScanTreeAndPrune(runfiles_output_base_);
    CreateFiles();
    CopyManifestFile();
  }

 private:
  void SetupOutputBase() {
    if (!DoesDirectoryPathExist(runfiles_output_base_.c_str())) {
      MakeDirectoriesOrDie(runfiles_output_base_);
    }
  }

  void MakeDirectoriesOrDie(const wstring& path) {
    if (!blaze_util::MakeDirectoriesW(path, 0755)) {
      die(L"MakeDirectoriesW failed (%s): %hs", path.c_str(),
          GetLastErrorString().c_str());
    }
  }

  void RemoveDirectoryOrDie(const wstring& path) {
    if (!RemoveDirectoryW(path.c_str())) {
      die(L"RemoveDirectoryW failed (%s): %hs", GetLastErrorString().c_str());
    }
  }

  void DeleteFileOrDie(const wstring& path) {
    SetFileAttributesW(path.c_str(), GetFileAttributesW(path.c_str()) &
                                         ~FILE_ATTRIBUTE_READONLY);
    if (!DeleteFileW(path.c_str())) {
      die(L"DeleteFileW failed (%s): %hs", path.c_str(),
          GetLastErrorString().c_str());
    }
  }

  // This function scan the current directory, remove all
  // files/symlinks/directories that are not presented in manifest file. If a
  // symlink already exists and points to the correct target, this function
  // erases its entry from manifest_file_map, so that we won't recreate it.
  void ScanTreeAndPrune(const wstring& path) {
    static const wstring kDot(L".");
    static const wstring kDotDot(L"..");

    WIN32_FIND_DATAW metadata;
    HANDLE handle = ::FindFirstFileW((path + L"\\*").c_str(), &metadata);
    if (handle == INVALID_HANDLE_VALUE) {
      return;  // directory does not exist or is empty
    }

    do {
      if (kDot != metadata.cFileName && kDotDot != metadata.cFileName) {
        wstring subpath = path + L"\\" + metadata.cFileName;
        subpath = AsAbsoluteWindowsPath(subpath.c_str());
        bool is_dir =
            (metadata.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) != 0;
        bool is_symlink =
            (metadata.dwFileAttributes & FILE_ATTRIBUTE_REPARSE_POINT) != 0;
        if (is_symlink) {
          wstring target, werror;
          if (!ReadSymlink(subpath, &target, &werror)) {
            die(L"ReadSymlinkW failed (%s): %hs", subpath.c_str(),
                werror.c_str());
          }

          target = AsAbsoluteWindowsPath(target.c_str());
          ManifestFileMap::iterator expected_target =
              manifest_file_map.find(subpath);

          if (expected_target == manifest_file_map.end() ||
              expected_target->second.empty()
              // Both paths are normalized paths in lower case, we can compare
              // them directly.
              || target != expected_target->second.c_str() ||
              blaze_util::IsDirectoryW(target) != is_dir) {
            if (is_dir) {
              RemoveDirectoryOrDie(subpath);
            } else {
              DeleteFileOrDie(subpath);
            }
          } else {
            manifest_file_map.erase(expected_target);
          }
        } else {
          if (is_dir) {
            ScanTreeAndPrune(subpath);
            // If the directory is empty, then we remove the directory.
            // Otherwise RemoveDirectory will fail with ERROR_DIR_NOT_EMPTY,
            // which we can just ignore.
            // Because if the directory is not empty, it means it contains some
            // symlinks already pointing to the correct targets (we just called
            // ScanTreeAndPrune). Then this directory shouldn't be removed in
            // the first place.
            if (!RemoveDirectoryW(subpath.c_str()) &&
                GetLastError() != ERROR_DIR_NOT_EMPTY) {
              die(L"RemoveDirectoryW failed (%s): %hs", subpath.c_str(),
                  GetLastErrorString().c_str());
            }
          } else {
            DeleteFileOrDie(subpath);
          }
        }
      }
    } while (::FindNextFileW(handle, &metadata));
    ::FindClose(handle);
  }

  void CreateFiles() {
    for (const auto& it : manifest_file_map) {
      // Ensure the parent directory exists
      wstring parent_dir = GetParentDirFromPath(it.first);
      if (!DoesDirectoryPathExist(parent_dir.c_str())) {
        MakeDirectoriesOrDie(parent_dir);
      }

      if (it.second.empty()) {
        // Create an empty file
        HANDLE h = CreateFileW(it.first.c_str(),  // name of the file
                               GENERIC_WRITE,     // open for writing
                               // Must share for reading, otherwise
                               // symlink-following file existence checks (e.g.
                               // java.nio.file.Files.exists()) fail.
                               FILE_SHARE_READ,
                               0,  // use default security descriptor
                               CREATE_ALWAYS,  // overwrite if exists
                               FILE_ATTRIBUTE_NORMAL, 0);
        if (h != INVALID_HANDLE_VALUE) {
          CloseHandle(h);
        } else {
          die(L"CreateFileW failed (%s): %hs", it.first.c_str(),
              GetLastErrorString().c_str());
        }
      } else {
        DWORD create_dir = 0;
        if (blaze_util::IsDirectoryW(it.second.c_str())) {
          create_dir = SYMBOLIC_LINK_FLAG_DIRECTORY;
        }
        if (!CreateSymbolicLinkW(
                it.first.c_str(), it.second.c_str(),
                bazel::windows::symlinkPrivilegeFlag | create_dir)) {
          if (GetLastError() == ERROR_INVALID_PARAMETER) {
            // We are on a version of Windows that does not support this flag.
            // Retry without the flag and return to error handling if necessary.
            if (CreateSymbolicLinkW(it.first.c_str(), it.second.c_str(),
                                    create_dir)) {
              return;
            }
          }
          if (GetLastError() == ERROR_PRIVILEGE_NOT_HELD) {
            die(L"CreateSymbolicLinkW failed:\n%hs\n",
                "Bazel needs to create symlinks to build the runfiles tree.\n"
                "Creating symlinks on Windows requires one of the following:\n"
                "    1. Bazel is run with administrator privileges.\n"
                "    2. The system version is Windows 10 Creators Update "
                "(1703) or "
                "later and developer mode is enabled.",
                GetLastErrorString().c_str());
          } else {
            die(L"CreateSymbolicLinkW failed (%s -> %s): %hs", it.first.c_str(),
                it.second.c_str(), GetLastErrorString().c_str());
          }
        }
      }
    }
  }

  void CopyManifestFile() {
    wstring new_manifest_file = runfiles_output_base_ + L"\\MANIFEST";
    if (!CopyFileW(manifest_path_.c_str(), new_manifest_file.c_str(),
                   /*bFailIfExists=*/FALSE)) {
      die(L"CopyFileW failed (%s -> %s): %hs", manifest_path_.c_str(),
          new_manifest_file.c_str(), GetLastErrorString().c_str());
    }
  }

 private:
  wstring manifest_path_;
  wstring runfiles_output_base_;
  ManifestFileMap manifest_file_map;
};

int wmain(int argc, wchar_t** argv) {
  argc--;
  argv++;
  bool allow_relative = false;
  bool ignore_metadata = false;

  while (argc >= 1) {
    if (wcscmp(argv[0], L"--allow_relative") == 0) {
      allow_relative = true;
      argc--;
      argv++;
    } else if (wcscmp(argv[0], L"--use_metadata") == 0) {
      // If --use_metadata is passed, it means manifest file contains metadata
      // lines, which we should ignore when reading manifest file.
      ignore_metadata = true;
      argc--;
      argv++;
    } else {
      break;
    }
  }

  if (argc != 2) {
    fprintf(stderr,
            "usage: [--allow_relative] [--use_metadata] "
            "<manifest_file> <runfiles_base_dir>\n");
    return 1;
  }

  manifest_filename = argv[0];
  runfiles_base_dir = argv[1];

  wstring manifest_absolute_path = AsAbsoluteWindowsPath(manifest_filename);
  wstring output_base_absolute_path = AsAbsoluteWindowsPath(runfiles_base_dir);

  RunfilesCreator runfiles_creator(manifest_absolute_path,
                                   output_base_absolute_path);
  runfiles_creator.ReadManifest(allow_relative, ignore_metadata);
  runfiles_creator.CreateRunfiles();

  return 0;
}
