// 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.common.annotations.VisibleForTesting;
import com.google.common.base.Function;
import com.google.common.base.Preconditions;
import com.google.common.base.Predicate;
import com.google.devtools.build.lib.concurrent.ThreadSafety.ThreadSafe;
import com.google.devtools.build.lib.vfs.FileStatus;
import com.google.devtools.build.lib.vfs.FileSystem;
import com.google.devtools.build.lib.vfs.JavaIoFileSystem;
import com.google.devtools.build.lib.vfs.Path;
import com.google.devtools.build.lib.vfs.Path.PathFactory;
import com.google.devtools.build.lib.vfs.PathFragment;
import com.google.devtools.build.lib.windows.jni.WindowsFileOperations;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.LinkOption;
import java.nio.file.attribute.DosFileAttributes;
import java.util.Arrays;
import java.util.concurrent.atomic.AtomicReference;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import javax.annotation.Nullable;

/** File system implementation for Windows. */
@ThreadSafe
public class WindowsFileSystem extends JavaIoFileSystem {

  // Properties of 8dot3 (DOS-style) short file names:
  // - they are at most 11 characters long
  // - they have a prefix (before "~") that is {1..6} characters long, may contain numbers, letters,
  //   "_", even "~", and maybe even more
  // - they have a "~" after the prefix
  // - have {1..6} numbers after "~" (according to [1] this is only one digit, but MSDN doesn't
  //   clarify this), the combined length up till this point is at most 8
  // - they have an optional "." afterwards, and another {0..3} more characters
  // - just because a path looks like a short name it isn't necessarily one; the user may create
  //   such names and they'd resolve to themselves
  // [1] https://en.wikipedia.org/wiki/8.3_filename#VFAT_and_Computer-generated_8.3_filenames
  //     bullet point (3) (on 2016-12-05)
  @VisibleForTesting
  static final Predicate<String> SHORT_NAME_MATCHER =
      new Predicate<String>() {
        private final Pattern pattern = Pattern.compile("^(.{1,6})~([0-9]{1,6})(\\..{0,3}){0,1}");

        @Override
        public boolean apply(@Nullable String input) {
          Matcher m = pattern.matcher(input);
          return input.length() <= 12
              && m.matches()
              && m.groupCount() >= 2
              && (m.group(1).length() + m.group(2).length()) < 8; // the "~" makes it at most 8
        }
      };

  /** Resolves DOS-style, shortened path names, returning the last segment's long form. */
  private static final Function<String, String> WINDOWS_SHORT_PATH_RESOLVER =
      path -> {
        try {
          // Since Path objects are created hierarchically, we know for sure that every segment of
          // the path, except the last one, is already canonicalized, so we can return just that.
          // Plus the returned value is passed to Path.getChild so we must not return a full
          // path here.
          return PathFragment.create(WindowsFileOperations.getLongPath(path)).getBaseName();
        } catch (IOException e) {
          return null;
        }
      };

  @VisibleForTesting
  private enum WindowsPathFactory implements PathFactory {
    INSTANCE {
      @Override
      public Path createRootPath(FileSystem filesystem) {
        return new WindowsPath(filesystem, PathFragment.ROOT_DIR, null);
      }

      @Override
      public Path createChildPath(Path parent, String childName) {
        Preconditions.checkState(parent instanceof WindowsPath);
        return new WindowsPath(parent.getFileSystem(), childName, (WindowsPath) parent);
      }

      @Override
      public Path getCachedChildPathInternal(Path path, String childName) {
        return WindowsPathFactory.getCachedChildPathInternalImpl(
            path, childName, WINDOWS_SHORT_PATH_RESOLVER);
      }
    };

