// 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.base.Preconditions;
import com.google.common.base.Throwables;
import com.google.common.collect.ImmutableMap;
import com.google.common.collect.ImmutableSet;
import com.google.devtools.build.lib.bugreport.BugReport;
import com.google.devtools.build.lib.cmdline.Label;
import com.google.devtools.build.lib.cmdline.QueryExceptionMarkerInterface;
import com.google.devtools.build.lib.cmdline.ResolvedTargets;
import com.google.devtools.build.lib.cmdline.SignedTargetPattern;
import com.google.devtools.build.lib.cmdline.TargetParsingException;
import com.google.devtools.build.lib.cmdline.TargetPattern;
import com.google.devtools.build.lib.events.Event;
import com.google.devtools.build.lib.events.ExtendedEventHandler;
import com.google.devtools.build.lib.io.InconsistentFilesystemException;
import com.google.devtools.build.lib.io.ProcessPackageDirectoryException;
import com.google.devtools.build.lib.packages.NoSuchPackageException;
import com.google.devtools.build.lib.packages.Package;
import com.google.devtools.build.lib.packages.Target;
import com.google.devtools.build.lib.pkgcache.FilteringPolicies;
import com.google.devtools.build.lib.pkgcache.ParsingFailedEvent;
import com.google.devtools.build.lib.pkgcache.RecursivePackageProvider.PackageBackedRecursivePackageProvider;
import com.google.devtools.build.lib.pkgcache.TargetPatternPreloader;
import com.google.devtools.build.lib.server.FailureDetails.TargetPatterns;
import com.google.devtools.build.lib.skyframe.TargetPatternValue.TargetPatternKey;
import com.google.devtools.build.lib.util.DetailedExitCode;
import com.google.devtools.build.lib.vfs.PathFragment;
import com.google.devtools.build.skyframe.ErrorInfo;
import com.google.devtools.build.skyframe.EvaluationResult;
import com.google.devtools.build.skyframe.SkyKey;
import com.google.devtools.build.skyframe.SkyValue;
import com.google.devtools.build.skyframe.WalkableGraph;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import java.util.Map;
import java.util.concurrent.atomic.AtomicReference;
import javax.annotation.Nullable;

/** Skyframe-based target pattern parsing. */
public final class SkyframeTargetPatternEvaluator implements TargetPatternPreloader {
  private final SkyframeExecutor skyframeExecutor;

  public SkyframeTargetPatternEvaluator(SkyframeExecutor skyframeExecutor) {
    this.skyframeExecutor = skyframeExecutor;
  }

