/*
 * 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.assertTrue;

import com.facebook.buck.event.BuckEventBus;
import com.facebook.buck.graph.MutableDirectedGraph;
import com.facebook.buck.model.BuildTarget;
import com.facebook.buck.model.BuildTargetFactory;
import com.facebook.buck.model.BuildTargetPattern;
import com.facebook.buck.rules.ArtifactCache;
import com.facebook.buck.rules.BuildContext;
import com.facebook.buck.rules.BuildRule;
import com.facebook.buck.rules.BuildRuleSuccess;
import com.facebook.buck.rules.BuildRuleType;
import com.facebook.buck.rules.DependencyGraph;
import com.facebook.buck.rules.InputRule;
import com.facebook.buck.rules.KnownBuildRuleTypes;
import com.facebook.buck.rules.NoopArtifactCache;
import com.facebook.buck.rules.OutputKey;
import com.facebook.buck.rules.RuleKey;
import com.facebook.buck.testutil.TestConsole;
import com.facebook.buck.util.Console;
import com.facebook.buck.util.ProjectFilesystem;
import com.google.common.collect.ImmutableSet;
import com.google.common.collect.ImmutableSortedSet;
import com.google.common.util.concurrent.ListenableFuture;

import org.junit.Before;
import org.junit.Test;
import org.kohsuke.args4j.CmdLineException;
import org.kohsuke.args4j.CmdLineParser;

import java.io.File;

/**
 * Outputs targets that own a specified list of files.
 */
public class AuditOwnerCommandTest {

  private static class StubBuildRule implements BuildRule {

    private final ImmutableSet<InputRule> inputs;
    private final BuildTarget target;

    public StubBuildRule(BuildTarget target, Iterable<InputRule> inputs) {
      this.target = target;
      this.inputs = ImmutableSet.copyOf(inputs);
    }

    @Override
    public Iterable<InputRule> getInputs() {
      return inputs;
    }

    @Override
    public String getPathToOutputFile() {
      return null;
    }

    @Override
    public final OutputKey getOutputKey(ProjectFilesystem projectFilesystem) {
      throw new UnsupportedOperationException();
    }

    @Override
    public BuildTarget getBuildTarget() {
      return target;
    }

    @Override
    public String getFullyQualifiedName() {
      return target.getFullyQualifiedName();
    }

    @Override
    public BuildRuleType getType() {
      throw new UnsupportedOperationException();
    }

    @Override
    public ImmutableSortedSet<BuildRule> getDeps() {
      throw new UnsupportedOperationException();
    }

    @Override
    public ImmutableSet<BuildTargetPattern> getVisibilityPatterns() {
      throw new UnsupportedOperationException();
    }

    @Override
    public boolean isVisibleTo(BuildTarget target) {
      throw new UnsupportedOperationException();
    }

    @Override
    public ListenableFuture<BuildRuleSuccess> build(BuildContext context) {
      throw new UnsupportedOperationException();
    }

    @Override
    public BuildRuleSuccess.Type getBuildResultType() {
      throw new UnsupportedOperationException();
    }

    @Override
    public boolean isAndroidRule() {
      throw new UnsupportedOperationException();
    }

    @Override
    public boolean isLibrary() {
      throw new UnsupportedOperationException();
    }

    @Override
    public boolean getExportDeps() {
      throw new UnsupportedOperationException();
    }

    @Override
    public boolean isPackagingRule() {
      throw new UnsupportedOperationException();
    }

    @Override
    public final RuleKey getRuleKey() {
      throw new UnsupportedOperationException();
    }

    @Override
    public int compareTo(BuildRule buildRule) {
      throw new UnsupportedOperationException();
    }
  }

  private static class FakeProjectFilesystem extends ProjectFilesystem {
    public FakeProjectFilesystem() {
      super(new File("."));
    }
  }

  @SuppressWarnings("serial")
  private static class ExistingDirectoryFile extends File {
    public ExistingDirectoryFile(File file, String s) {
      super(file, s);
    }

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

    @Override
    public boolean isDirectory() {
      return true;
    }

    @Override
    public boolean exists() {
      return true;
    }
  }

  @SuppressWarnings("serial")
  private static class MissingFile extends File {
    public MissingFile(File file, String s) {
      super(file, s);
    }

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

    @Override
    public boolean isFile() {
      return true;
    }

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

  @SuppressWarnings("serial")
  private static class ExistingFile extends File {
    public ExistingFile(File file, String s) {
      super(file, s);
    }

    @Override
    public boolean exists() {
      return true;
    }

    @Override
    public boolean isFile() {
      return true;
    }

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

  private BuckConfig buckConfig;

  @Before
  public void setUp() {
    buckConfig = new FakeBuckConfig();
  }

