/*
 * Copyright 2012-present Facebook, Inc.
 *
 * 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.facebook.buck.cli;

import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNull;
import static org.junit.Assert.assertTrue;
import static org.junit.Assert.fail;

import com.facebook.buck.cli.TargetsCommand.TargetsCommandPredicate;
import com.facebook.buck.event.BuckEventBus;
import com.facebook.buck.event.BuckEventBusFactory;
import com.facebook.buck.java.DefaultJavaLibraryRule;
import com.facebook.buck.java.JavaTestRule;
import com.facebook.buck.java.PrebuiltJarRule;
import com.facebook.buck.json.BuildFileParseException;
import com.facebook.buck.model.BuildTarget;
import com.facebook.buck.model.BuildTargetFactory;
import com.facebook.buck.model.BuildTargetPattern;
import com.facebook.buck.parser.BuildTargetParseException;
import com.facebook.buck.parser.BuildTargetParser;
import com.facebook.buck.parser.NoSuchBuildTargetException;
import com.facebook.buck.parser.ParseContext;
import com.facebook.buck.parser.PartialGraph;
import com.facebook.buck.parser.PartialGraphFactory;
import com.facebook.buck.rules.ArtifactCache;
import com.facebook.buck.rules.BuildRule;
import com.facebook.buck.rules.BuildRuleResolver;
import com.facebook.buck.rules.BuildRuleType;
import com.facebook.buck.rules.DependencyGraph;
import com.facebook.buck.rules.FakeAbstractBuildRuleBuilderParams;
import com.facebook.buck.rules.FakeBuildRule;
import com.facebook.buck.rules.KnownBuildRuleTypes;
import com.facebook.buck.rules.NoopArtifactCache;
import com.facebook.buck.testutil.BuckTestConstant;
import com.facebook.buck.testutil.IdentityPathRelativizer;
import com.facebook.buck.testutil.RuleMap;
import com.facebook.buck.testutil.TestConsole;
import com.facebook.buck.util.ProjectFilesystem;
import com.facebook.buck.util.environment.Platform;
import com.fasterxml.jackson.core.JsonFactory;
import com.fasterxml.jackson.core.JsonParser.Feature;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.google.common.base.Charsets;
import com.google.common.base.Function;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableSet;
import com.google.common.collect.ImmutableSortedSet;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import com.google.common.io.Files;

import org.easymock.EasyMock;
import org.junit.Before;
import org.junit.Test;
import org.kohsuke.args4j.CmdLineException;

import java.io.File;
import java.io.IOException;
import java.io.Reader;
import java.io.StringReader;
import java.nio.file.Path;
import java.util.List;
import java.util.SortedMap;

public class TargetsCommandTest {

  private static final Function<String, Path> PATH_RELATIVIZER =
      IdentityPathRelativizer.getIdentityRelativizer();
  private final String projectRootPath = ".";
  private final File projectRoot = new File(projectRootPath);
  private TestConsole console;
  private TargetsCommand targetsCommand;

  private SortedMap<String, BuildRule> buildBuildTargets(String outputFile, String name) {
    return buildBuildTargets(outputFile, name, "//");
  }

  private SortedMap<String, BuildRule> buildBuildTargets(String outputFile,
      String name,
      String baseName) {
    SortedMap<String, BuildRule> buildRules = Maps.newTreeMap();
    BuildTarget buildTarget = new BuildTarget(baseName, name);
    FakeBuildRule buildRule = new FakeBuildRule(BuildRuleType.JAVA_LIBRARY,
        buildTarget,
        ImmutableSortedSet.<BuildRule>of(),
        ImmutableSet.<BuildTargetPattern>of());
    buildRule.setOutputFile(outputFile);

    buildRules.put(buildTarget.getFullyQualifiedName(), buildRule);
    return buildRules;
  }

  private String testDataPath(String fileName) {
    return "testdata/com/facebook/buck/cli/" + fileName;
  }

  @Before
  public void setUp() {
    console = new TestConsole();
    ProjectFilesystem projectFilesystem = new ProjectFilesystem(projectRoot);
    KnownBuildRuleTypes buildRuleTypes = new KnownBuildRuleTypes();
    ArtifactCache artifactCache = new NoopArtifactCache();
    BuckEventBus eventBus = BuckEventBusFactory.newInstance();
    targetsCommand =
        new TargetsCommand(new CommandRunnerParams(
            console,
            projectFilesystem,
            buildRuleTypes,
            new InstanceArtifactCacheFactory(artifactCache),
            eventBus,
            BuckTestConstant.PYTHON_INTERPRETER,
            Platform.detect()));
  }

  @Test
  public void testJsonOutputForBuildTarget() throws IOException, BuildFileParseException {
    final String testBuckFileJson1 = testDataPath("TargetsCommandTestBuckJson1.js");
    final String outputFile = "buck-out/gen/test/outputFile";
    JsonFactory jsonFactory = new JsonFactory();
    ObjectMapper mapper = new ObjectMapper();

    // run `buck targets` on the build file and parse the observed JSON.
    SortedMap<String, BuildRule> buildRules = buildBuildTargets(
        outputFile, "test-library", "//testdata/com/facebook/buck/cli");

    targetsCommand.printJsonForTargets(buildRules, /* includes */ ImmutableList.<String>of());
    String observedOutput = console.getTextWrittenToStdOut();
    JsonNode observed = mapper.readTree(jsonFactory.createJsonParser(observedOutput));

    // parse the expected JSON.
    String expectedJson = Files.toString(new File(testBuckFileJson1), Charsets.UTF_8)
        .replace("{$OUTPUT_FILE}", outputFile);
    JsonNode expected = mapper.readTree(jsonFactory.createJsonParser(expectedJson)
        .enable(Feature.ALLOW_COMMENTS));

    assertEquals("Output from targets command should match expected JSON.", expected, observed);
    assertEquals("Nothing should be printed to stderr.",
        "",
        console.getTextWrittenToStdErr());
  }

  @Test
  public void testNormalOutputForBuildTarget() throws IOException {
    final String outputFile = "buck-out/gen/test/outputFile";

    // run `buck targets` on the build file and parse the observed JSON.
    SortedMap<String, BuildRule> buildRules = buildBuildTargets(outputFile, "test-library");

    targetsCommand.printTargetsList(buildRules, /* showOutput */ false);
    String observedOutput = console.getTextWrittenToStdOut();

    assertEquals("Output from targets command should match expected output.",
        "//:test-library",
        observedOutput.trim());
    assertEquals("Nothing should be printed to stderr.",
        "",
        console.getTextWrittenToStdErr());
  }

  @Test
  public void testNormalOutputForBuildTargetWithOutput() throws IOException {
    final String outputFile = "buck-out/gen/test/outputFile";

    // run `buck targets` on the build file and parse the observed JSON.
    SortedMap<String, BuildRule> buildRules = buildBuildTargets(
        outputFile,
        "test-library");

    targetsCommand.printTargetsList(buildRules, /* showOutput */ true);
    String observedOutput = console.getTextWrittenToStdOut();

    assertEquals("Output from targets command should match expected output.",
        "//:test-library " + outputFile,
        observedOutput.trim());
    assertEquals("Nothing should be printed to stderr.",
        "",
        console.getTextWrittenToStdErr());
  }

  @Test
  public void testJsonOutputForMissingBuildTarget() throws BuildFileParseException, IOException {
    // nonexistent target should not exist.
    final String outputFile = "buck-out/gen/test/outputFile";
    SortedMap<String, BuildRule> buildRules = buildBuildTargets(outputFile, "nonexistent");
    targetsCommand.printJsonForTargets(buildRules, /* includes */ ImmutableList.<String>of());

    String output = console.getTextWrittenToStdOut();
    assertEquals("[\n]\n", output);
    assertEquals("unable to find rule for target //:nonexistent\n",
        console.getTextWrittenToStdErr());
  }

  @Test
  public void testValidateBuildTargetForNonAliasTarget()
      throws IOException, NoSuchBuildTargetException {
    // Set up the test buck file, parser, config, options.
    BuildTargetParser parser = EasyMock.createMock(BuildTargetParser.class);
    EasyMock.expect(parser.parse("//:test-library", ParseContext.fullyQualified()))
        .andReturn(new BuildTarget(
            "//testdata/com/facebook/buck/cli", "test-library"))
        .anyTimes();
    EasyMock.expect(parser.parse("//:", ParseContext.fullyQualified()))
        .andThrow(new BuildTargetParseException(
            String.format("%s cannot end with a colon.", "//:")))
        .anyTimes();
    EasyMock.expect(parser.parse("//blah/foo:bar", ParseContext.fullyQualified()))
        .andThrow(EasyMock.createMock(NoSuchBuildTargetException.class))
        .anyTimes();
    EasyMock.expect(parser.parse("//:test-libarry", ParseContext.fullyQualified()))
        .andReturn(new BuildTarget(
            "//testdata/com/facebook/buck/cli", "test-libarry"))
        .anyTimes();
    EasyMock.replay(parser);
    Reader reader = new StringReader("");
    BuckConfig config = BuckConfig.createFromReader(
        reader, new ProjectFilesystem(new File(".")), parser, Platform.detect());
    TargetsCommandOptions options = new TargetsCommandOptions(config);

    // Test a valid target.
    assertEquals(
        "//testdata/com/facebook/buck/cli:test-library",
        targetsCommand.validateBuildTargetForFullyQualifiedTarget("//:test-library", options));

    // Targets that will be rejected by BuildTargetParser with an exception.
    try {
      targetsCommand.validateBuildTargetForFullyQualifiedTarget("//:", options);
      fail("Should have thrown BuildTargetParseException.");
    } catch (BuildTargetParseException e) {
      assertEquals("//: cannot end with a colon.", e.getHumanReadableErrorMessage());
    }
    assertNull(targetsCommand.validateBuildTargetForFullyQualifiedTarget(
        "//blah/foo:bar", options));

    // Should pass BuildTargetParser but validateBuildTargetForNonAliasTarget will return null.
    assertNull(targetsCommand.validateBuildTargetForFullyQualifiedTarget(
        "//:test-libarry", options));
  }

  private PartialGraph createGraphFromBuildRules(BuildRuleResolver ruleResolver,
      List<String> targets) {
    List<BuildTarget> buildTargets = Lists.transform(targets, new Function<String, BuildTarget>() {
      @Override
      public BuildTarget apply(String target) {
        return BuildTargetFactory.newInstance(target);
      }
    });

    DependencyGraph dependencyGraph = RuleMap.createGraphFromBuildRules(ruleResolver);
    return PartialGraphFactory.newInstance(dependencyGraph, buildTargets);
  }

  @Test
  public void testGetMachingBuildTargets() throws CmdLineException, IOException {
    BuildRuleResolver ruleResolver = new BuildRuleResolver();
    ruleResolver.buildAndAddToIndex(
        PrebuiltJarRule.newPrebuiltJarRuleBuilder(new FakeAbstractBuildRuleBuilderParams())
        .setBuildTarget(BuildTargetFactory.newInstance("//empty:empty"))
        .setBinaryJar("")
        .addVisibilityPattern(BuildTargetPattern.MATCH_ALL));
    ruleResolver.buildAndAddToIndex(
        DefaultJavaLibraryRule.newJavaLibraryRuleBuilder(new FakeAbstractBuildRuleBuilderParams())
        .setBuildTarget(BuildTargetFactory.newInstance("//javasrc:java-library"))
        .addSrc("javasrc/JavaLibrary.java")
        .addVisibilityPattern(BuildTargetPattern.MATCH_ALL)
        .addDep(BuildTargetFactory.newInstance("//empty:empty")));
    ruleResolver.buildAndAddToIndex(
        JavaTestRule.newJavaTestRuleBuilder(new FakeAbstractBuildRuleBuilderParams())
        .setBuildTarget(BuildTargetFactory.newInstance("//javatest:test-java-library"))
        .addSrc("javatest/TestJavaLibrary.java")
        .addDep(BuildTargetFactory.newInstance("//javasrc:java-library")));

    List<String> targets = Lists.newArrayList();
    targets.add("//empty:empty");
    targets.add("//javasrc:java-library");
    targets.add("//javatest:test-java-library");

    PartialGraph graph = createGraphFromBuildRules(ruleResolver, targets);
    ImmutableSet<BuildRuleType> buildRuleTypes = ImmutableSet.of();

    ImmutableSet<String> referencedFiles;
    ImmutableSet<BuildTarget> targetBuildRules = ImmutableSet.of();

    // No target depends on the referenced file.
    referencedFiles = ImmutableSet.of("excludesrc/CannotFind.java");
    SortedMap<String, BuildRule> matchingBuildRules =
        targetsCommand.getMatchingBuildRules(
            graph.getDependencyGraph(),
            new TargetsCommandPredicate(graph, PATH_RELATIVIZER, buildRuleTypes, referencedFiles, targetBuildRules));
    assertTrue(matchingBuildRules.isEmpty());

    // Only test-android-library target depends on the referenced file.
    referencedFiles = ImmutableSet.of("javatest/TestJavaLibrary.java");
    matchingBuildRules =
        targetsCommand.getMatchingBuildRules(
            graph.getDependencyGraph(),
            new TargetsCommandPredicate(graph, PATH_RELATIVIZER, buildRuleTypes, referencedFiles, targetBuildRules));
    assertEquals(
        ImmutableSet.of("//javatest:test-java-library"),
        matchingBuildRules.keySet());

    // The test-android-library target indirectly depend on the referenced file,
    // while test-java-library target directly depend on the referenced file.
    referencedFiles = ImmutableSet.of("javasrc/JavaLibrary.java");
    matchingBuildRules =
        targetsCommand.getMatchingBuildRules(
            graph.getDependencyGraph(),
            new TargetsCommandPredicate(graph, PATH_RELATIVIZER, buildRuleTypes, referencedFiles, targetBuildRules));
    assertEquals(
        ImmutableSet.of("//javatest:test-java-library", "//javasrc:java-library"),
        matchingBuildRules.keySet());

    // Output target only need to depend on one referenced file.
    referencedFiles = ImmutableSet.of(
        "javatest/TestJavaLibrary.java", "othersrc/CannotFind.java");
    matchingBuildRules =
        targetsCommand.getMatchingBuildRules(
            graph.getDependencyGraph(),
            new TargetsCommandPredicate(graph, PATH_RELATIVIZER, buildRuleTypes, referencedFiles, targetBuildRules));
    assertEquals(
        ImmutableSet.of("//javatest:test-java-library"),
        matchingBuildRules.keySet());

    // If no referenced file, means this filter is disabled, we can find all targets.
    referencedFiles = null;
    matchingBuildRules =
        targetsCommand.getMatchingBuildRules(
            graph.getDependencyGraph(),
            new TargetsCommandPredicate(graph,
                PATH_RELATIVIZER,
                buildRuleTypes,
                ImmutableSet.<String>of(),
                targetBuildRules));
    assertEquals(
        ImmutableSet.of(
            "//javatest:test-java-library",
            "//javasrc:java-library",
            "//empty:empty"),
        matchingBuildRules.keySet());

    // Specify java_test, java_library as type filters.
    matchingBuildRules =
        targetsCommand.getMatchingBuildRules(
            graph.getDependencyGraph(),
            new TargetsCommandPredicate(
                graph,
                PATH_RELATIVIZER,
                ImmutableSet.of(BuildRuleType.JAVA_TEST, BuildRuleType.JAVA_LIBRARY),
                ImmutableSet.<String>of(),
                targetBuildRules));
    assertEquals(
        ImmutableSet.of(
            "//javatest:test-java-library",
            "//javasrc:java-library"),
        matchingBuildRules.keySet());


    // Specify java_test, java_library, and a rule name as type filters.
    matchingBuildRules =
        targetsCommand.getMatchingBuildRules(
            graph.getDependencyGraph(),
            new TargetsCommandPredicate(
                graph,
                PATH_RELATIVIZER,
                ImmutableSet.of(BuildRuleType.JAVA_TEST, BuildRuleType.JAVA_LIBRARY),
                ImmutableSet.<String>of(),
                ImmutableSet.of(BuildTargetFactory.newInstance("//javasrc:java-library"))));
    assertEquals(
        ImmutableSet.of("//javasrc:java-library"), matchingBuildRules.keySet());

    // Only filter by BuildTarget
    matchingBuildRules =
        targetsCommand.getMatchingBuildRules(
            graph.getDependencyGraph(),
            new TargetsCommandPredicate(
                graph,
                PATH_RELATIVIZER,
                ImmutableSet.<BuildRuleType>of(),
                ImmutableSet.<String>of(),
                ImmutableSet.of(BuildTargetFactory.newInstance("//javasrc:java-library"))));
    assertEquals(
        ImmutableSet.of("//javasrc:java-library"), matchingBuildRules.keySet());


    // Filter by BuildTarget and Referenced Files
    matchingBuildRules =
        targetsCommand.getMatchingBuildRules(
            graph.getDependencyGraph(),
            new TargetsCommandPredicate(
                graph,
                PATH_RELATIVIZER,
                ImmutableSet.<BuildRuleType>of(),
                ImmutableSet.of("javatest/TestJavaLibrary.java"),
                ImmutableSet.of(BuildTargetFactory.newInstance("//javasrc:java-library"))));
    assertEquals(
        ImmutableSet.<String>of(), matchingBuildRules.keySet());

  }
}
