// Copyright 2016 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.

package com.google.devtools.build.lib.windows;

import com.google.devtools.build.lib.jni.JniLoader;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.nio.file.AccessDeniedException;

/** File operations on Windows. */
public class WindowsFileOperations {

  // A note about UNC paths and path prefixes on Windows. The prefixes can be:
  // - "\\?\", meaning it's a UNC path that is passed to user mode unicode WinAPI functions
  //   (e.g. CreateFileW) or a return value of theirs (e.g. GetLongPathNameW); this is the
  //   prefix we'll most often see
  // - "\??\", meaning it's Device Object path; it's mostly only used by kernel/driver functions
  //   but we may come across it when resolving junction targets, as the target's path is
  //   specified with this prefix, see usages of DeviceIoControl with FSCTL_GET_REPARSE_POINT
  // - "\\.\", meaning it's a Device Object path again; both "\??\" and "\\.\" are shorthands
  //   for the "\DosDevices\" Object Directory, so "\\.\C:" and "\??\C:" and "\DosDevices\C:"
  //   and "C:\" all mean the same thing, but functions like CreateFileW don't understand the
  //   fully qualified device path, only the shorthand versions; the difference between "\\.\"
  //   is "\??\" is not entirely clear (one is not available while Windows is booting, but
  //   that only concerns device drivers) but we most likely won't come across them anyway
  // Some of this is documented here:
  // - https://msdn.microsoft.com/en-us/library/windows/hardware/ff557762(v=vs.85).aspx
  // - https://msdn.microsoft.com/en-us/library/windows/hardware/ff565384(v=vs.85).aspx
  // - http://stackoverflow.com/questions/23041983
  // - http://stackoverflow.com/questions/14482421

  static {
    JniLoader.loadJni();
  }

  private WindowsFileOperations() {
    // Prevent construction
  }

  /** Result of {@link #readSymlinkOrJunction}. */
  public static class ReadSymlinkOrJunctionResult {

    /** Status code, indicating success or failure. */
    public enum Status {
      OK,
      NOT_A_LINK,
      ERROR
    }

    private String result;
    private Status status;

    public ReadSymlinkOrJunctionResult(Status s, String r) {
      this.status = s;
      this.result = r;
    }

    /** Result string (junction target) or error message (depending on {@link status}). */
    public String getResult() {
      return result;
    }

    public Status getStatus() {
      return status;
    }
  }

  // Keep IS_SYMLINK_OR_JUNCTION_* values in sync with src/main/native/windows/file.cc.
  private static final int IS_SYMLINK_OR_JUNCTION_SUCCESS = 0;
  // IS_SYMLINK_OR_JUNCTION_ERROR = 1;
  private static final int IS_SYMLINK_OR_JUNCTION_DOES_NOT_EXIST = 2;

  // Keep GET_CHANGE_TIME_* values in sync with src/main/native/windows/file.cc.
  private static final int GET_CHANGE_TIME_SUCCESS = 0;
  //  private static final int GET_CHANGE_TIME_ERROR = 1;
  private static final int GET_CHANGE_TIME_DOES_NOT_EXIST = 2;
  private static final int GET_CHANGE_TIME_ACCESS_DENIED = 3;

  // Keep CREATE_JUNCTION_* values in sync with src/main/native/windows/file.h.
  private static final int CREATE_JUNCTION_SUCCESS = 0;
  // CREATE_JUNCTION_ERROR = 1;
  private static final int CREATE_JUNCTION_TARGET_NAME_TOO_LONG = 2;
  private static final int CREATE_JUNCTION_ALREADY_EXISTS_WITH_DIFFERENT_TARGET = 3;
  private static final int CREATE_JUNCTION_ALREADY_EXISTS_BUT_NOT_A_JUNCTION = 4;
  private static final int CREATE_JUNCTION_ACCESS_DENIED = 5;
  private static final int CREATE_JUNCTION_DISAPPEARED = 6;

  // Keep CREATE_SYMLINK_* values in sync with src/main/native/windows/file.h.
  private static final int CREATE_SYMLINK_SUCCESS = 0;
  // CREATE_SYMLINK_ERROR = 1;
  private static final int CREATE_SYMLINK_TARGET_IS_DIRECTORY = 2;

  // Keep DELETE_PATH_* values in sync with src/main/native/windows/file.h.
  private static final int DELETE_PATH_SUCCESS = 0;
  // DELETE_PATH_ERROR = 1;
  private static final int DELETE_PATH_DOES_NOT_EXIST = 2;
  private static final int DELETE_PATH_DIRECTORY_NOT_EMPTY = 3;
  private static final int DELETE_PATH_ACCESS_DENIED = 4;