    private static Path getCachedChildPathInternalImpl(
        Path parent, String child, Function<String, String> resolver) {
      if (parent != null && parent.isRootDirectory()) {
        // This is a top-level directory. It's either a drive name ("C:" or "c") or some other
        // Unix path (e.g. "/usr").
        //
        // We need to translate it to an absolute Windows path. The correct way would be looking
        // up /etc/mtab to see if any mount point matches the prefix of the path, and change the
        // prefix to the mounted path. Looking up /etc/mtab each time we create a path however
        // would be too expensive so we use a heuristic instead.
        //
        // If the name looks like a volume name ("C:" or "c") then we treat it as such, otherwise
        // we make it relative to UNIX_ROOT, thus "/usr" becomes "C:/tools/msys64/usr".
        //
        // This heuristic ignores other mount points as well as procfs.

        // TODO(laszlocsomor): use GetLogicalDrives to retrieve the list of drives and only apply
        // this heuristic for the valid drives. It's possible that the user has a directory "/a"
        // but no "A:\" drive, so in that case we should prepend the MSYS root.

        if (WindowsPath.isWindowsVolumeName(child)) {
          child = WindowsPath.getDriveLetter((WindowsPath) parent, child) + ":";
        } else {
          if (UNIX_ROOT.get() == null) {
            String jvmFlag = "bazel.windows_unix_root";
            PathFragment value = determineUnixRoot(jvmFlag);
            if (value == null) {
              throw new IllegalStateException(
                  String.format(
                      "\"%1$s\" JVM flag is not set. Use the --host_jvm_args flag or export the "
                          + "BAZEL_SH environment variable. For example "
                          + "\"--host_jvm_args=-D%1$s=c:/tools/msys64\" or "
                          + "\"set BAZEL_SH=c:/tools/msys64/usr/bin/bash.exe\". "
                          + "parent=(%2$s) name=(%3$s)",
                      jvmFlag, parent, child));
            }
            UNIX_ROOT.set(value);
          }
          parent = parent.getRelative(UNIX_ROOT.get());
        }
      }

      String resolvedChild = child;
      if (parent != null && !parent.isRootDirectory() && SHORT_NAME_MATCHER.apply(child)) {
        String pathString = parent.getPathString();
        if (!pathString.endsWith("/")) {
          pathString += "/";
        }
        pathString += child;
        resolvedChild = resolver.apply(pathString);
      }
      return Path.getCachedChildPathInternal(
          parent,
          // If resolution succeeded, or we didn't attempt to resolve, then `resolvedChild` has the
          // child name. If it's null, then resolution failed; use the unresolved child name in that
          // case.
          resolvedChild != null ? resolvedChild : child,
          // If resolution failed, likely because the path doesn't exist, then do not cache the
          // child. If we did, then in case the path later came into existence, we'd have a stale
          // cache entry.
          /* cacheable */ resolvedChild != null);
    }

    /**
     * Creates a {@link PathFactory} with a mock shortname resolver.
     *
     * <p>The factory works exactly like the actual one ({@link WindowsPathFactory#INSTANCE}) except
     * it's using the mock resolver.
     */
    public static PathFactory createForTesting(final Function<String, String> mockResolver) {
      return new PathFactory() {
        @Override
        public Path createRootPath(FileSystem filesystem) {
          return INSTANCE.createRootPath(filesystem);
        }

        @Override
        public Path createChildPath(Path parent, String childName) {
          return INSTANCE.createChildPath(parent, childName);
        }

        @Override
        public Path getCachedChildPathInternal(Path path, String childName) {
          return WindowsPathFactory.getCachedChildPathInternalImpl(path, childName, mockResolver);
        }
      };
    }
  }

  /** A windows-specific subclass of Path. */
  @VisibleForTesting
  protected static final class WindowsPath extends Path {

    // The drive letter is '\0' if and only if this Path is the filesystem root "/".
    private char driveLetter;

    private WindowsPath(FileSystem fileSystem) {
      super(fileSystem);
      this.driveLetter = '\0';
    }

    private WindowsPath(FileSystem fileSystem, String name, WindowsPath parent) {
      super(fileSystem, name, parent);
      this.driveLetter = getDriveLetter(parent, name);
    }

    @Override
    protected void buildPathString(StringBuilder result) {
      if (isRootDirectory()) {
        result.append(PathFragment.ROOT_DIR);
      } else {
        if (isTopLevelDirectory()) {
          result.append(driveLetter).append(':').append(PathFragment.SEPARATOR_CHAR);
        } else {
          WindowsPath parent = (WindowsPath) getParentDirectory();
          parent.buildPathString(result);
          if (!parent.isTopLevelDirectory()) {
            result.append(PathFragment.SEPARATOR_CHAR);
          }
          result.append(getBaseName());
        }
      }
    }