  @Override
  public Map<String, Collection<Target>> preloadTargetPatterns(
      ExtendedEventHandler eventHandler,
      PathFragment relativeWorkingDirectory,
      Collection<String> patterns,
      boolean keepGoing)
      throws TargetParsingException, InterruptedException {
    ImmutableMap.Builder<String, Collection<Target>> resultBuilder = ImmutableMap.builder();
    List<PatternLookup> patternLookups = new ArrayList<>();
    List<SkyKey> allKeys = new ArrayList<>();
    for (String pattern : patterns) {
      Preconditions.checkArgument(!pattern.startsWith("-"));
      PatternLookup patternLookup =
          createPatternLookup(relativeWorkingDirectory, eventHandler, pattern, keepGoing);
      if (patternLookup == null) {
        resultBuilder.put(pattern, ImmutableSet.of());
      } else {
        patternLookups.add(patternLookup);
        allKeys.add(patternLookup.skyKey);
      }
    }

    EvaluationResult<SkyValue> result =
        skyframeExecutor.targetPatterns(
            allKeys, SkyframeExecutor.DEFAULT_THREAD_COUNT, keepGoing, eventHandler);
    Exception catastrophe = result.getCatastrophe();
    Throwables.propagateIfPossible(catastrophe, TargetParsingException.class);
    if (catastrophe != null) {
      throw wrapException(catastrophe, null, result);
    }
    WalkableGraph walkableGraph = Preconditions.checkNotNull(result.getWalkableGraph(), result);
    for (PatternLookup patternLookup : patternLookups) {
      SkyKey key = patternLookup.skyKey;
      SkyValue resultValue = result.get(key);
      if (resultValue != null) {
        try {
          Collection<Target> resolvedTargets =
              patternLookup.process(eventHandler, resultValue, walkableGraph, keepGoing);
          resultBuilder.put(patternLookup.pattern, resolvedTargets);
        } catch (TargetParsingException e) {
          if (!keepGoing) {
            throw e;
          }
          eventHandler.handle(createPatternParsingError(e, patternLookup.pattern));
          eventHandler.post(PatternExpandingError.skipped(patternLookup.pattern, e.getMessage()));
          resultBuilder.put(patternLookup.pattern, ImmutableSet.of());
        }
      } else {
        String rawPattern = patternLookup.pattern;
        ErrorInfo error = result.errorMap().get(key);
        if (error == null) {
          if (keepGoing) {
            BugReport.sendBugReport(
                new IllegalStateException(
                    "No error for a non-catastrophic keep-going build: " + key + ", " + result));
          }
          continue;
        }
        String errorMessage;
        TargetParsingException targetParsingException;
        if (error.getException() != null) {
          // This exception could be a TargetParsingException for a target pattern, a
          // NoSuchPackageException for a label (or package wildcard), or potentially a lower-level
          // exception if there is a bug in error handling.
          Exception exception = error.getException();
          errorMessage = exception.getMessage();
          if (exception instanceof TargetParsingException) {
            targetParsingException = (TargetParsingException) exception;
          } else {
            targetParsingException = wrapException(exception, key, key);
          }
        } else {
          Preconditions.checkState(
              !error.getCycleInfo().isEmpty(),
              "No exception or cycle %s %s %s",
              key,
              error,
              result);
          errorMessage = "cycles detected during target parsing";
          targetParsingException =
              new TargetParsingException(errorMessage, TargetPatterns.Code.CYCLE);
          skyframeExecutor
              .getCyclesReporter()
              .reportCycles(error.getCycleInfo(), key, eventHandler);
        }
        if (keepGoing) {
          eventHandler.handle(createPatternParsingError(targetParsingException, rawPattern));
          eventHandler.post(PatternExpandingError.skipped(rawPattern, errorMessage));
        } else {
          eventHandler.post(PatternExpandingError.failed(patternLookup.pattern, errorMessage));
          throw targetParsingException;
        }
        resultBuilder.put(patternLookup.pattern, ImmutableSet.of());
      }
    }
    return resultBuilder.buildOrThrow();
  }

  private static TargetParsingException wrapException(
      Exception exception, @Nullable SkyKey key, Object debugging) {
    if ((key == null || (key instanceof PackageValue.Key))
        && (exception instanceof NoSuchPackageException)) {
      // A "simple" target pattern (like "//pkg:t") doesn't have a TargetPatternKey, just a Package
      // key, so it results in NoSuchPackageException that we transform here.
      return new TargetParsingException(
          exception.getMessage(),
          exception,
          ((NoSuchPackageException) exception).getDetailedExitCode());
    }
    BugReport.sendBugReport(
        new IllegalStateException("Unexpected exception: " + debugging, exception));
    String message = "Target parsing failed due to unexpected exception: " + exception.getMessage();
    DetailedExitCode detailedExitCode = DetailedException.getDetailedExitCode(exception);
    return detailedExitCode != null
        ? new TargetParsingException(message, exception, detailedExitCode)
        : new TargetParsingException(message, exception, TargetPatterns.Code.CANNOT_PRELOAD_TARGET);
  }

  private PatternLookup createPatternLookup(
      PathFragment offset,
      ExtendedEventHandler eventHandler,
      String targetPattern,
      boolean keepGoing)
      throws TargetParsingException {
    try {
      TargetPatternKey key =
          TargetPatternValue.key(
              SignedTargetPattern.parse(targetPattern, TargetPattern.mainRepoParser(offset)),
              FilteringPolicies.NO_FILTER);
      return isSimple(key.getParsedPattern())
          ? new SimpleLookup(targetPattern, key)
          : new NormalLookup(targetPattern, key);
    } catch (TargetParsingException e) {
      // We report a parsing failed exception to the event bus here in case the pattern did not
      // successfully parse (which happens before the SkyKey is created). Otherwise the
      // TargetPatternFunction posts the event.
      eventHandler.post(new ParsingFailedEvent(targetPattern, e.getMessage()));
      if (!keepGoing) {
        throw e;
      }
      eventHandler.handle(createPatternParsingError(e, targetPattern));
      return null;
    }
  }