  // Keep READ_SYMLINK_OR_JUNCTION_* values in sync with src/main/native/windows/file.h.
  private static final int READ_SYMLINK_OR_JUNCTION_SUCCESS = 0;
  // READ_SYMLINK_OR_JUNCTION_ERROR = 1;
  private static final int READ_SYMLINK_OR_JUNCTION_ACCESS_DENIED = 2;
  private static final int READ_SYMLINK_OR_JUNCTION_DOES_NOT_EXIST = 3;
  private static final int READ_SYMLINK_OR_JUNCTION_NOT_A_LINK = 4;
  private static final int READ_SYMLINK_OR_JUNCTION_UNKNOWN_LINK_TYPE = 5;

  private static native int nativeIsSymlinkOrJunction(
      String path, boolean[] result, String[] error);

  private static native int nativeGetChangeTime(
      String path, boolean followReparsePoints, long[] result, String[] error);

  private static native boolean nativeGetLongPath(String path, String[] result, String[] error);

  private static native int nativeCreateJunction(String name, String target, String[] error);

  private static native int nativeCreateSymlink(String name, String target, String[] error);

  private static native int nativeReadSymlinkOrJunction(
      String name, String[] result, String[] error);

  private static native int nativeDeletePath(String path, String[] error);

  /** Determines whether `path` is a junction point or directory symlink. */
  public static boolean isSymlinkOrJunction(String path) throws IOException {
    boolean[] result = new boolean[] {false};
    String[] error = new String[] {null};
    switch (nativeIsSymlinkOrJunction(asLongPath(path), result, error)) {
      case IS_SYMLINK_OR_JUNCTION_SUCCESS:
        return result[0];
      case IS_SYMLINK_OR_JUNCTION_DOES_NOT_EXIST:
        error[0] = "path does not exist";
        break;
      default:
        // This is IS_SYMLINK_OR_JUNCTION_ERROR (1). The JNI code puts a custom message in
        // 'error[0]'.
        break;
    }
    throw new IOException(String.format("Cannot tell if '%s' is link: %s", path, error[0]));
  }

  /** Returns the time at which the file was last changed, including metadata changes. */
  public static long getLastChangeTime(String path, boolean followReparsePoints)
      throws IOException {
    long[] result = new long[] {0};
    String[] error = new String[] {null};
    switch (nativeGetChangeTime(asLongPath(path), followReparsePoints, result, error)) {
      case GET_CHANGE_TIME_SUCCESS:
        return result[0];
      case GET_CHANGE_TIME_DOES_NOT_EXIST:
        throw new FileNotFoundException(path);
      case GET_CHANGE_TIME_ACCESS_DENIED:
        throw new AccessDeniedException(path);
      default:
        // This is GET_CHANGE_TIME_ERROR (1). The JNI code puts a custom message in 'error[0]'.
        break;
    }
    throw new IOException(String.format("Cannot get last change time of '%s': %s", path, error[0]));
  }

  /**
   * Returns the long path associated with the input `path`.
   *
   * <p>This method resolves all 8dot3 style components of the path and returns the long format. For
   * example, if the input is "C:/progra~1/micros~1" the result may be "C:\Program Files\Microsoft
   * Visual Studio 14.0". The returned path is Windows-style in that it uses backslashes, even if
   * the input uses forward slashes.
   *
   * <p>May return an UNC path if `path` or its resolution is sufficiently long.
   *
   * @throws IOException if the `path` is not found or some other I/O error occurs
   */
  public static String getLongPath(String path) throws IOException {
    String[] result = new String[] {null};
    String[] error = new String[] {null};
    if (nativeGetLongPath(asLongPath(path), result, error)) {
      return removeUncPrefixAndUseSlashes(result[0]);
    } else {
      throw new IOException(error[0]);
    }
  }

  /** Returns a Windows-style path suitable to pass to unicode WinAPI functions. */
  static String asLongPath(String path) {
    return !path.startsWith("\\\\?\\")
        ? ("\\\\?\\" + path.replace('/', '\\'))
        : path.replace('/', '\\');
  }

  private static String removeUncPrefixAndUseSlashes(String p) {
    if (p.length() >= 4
        && p.charAt(0) == '\\'
        && (p.charAt(1) == '\\' || p.charAt(1) == '?')
        && p.charAt(2) == '?'
        && p.charAt(3) == '\\') {
      p = p.substring(4);
    }
    return p.replace('\\', '/');
  }