    @Override
    public void reinitializeAfterDeserialization() {
      Preconditions.checkState(
          getParentDirectory().isRootDirectory() || getParentDirectory() instanceof WindowsPath);
      this.driveLetter =
          (getParentDirectory() != null) ? ((WindowsPath) getParentDirectory()).driveLetter : '\0';
    }

    @Override
    public boolean isMaybeRelativeTo(Path ancestorCandidate) {
      Preconditions.checkState(ancestorCandidate instanceof WindowsPath);
      return ancestorCandidate.isRootDirectory()
          || driveLetter == ((WindowsPath) ancestorCandidate).driveLetter;
    }

    @Override
    public boolean isTopLevelDirectory() {
      return isRootDirectory() || getParentDirectory().isRootDirectory();
    }

    @Override
    public PathFragment asFragment() {
      String[] segments = getSegments();
      if (segments.length > 0) {
        // Strip off the first segment that contains the volume name.
        segments = Arrays.copyOfRange(segments, 1, segments.length);
      }

      return PathFragment.create(driveLetter, true, segments);
    }

    @Override
    protected Path getRootForRelativePathComputation(PathFragment relative) {
      Path result = this;
      if (relative.isAbsolute()) {
        result = getFileSystem().getRootDirectory();
        if (!relative.windowsVolume().isEmpty()) {
          result = result.getRelative(relative.windowsVolume());
        }
      }
      return result;
    }

    private static boolean isWindowsVolumeName(String name) {
      return (name.length() == 1 || (name.length() == 2 && name.charAt(1) == ':'))
          && Character.isLetter(name.charAt(0));
    }

    private static char getDriveLetter(WindowsPath parent, String name) {
      if (parent == null) {
        return '\0';
      } else {
        if (parent.isRootDirectory()) {
          Preconditions.checkState(
              isWindowsVolumeName(name),
              "top-level directory on Windows must be a drive (name = '%s')",
              name);
          return Character.toUpperCase(name.charAt(0));
        } else {
          return parent.driveLetter;
        }
      }
    }

    @VisibleForTesting
    @Override
    protected synchronized void applyToChildren(Predicate<Path> function) {
      super.applyToChildren(function);
    }
  }

  @VisibleForTesting
  static PathFactory getPathFactoryForTesting(Function<String, String> mockResolver) {
    return WindowsPathFactory.createForTesting(mockResolver);
  }

  private static final AtomicReference<PathFragment> UNIX_ROOT = new AtomicReference<>(null);

  public static final LinkOption[] NO_OPTIONS = new LinkOption[0];
  public static final LinkOption[] NO_FOLLOW = new LinkOption[] {LinkOption.NOFOLLOW_LINKS};

  @Override
  protected PathFactory getPathFactory() {
    return WindowsPathFactory.INSTANCE;
  }

  @Override
  public String getFileSystemType(Path path) {
    // TODO(laszlocsomor): implement this properly, i.e. actually query this information from
    // somewhere (java.nio.Filesystem? System.getProperty? implement JNI method and use WinAPI?).
    return "ntfs";
  }

  @Override
  protected void createSymbolicLink(Path linkPath, PathFragment targetFragment) throws IOException {
    Path targetPath =
        targetFragment.isAbsolute()
            ? getPath(targetFragment)
            : linkPath.getParentDirectory().getRelative(targetFragment);
    try {
      java.nio.file.Path link = getIoFile(linkPath).toPath();
      java.nio.file.Path target = getIoFile(targetPath).toPath();
      // Still Create a dangling junction if the target doesn't exist.
      if (!target.toFile().exists() || target.toFile().isDirectory()) {
        WindowsFileOperations.createJunction(link.toString(), target.toString());
      } else {
        Files.copy(target, link);
      }
    } catch (java.nio.file.FileAlreadyExistsException e) {
      throw new IOException(linkPath + ERR_FILE_EXISTS);
    } catch (java.nio.file.AccessDeniedException e) {
      throw new IOException(linkPath + ERR_PERMISSION_DENIED);
    } catch (java.nio.file.NoSuchFileException e) {
      throw new FileNotFoundException(linkPath + ERR_NO_SUCH_FILE_OR_DIR);
    }
  }