  private AuditOwnerOptions getOptions(String... args) throws CmdLineException {
    AuditOwnerOptions options = new AuditOwnerOptions(buckConfig);
    new CmdLineParser(options).parseArgument(args);
    return options;
  }

  private AuditOwnerCommand createAuditOwnerCommand(ProjectFilesystem filesystem) {
    Console console = new TestConsole();
    KnownBuildRuleTypes buildRuleTypes = new KnownBuildRuleTypes();
    ArtifactCache artifactCache = new NoopArtifactCache();
    BuckEventBus eventBus = new BuckEventBus();
    return new AuditOwnerCommand(new CommandRunnerParams(
        console,
        filesystem,
        buildRuleTypes,
        artifactCache,
        eventBus));
  }

  @Test
  public void verifyPathsThatAreNotFilesAreCorrectlyReported() throws CmdLineException {
    // All files will be directories now
    FakeProjectFilesystem filesystem = new FakeProjectFilesystem() {
      @Override
      public File getFileForRelativePath(String pathRelativeToProjectRoot) {
        return new ExistingDirectoryFile(getProjectRoot(), pathRelativeToProjectRoot);
      }
    };

    // Empty graph
    MutableDirectedGraph<BuildRule> mutableGraph = new MutableDirectedGraph<BuildRule>();
    DependencyGraph graph = new DependencyGraph(mutableGraph);

    // Inputs that should be treated as "non-files", i.e. as directories
    String[] args = new String[] {
        "java/somefolder/badfolder",
        "java/somefolder",
        "com/test/subtest"
    };
    ImmutableSet<String> inputs = ImmutableSet.copyOf(args);

    // Create options
    AuditOwnerOptions options = getOptions(args);

    // Create command under test
    AuditOwnerCommand command = createAuditOwnerCommand(filesystem);

    // Generate report and verify nonFileInputs are filled in as expected.
    AuditOwnerCommand.OwnersReport report = command.generateOwnersReport(graph, options);
    assertTrue(report.owners.isEmpty());
    assertTrue(report.nonExistentInputs.isEmpty());
    assertTrue(report.inputsWithNoOwners.isEmpty());
    assertEquals(inputs, report.nonFileInputs);
  }

  @Test
  public void verifyMissingFilesAreCorrectlyReported() throws CmdLineException {
    // All files will be directories now
    FakeProjectFilesystem filesystem = new FakeProjectFilesystem() {
      @Override
      public File getFileForRelativePath(String pathRelativeToProjectRoot) {
        return new MissingFile(getProjectRoot(), pathRelativeToProjectRoot);
      }
    };

    // Empty graph
    MutableDirectedGraph<BuildRule> mutableGraph = new MutableDirectedGraph<BuildRule>();
    DependencyGraph graph = new DependencyGraph(mutableGraph);

    // Inputs that should be treated as missing files
    String[] args = new String[] {
        "java/somefolder/badfolder/somefile.java",
        "java/somefolder/perfect.java",
        "com/test/subtest/random.java"
    };
    ImmutableSet<String> inputs = ImmutableSet.copyOf(args);

    // Create options
    AuditOwnerOptions options = getOptions(args);

    // Create command under test
    AuditOwnerCommand command = createAuditOwnerCommand(filesystem);

    // Generate report and verify nonFileInputs are filled in as expected.
    AuditOwnerCommand.OwnersReport report = command.generateOwnersReport(graph, options);
    assertTrue(report.owners.isEmpty());
    assertTrue(report.nonFileInputs.isEmpty());
    assertTrue(report.inputsWithNoOwners.isEmpty());
    assertEquals(inputs, report.nonExistentInputs);
  }

  @Test
  public void verifyInputsWithoutOwnersAreCorrectlyReported() throws CmdLineException {
    // All files will be directories now
    FakeProjectFilesystem filesystem = new FakeProjectFilesystem() {
      @Override
      public File getFileForRelativePath(String pathRelativeToProjectRoot) {
        return new ExistingFile(getProjectRoot(), pathRelativeToProjectRoot);
      }
    };

    // Empty graph
    MutableDirectedGraph<BuildRule> mutableGraph = new MutableDirectedGraph<BuildRule>();
    DependencyGraph graph = new DependencyGraph(mutableGraph);

    // Inputs that should be treated as existing files
    String[] args = new String[] {
        "java/somefolder/badfolder/somefile.java",
        "java/somefolder/perfect.java",
        "com/test/subtest/random.java"
    };
    ImmutableSortedSet<InputRule> inputs
        = InputRule.inputPathsAsInputRules(ImmutableSortedSet.copyOf(args),
            filesystem.getPathRelativizer());

    // Create options
    AuditOwnerOptions options = getOptions(args);

    // Create command under test
    AuditOwnerCommand command = createAuditOwnerCommand(filesystem);

    // Generate report and verify nonFileInputs are filled in as expected.
    AuditOwnerCommand.OwnersReport report = command.generateOwnersReport(graph, options);
    assertTrue(report.owners.isEmpty());
    assertTrue(report.nonFileInputs.isEmpty());
    assertTrue(report.nonExistentInputs.isEmpty());
    assertEquals(inputs, report.inputsWithNoOwners);
  }

