// Copyright 2015 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.pkgcache;

import static com.google.common.truth.Truth.assertThat;

import com.google.common.base.Predicates;
import com.google.devtools.build.lib.cmdline.Label;
import com.google.devtools.build.lib.cmdline.LabelSyntaxException;
import com.google.devtools.build.lib.cmdline.ResolvedTargets;
import com.google.devtools.build.lib.cmdline.TargetParsingException;
import com.google.devtools.build.lib.events.DelegatingEventHandler;
import com.google.devtools.build.lib.events.ExtendedEventHandler;
import com.google.devtools.build.lib.packages.ConstantRuleVisibility;
import com.google.devtools.build.lib.packages.Target;
import com.google.devtools.build.lib.packages.util.PackageLoadingTestCase;
import com.google.devtools.build.lib.util.Pair;
import com.google.devtools.build.lib.vfs.PathFragment;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.TreeSet;
import java.util.stream.Collectors;
import org.junit.Before;

/**
 * Abstract framework for target pattern evaluation tests. The {@link TargetPatternEvaluatorTest}
 * contains much of the functionality that might be needed for future tests, and its methods should
 * be extracted here if they are needed by other classes.
 */
public abstract class AbstractTargetPatternEvaluatorTest extends PackageLoadingTestCase {
  protected TargetPatternPreloader parser;
  protected RecordingParsingListener parsingListener;

  protected static ResolvedTargets<Target> parseTargetPatternList(
      TargetPatternPreloader parser,
      ExtendedEventHandler eventHandler,
      List<String> targetPatterns,
      boolean keepGoing)
      throws TargetParsingException, InterruptedException {
    return parseTargetPatternList(
        PathFragment.EMPTY_FRAGMENT,
        parser,
        eventHandler,
        targetPatterns,
        keepGoing);
  }

  protected static ResolvedTargets<Target> parseTargetPatternList(
      PathFragment relativeWorkingDirectory,
      TargetPatternPreloader parser,
      ExtendedEventHandler eventHandler,
      List<String> targetPatterns,
      boolean keepGoing)
      throws TargetParsingException, InterruptedException {
    List<String> positivePatterns =
        targetPatterns.stream()
            .map((s) -> s.startsWith("-") ? s.substring(1) : s)
            .collect(Collectors.toList());
    Map<String, Collection<Target>> resolvedTargetsMap =
        parser.preloadTargetPatterns(
            eventHandler, relativeWorkingDirectory, positivePatterns, keepGoing);
    ResolvedTargets.Builder<Target> result = ResolvedTargets.builder();
    for (String pattern : targetPatterns) {
      if (pattern.startsWith("-")) {
        String positivePattern = pattern.substring(1);
        Collection<Target> resolvedTargets = resolvedTargetsMap.get(positivePattern);
        result.filter(Predicates.not(Predicates.in(resolvedTargets)));
      } else {
        Collection<Target> resolvedTargets = resolvedTargetsMap.get(pattern);
        result.addAll(resolvedTargets);
      }
    }
    return result.build();
  }

  /**
   * Method converts collection of targets to the new, mutable,
   * lexicographically-ordered set of corresponding labels.
   */
  protected static Set<Label> targetsToLabels(Iterable<Target> targets) {
    Set<Label> labels = new TreeSet<>();
    for (Target target : targets) {
      labels.add(target.getLabel());
    }
    return labels;
  }

  @Before
  public final void initializeParser() throws Exception {
    setUpSkyframe(ConstantRuleVisibility.PRIVATE);
    parser = skyframeExecutor.newTargetPatternPreloader();
    parsingListener = new RecordingParsingListener(reporter);
  }

  protected static Set<Label> labels(String... labelStrings) throws LabelSyntaxException {
    Set<Label> labels = new HashSet<>();
    for (String labelString : labelStrings) {
      labels.add(Label.parseCanonical(labelString));
    }
    return labels;
  }

  protected Pair<Set<Label>, Boolean> parseListKeepGoing(String... patterns)
      throws TargetParsingException, InterruptedException {
    ResolvedTargets<Target> result =
        parseTargetPatternList(parser, parsingListener, Arrays.asList(patterns), true);
    return Pair.of(targetsToLabels(result.getTargets()), result.hasError());
  }

  /** Event handler that records all parsing errors. */
  protected static final class RecordingParsingListener extends DelegatingEventHandler {
    protected final List<Pair<String, String>> events = new ArrayList<>();

    private RecordingParsingListener(ExtendedEventHandler delegate) {
      super(delegate);
    }

    @Override
    public void post(Postable post) {
      super.post(post);
      if (post instanceof ParsingFailedEvent) {
        ParsingFailedEvent e = (ParsingFailedEvent) post;
        events.add(Pair.of(e.getPattern(), e.getMessage()));
      }
    }

    protected void assertEmpty() {
      assertThat(events).isEmpty();
    }
  }
}