  @Override
  public boolean supportsSymbolicLinksNatively(Path path) {
    return false;
  }

  @Override
  public boolean isFilePathCaseSensitive() {
    return false;
  }

  @Override
  protected boolean fileIsSymbolicLink(File file) {
    try {
      if (isJunction(file)) {
        return true;
      }
    } catch (IOException e) {
      // Did not work, try in another way
    }
    return super.fileIsSymbolicLink(file);
  }

  public static LinkOption[] symlinkOpts(boolean followSymlinks) {
    return followSymlinks ? NO_OPTIONS : NO_FOLLOW;
  }

  @Override
  protected FileStatus stat(Path path, boolean followSymlinks) throws IOException {
    File file = getIoFile(path);
    final DosFileAttributes attributes;
    try {
      attributes = getAttribs(file, followSymlinks);
    } catch (IOException e) {
      throw new FileNotFoundException(path + ERR_NO_SUCH_FILE_OR_DIR);
    }

    final boolean isSymbolicLink = !followSymlinks && fileIsSymbolicLink(file);
    FileStatus status =
        new FileStatus() {
          @Override
          public boolean isFile() {
            return attributes.isRegularFile() || (isSpecialFile() && !isDirectory());
          }

          @Override
          public boolean isSpecialFile() {
            return attributes.isOther();
          }

          @Override
          public boolean isDirectory() {
            return attributes.isDirectory();
          }

          @Override
          public boolean isSymbolicLink() {
            return isSymbolicLink;
          }

          @Override
          public long getSize() throws IOException {
            return attributes.size();
          }

          @Override
          public long getLastModifiedTime() throws IOException {
            return attributes.lastModifiedTime().toMillis();
          }

          @Override
          public long getLastChangeTime() {
            // This is the best we can do with Java NIO...
            return attributes.lastModifiedTime().toMillis();
          }

          @Override
          public long getNodeId() {
            // TODO(bazel-team): Consider making use of attributes.fileKey().
            return -1;
          }
        };

    return status;
  }

  @Override
  protected boolean isDirectory(Path path, boolean followSymlinks) {
    if (!followSymlinks) {
      try {
        if (isJunction(getIoFile(path))) {
          return false;
        }
      } catch (IOException e) {
        return false;
      }
    }
    return super.isDirectory(path, followSymlinks);
  }

  /**
   * Returns true if the path refers to a directory junction, directory symlink, or regular symlink.
   *
   * <p>Directory junctions are symbolic links created with "mklink /J" where the target is a
   * directory or another directory junction. Directory junctions can be created without any user
   * privileges.
   *
   * <p>Directory symlinks are symbolic links created with "mklink /D" where the target is a
   * directory or another directory symlink. Note that directory symlinks can only be created by
   * Administrators.
   *
   * <p>Normal symlinks are symbolic links created with "mklink". Normal symlinks should not point
   * at directories, because even though "mklink" can create the link, it will not be a functional
   * one (the linked directory's contents cannot be listed). Only Administrators may create regular
   * symlinks.
   *
   * <p>This method returns true for all three types as long as their target is a directory (even if
   * they are dangling), though only directory junctions and directory symlinks are useful.
   */
  @VisibleForTesting
  static boolean isJunction(File file) throws IOException {
    return WindowsFileOperations.isJunction(file.getPath());
  }

  private static DosFileAttributes getAttribs(File file, boolean followSymlinks)
      throws IOException {
    return Files.readAttributes(
        file.toPath(), DosFileAttributes.class, symlinkOpts(followSymlinks));
  }

  private static PathFragment determineUnixRoot(String jvmArgName) {
    // Get the path from a JVM flag, if specified.
    String path = System.getProperty(jvmArgName);
    if (path == null) {
      return null;
    }

    path = path.trim();
    if (path.isEmpty()) {
      return null;
    }

    PathFragment result = PathFragment.create(path);
    if (result.getDriveLetter() == '\0' || !result.isAbsolute()) {
      return null;
    }
    return result;
  }
}