  /**
   * Verify that owners are correctly detected:
   *  - one owner, multiple inputs
   */
  @Test
  public void verifyInputsWithOneOwnerAreCorrectlyReported() throws CmdLineException {
    // All files will be directories now
    FakeProjectFilesystem filesystem = new FakeProjectFilesystem() {
      @Override
      public File getFileForRelativePath(String pathRelativeToProjectRoot) {
        return new ExistingFile(getProjectRoot(), pathRelativeToProjectRoot);
      }
    };

    // Create inputs
    String[] args = new String[] {
        "java/somefolder/badfolder/somefile.java",
        "java/somefolder/perfect.java",
        "com/test/subtest/random.java"
    };
    ImmutableSortedSet<InputRule> inputs
        = InputRule.inputPathsAsInputRules(ImmutableSortedSet.copyOf(args),
            filesystem.getPathRelativizer());

    // Build rule that owns all inputs
    BuildTarget target = BuildTargetFactory.newInstance("//base/name", "name");
    BuildRule ownerRule = new StubBuildRule(target, inputs);

    // Create graph
    MutableDirectedGraph<BuildRule> mutableGraph = new MutableDirectedGraph<BuildRule>();
    mutableGraph.addNode(ownerRule);

    DependencyGraph graph = new DependencyGraph(mutableGraph);

    // Create options
    AuditOwnerOptions options = getOptions(args);

    // Create command under test
    AuditOwnerCommand command = createAuditOwnerCommand(filesystem);

    // Generate report and verify nonFileInputs are filled in as expected.
    AuditOwnerCommand.OwnersReport report = command.generateOwnersReport(graph, options);
    assertTrue(report.nonFileInputs.isEmpty());
    assertTrue(report.nonExistentInputs.isEmpty());
    assertTrue(report.inputsWithNoOwners.isEmpty());

    assertEquals(inputs.size(), report.owners.size());
    assertTrue(report.owners.containsKey(ownerRule));
    assertEquals(ownerRule.getInputs(), report.owners.get(ownerRule));
  }

  /**
   * Verify that owners are correctly detected:
   *  - inputs that belong to multiple targets
   */
  @Test
  public void verifyInputsWithMultipleOwnersAreCorrectlyReported() throws CmdLineException {
    // All files will be directories now
    FakeProjectFilesystem filesystem = new FakeProjectFilesystem() {
      @Override
      public File getFileForRelativePath(String pathRelativeToProjectRoot) {
        return new ExistingFile(getProjectRoot(), pathRelativeToProjectRoot);
      }
    };

    // Create inputs
    String[] args = new String[] {
        "java/somefolder/badfolder/somefile.java",
        "java/somefolder/perfect.java",
        "com/test/subtest/random.java"
    };
    ImmutableSortedSet<InputRule> inputs
        = InputRule.inputPathsAsInputRules(ImmutableSortedSet.copyOf(args),
            filesystem.getPathRelativizer());

    // Build rule that owns all inputs
    BuildTarget target1 = BuildTargetFactory.newInstance("//base/name1:name1");
    BuildTarget target2 = BuildTargetFactory.newInstance("//base/name2:name2");
    BuildRule owner1Rule = new StubBuildRule(target1, inputs);
    BuildRule owner2Rule = new StubBuildRule(target2, inputs);

    // Create graph
    MutableDirectedGraph<BuildRule> mutableGraph = new MutableDirectedGraph<BuildRule>();
    mutableGraph.addNode(owner1Rule);
    mutableGraph.addNode(owner2Rule);

    DependencyGraph graph = new DependencyGraph(mutableGraph);

    // Create options
    AuditOwnerOptions options = getOptions(args);

    // Create command under test
    AuditOwnerCommand command = createAuditOwnerCommand(filesystem);

    // Generate report and verify nonFileInputs are filled in as expected.
    AuditOwnerCommand.OwnersReport report = command.generateOwnersReport(graph, options);
    assertTrue(report.nonFileInputs.isEmpty());
    assertTrue(report.nonExistentInputs.isEmpty());
    assertTrue(report.inputsWithNoOwners.isEmpty());

    assertTrue(report.owners.containsKey(owner1Rule));
    assertTrue(report.owners.containsKey(owner2Rule));
    assertEquals(owner1Rule.getInputs(), report.owners.get(owner1Rule));
    assertEquals(owner2Rule.getInputs(), report.owners.get(owner2Rule));
  }

}
