// Copyright 2014 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.skyframe;

import com.google.common.annotations.VisibleForTesting;
import com.google.common.base.Function;
import com.google.common.base.Preconditions;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableSet;
import com.google.common.collect.Iterables;
import com.google.devtools.build.lib.util.OS;
import com.google.devtools.build.lib.vfs.ModifiedFileSet;
import com.google.devtools.build.lib.vfs.PathFragment;
import com.google.devtools.build.lib.vfs.Root;
import com.google.devtools.common.options.Option;
import com.google.devtools.common.options.OptionDocumentationCategory;
import com.google.devtools.common.options.OptionEffectTag;
import com.google.devtools.common.options.OptionsBase;
import java.io.IOException;
import java.nio.file.FileSystems;
import java.nio.file.Path;
import java.util.Set;

/**
 * File system watcher for local filesystems. It's able to provide a list of changed files between
 * two consecutive calls. On Linux, uses the standard Java WatchService, which uses 'inotify' and,
 * on OS X, uses {@link MacOSXFsEventsDiffAwareness}, which use FSEvents.
 *
 * <p>
 * This is an abstract class, specialized by {@link MacOSXFsEventsDiffAwareness} and
 * {@link WatchServiceDiffAwareness}.
 */
public abstract class LocalDiffAwareness implements DiffAwareness {
  /**
   * Option to enable / disable local diff awareness.
   */
  public static final class Options extends OptionsBase {
    @Option(
      name = "watchfs",
      defaultValue = "false",
      category = "server startup",
      documentationCategory = OptionDocumentationCategory.UNCATEGORIZED,
      effectTags = {OptionEffectTag.UNKNOWN},
      help =
          "If true, %{product} tries to use the operating system's file watch service for "
              + "local changes instead of scanning every file for a change."
    )
    public boolean watchFS;
  }

  /** Factory for creating {@link LocalDiffAwareness} instances. */
  public static class Factory implements DiffAwareness.Factory {
    private final ImmutableList<String> prefixBlacklist;

    /**
     * Creates a new factory; the file system watcher may not work on all file systems, particularly
     * for network file systems. The prefix blacklist can be used to blacklist known paths that
     * point to network file systems.
     */
    public Factory(ImmutableList<String> prefixBlacklist) {
      this.prefixBlacklist = prefixBlacklist;
    }

    @Override
    public DiffAwareness maybeCreate(Root pathEntry) {
      com.google.devtools.build.lib.vfs.Path resolvedPathEntry;
      try {
        resolvedPathEntry = pathEntry.asPath().resolveSymbolicLinks();
      } catch (IOException e) {
        return null;
      }
      PathFragment resolvedPathEntryFragment = resolvedPathEntry.asFragment();
      // There's no good way to automatically detect network file systems. We rely on a blacklist
      // for now (and maybe add a command-line option in the future?).
      for (String prefix : prefixBlacklist) {
        if (resolvedPathEntryFragment.startsWith(PathFragment.create(prefix))) {
          return null;
        }
      }
      // On OSX uses FsEvents due to https://bugs.openjdk.java.net/browse/JDK-7133447
      if (OS.getCurrent() == OS.DARWIN) {
        return new MacOSXFsEventsDiffAwareness(resolvedPathEntryFragment.toString());
      }

      return new WatchServiceDiffAwareness(resolvedPathEntryFragment.toString());
    }
  }

  /**
   * A view that results in any subsequent getDiff calls returning
   * {@link ModifiedFileSet#EVERYTHING_MODIFIED}. Use this if --watchFs is disabled.
   *
   * <p>The position is set to -2 in order for {@link #areInSequence} below to always return false
   * if this view is passed to it. Any negative number would work; we don't use -1 as the other
   * view may have a position of 0.
   */
  protected static final View EVERYTHING_MODIFIED =
      new SequentialView(/*owner=*/null, /*position=*/-2, ImmutableSet.<Path>of());

  public static boolean areInSequence(SequentialView oldView, SequentialView newView) {
    // Keep this in sync with the EVERYTHING_MODIFIED View above.
    return oldView.owner == newView.owner && (oldView.position + 1) == newView.position;
  }

  private int numGetCurrentViewCalls = 0;

  /** Root directory to watch. This is an absolute path. */
  protected final Path watchRootPath;

  protected LocalDiffAwareness(String watchRoot) {
    this.watchRootPath = FileSystems.getDefault().getPath(watchRoot);
  }

  /**
   * The WatchService is inherently sequential and side-effectful, so we enforce this by only
   * supporting {@link #getDiff} calls that happen to be sequential.
   */
  @VisibleForTesting
  static class SequentialView implements DiffAwareness.View {
    private final LocalDiffAwareness owner;
    private final int position;
    private final Set<Path> modifiedAbsolutePaths;

    public SequentialView(LocalDiffAwareness owner, int position, Set<Path> modifiedAbsolutePaths) {
      this.owner = owner;
      this.position = position;
      this.modifiedAbsolutePaths = modifiedAbsolutePaths;
    }

    @Override
    public String toString() {
      return String.format("SequentialView[owner=%s, position=%d, modifiedAbsolutePaths=%s]", owner,
          position, modifiedAbsolutePaths);
    }
  }

  /**
   * Returns true on any call before first call to {@link #newView}.
   */
  protected boolean isFirstCall() {
    return numGetCurrentViewCalls == 0;
  }

  /**
   * Create a new views using a list of modified absolute paths. This will increase the view
   * counter.
   */
  protected SequentialView newView(Set<Path> modifiedAbsolutePaths) {
    numGetCurrentViewCalls++;
    return new SequentialView(this, numGetCurrentViewCalls, modifiedAbsolutePaths);
  }

  @Override
  public ModifiedFileSet getDiff(View oldView, View newView)
      throws IncompatibleViewException, BrokenDiffAwarenessException {
    SequentialView oldSequentialView;
    SequentialView newSequentialView;
    try {
      oldSequentialView = (SequentialView) oldView;
      newSequentialView = (SequentialView) newView;
    } catch (ClassCastException e) {
      throw new IncompatibleViewException("Given views are not from LocalDiffAwareness");
    }
    if (!areInSequence(oldSequentialView, newSequentialView)) {
      return ModifiedFileSet.EVERYTHING_MODIFIED;
    }
    return ModifiedFileSet.builder()
        .modifyAll(Iterables.transform(newSequentialView.modifiedAbsolutePaths,
            nioAbsolutePathToPathFragment))
            .build();
  }

  @Override
  public String name() {
    return "local";
  }

  /** Converts java.nio.file.Path objects to vfs.PathFragment. */
  private final Function<Path, PathFragment> nioAbsolutePathToPathFragment =
      new Function<Path, PathFragment>() {
        @Override
        public PathFragment apply(Path input) {
          Preconditions.checkArgument(
              input.startsWith(watchRootPath), "%s %s", input, watchRootPath);
          return PathFragment.create(watchRootPath.relativize(input).toString());
        }
      };
}