  /**
   * Creates a junction at `name`, pointing to `target`.
   *
   * <p>Both `name` and `target` may be Unix-style Windows paths (i.e. use forward slashes), and
   * they don't need to have a UNC prefix, not even if they are longer than `MAX_PATH`. The
   * underlying logic will take care of adding the prefixes if necessary.
   *
   * @throws IOException if some error occurs
   */
  public static void createJunction(String name, String target) throws IOException {
    String[] error = new String[] {null};
    switch (nativeCreateJunction(asLongPath(name), asLongPath(target), error)) {
      case CREATE_JUNCTION_SUCCESS:
        return;
      case CREATE_JUNCTION_TARGET_NAME_TOO_LONG:
        error[0] = "target name is too long";
        break;
      case CREATE_JUNCTION_ALREADY_EXISTS_WITH_DIFFERENT_TARGET:
        error[0] = "junction already exists with different target";
        break;
      case CREATE_JUNCTION_ALREADY_EXISTS_BUT_NOT_A_JUNCTION:
        error[0] = "a file or directory already exists at the junction's path";
        break;
      case CREATE_JUNCTION_ACCESS_DENIED:
        error[0] = "access is denied";
        break;
      case CREATE_JUNCTION_DISAPPEARED:
        error[0] = "the junction's path got modified unexpectedly";
        break;
      default:
        // This is CREATE_JUNCTION_ERROR (1). The JNI code puts a custom message in 'error[0]'.
        break;
    }
    throw new IOException(
        String.format("Cannot create junction (name=%s, target=%s): %s", name, target, error[0]));
  }

  public static void createSymlink(String name, String target) throws IOException {
    String[] error = new String[] {null};
    switch (nativeCreateSymlink(asLongPath(name), asLongPath(target), error)) {
      case CREATE_SYMLINK_SUCCESS:
        return;
      case CREATE_SYMLINK_TARGET_IS_DIRECTORY:
        error[0] = "symlink target is a directory, use a junction";
        break;
      default:
        // this is CREATE_SYMLINK_ERROR (1). The JNI code puts a custom message in 'error[0]'.
        break;
    }
    throw new IOException(
        String.format("Cannot create symlink (name=%s, target=%s): %s", name, target, error[0]));
  }

  public static ReadSymlinkOrJunctionResult readSymlinkOrJunction(String name) {
    String[] target = new String[] {null};
    String[] error = new String[] {null};
    switch (nativeReadSymlinkOrJunction(asLongPath(name), target, error)) {
      case READ_SYMLINK_OR_JUNCTION_SUCCESS:
        return new ReadSymlinkOrJunctionResult(
            ReadSymlinkOrJunctionResult.Status.OK, removeUncPrefixAndUseSlashes(target[0]));
      case READ_SYMLINK_OR_JUNCTION_ACCESS_DENIED:
        error[0] = "access is denied";
        break;
      case READ_SYMLINK_OR_JUNCTION_DOES_NOT_EXIST:
        error[0] = "path does not exist";
        break;
      case READ_SYMLINK_OR_JUNCTION_NOT_A_LINK:
        return new ReadSymlinkOrJunctionResult(
            ReadSymlinkOrJunctionResult.Status.NOT_A_LINK, "path is not a link");
      case READ_SYMLINK_OR_JUNCTION_UNKNOWN_LINK_TYPE:
        error[0] = "unknown link type";
        break;
      default:
        // This is READ_SYMLINK_OR_JUNCTION_ERROR (1). The JNI code puts a custom message in
        // 'error[0]'.
        break;
    }
    return new ReadSymlinkOrJunctionResult(
        ReadSymlinkOrJunctionResult.Status.ERROR,
        String.format("Cannot read link (name=%s): %s", name, error[0]));
  }

  public static boolean deletePath(String path) throws IOException {
    String[] error = new String[] {null};
    int result = nativeDeletePath(asLongPath(path), error);
    switch (result) {
      case DELETE_PATH_SUCCESS:
        return true;
      case DELETE_PATH_DOES_NOT_EXIST:
        return false;
      case DELETE_PATH_DIRECTORY_NOT_EMPTY:
        throw new java.nio.file.DirectoryNotEmptyException(path);
      case DELETE_PATH_ACCESS_DENIED:
        throw new java.nio.file.AccessDeniedException(path);
      default:
        // This is DELETE_PATH_ERROR (1). The JNI code puts a custom message in 'error[0]'.
        throw new IOException(String.format("Cannot delete path '%s': %s", path, error[0]));
    }
  }
}