  /** Returns true for patterns that can be resolved from a single PackageValue. */
  private static boolean isSimple(TargetPattern targetPattern) {
    switch (targetPattern.getType()) {
      case SINGLE_TARGET:
      case TARGETS_IN_PACKAGE:
        return true;
      case PATH_AS_TARGET:
      case TARGETS_BELOW_DIRECTORY:
        // Both of these require multiple package lookups. PATH_AS_TARGET needs to find the
        // enclosing package, and TARGETS_BELOW_DIRECTORY recursively looks for all packages under a
        // specified directory.
        return false;
    }
    throw new AssertionError();
  }

  private static Event createPatternParsingError(TargetParsingException e, String pattern) {
    return Event.error("Skipping '" + pattern + "': " + e.getMessage())
        .withProperty(DetailedExitCode.class, e.getDetailedExitCode());
  }

  private abstract static class PatternLookup {
    protected final String pattern;
    @Nullable private final SkyKey skyKey;

    private PatternLookup(String pattern, SkyKey skyKey) {
      this.pattern = pattern;
      this.skyKey = skyKey;
    }

    public abstract Collection<Target> process(
        ExtendedEventHandler eventHandler,
        SkyValue value,
        WalkableGraph walkableGraph,
        boolean keepGoing)
        throws InterruptedException, TargetParsingException;
  }

  private static class NormalLookup extends PatternLookup {
    private final TargetPatternsResultBuilder resultBuilder;

    private NormalLookup(String targetPattern, TargetPatternKey key) {
      super(targetPattern, key);
      this.resultBuilder = new TargetPatternsResultBuilder();
    }

    @Override
    public Collection<Target> process(
        ExtendedEventHandler eventHandler,
        SkyValue value,
        WalkableGraph walkableGraph,
        boolean keepGoing)
        throws InterruptedException, TargetParsingException {
      TargetPatternValue resultValue = (TargetPatternValue) value;
      ResolvedTargets<Label> results = resultValue.getTargets();
      resultBuilder.addLabelsOfPositivePattern(results);
      return resultBuilder.build(walkableGraph);
    }
  }

  private static class SimpleLookup extends PatternLookup {
    private final TargetPattern targetPattern;

    private SimpleLookup(String pattern, TargetPatternKey key) {
      this(
          pattern, PackageValue.key(key.getParsedPattern().getDirectory()), key.getParsedPattern());
    }

    private SimpleLookup(String pattern, PackageValue.Key key, TargetPattern targetPattern) {
      super(pattern, key);
      this.targetPattern = targetPattern;
    }

    @Override
    public Collection<Target> process(
        ExtendedEventHandler eventHandler,
        SkyValue value,
        WalkableGraph walkableGraph,
        boolean keepGoing)
        throws InterruptedException, TargetParsingException {
      Package pkg = ((PackageValue) value).getPackage();
      RecursivePackageProviderBackedTargetPatternResolver resolver =
          new RecursivePackageProviderBackedTargetPatternResolver(
              new PackageBackedRecursivePackageProvider(
                  ImmutableMap.of(pkg.getPackageIdentifier(), pkg)),
              eventHandler,
              FilteringPolicies.NO_FILTER,
              /* packageSemaphore= */ null,
              SimplePackageIdentifierBatchingCallback::new);
      AtomicReference<Collection<Target>> result = new AtomicReference<>();
      try {
        targetPattern.eval(
            resolver,
            /*ignoredSubdirectories=*/ ImmutableSet::of,
            /*excludedSubdirectories=*/ ImmutableSet.of(),
            partialResult ->
                result.set(
                    partialResult instanceof Collection
                        ? (Collection<Target>) partialResult
                        : ImmutableSet.copyOf(partialResult)),
            QueryExceptionMarkerInterface.MarkerRuntimeException.class);
      } catch (ProcessPackageDirectoryException | InconsistentFilesystemException e) {
        throw new IllegalStateException(
            "PackageBackedRecursivePackageProvider doesn't throw for " + targetPattern, e);
      }
      return result.get();
    }
  }
}
