/*
 * 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 com.facebook.buck.graph.AbstractBottomUpTraversal;
import com.facebook.buck.json.BuildFileParseException;
import com.facebook.buck.log.Logger;
import com.facebook.buck.model.BuildTarget;
import com.facebook.buck.model.BuildTargetException;
import com.facebook.buck.parser.BuildTargetPatternParser;
import com.facebook.buck.parser.ParserConfig;
import com.facebook.buck.rules.TargetGraph;
import com.facebook.buck.rules.TargetNode;
import com.google.common.annotations.VisibleForTesting;
import com.google.common.base.Function;
import com.google.common.collect.Collections2;
import com.google.common.collect.FluentIterable;
import com.google.common.collect.ImmutableSet;
import com.google.common.collect.ImmutableSortedSet;

import java.io.IOException;
import java.util.Collection;


public class AuditDependenciesCommand extends AbstractCommandRunner<AuditDependenciesOptions> {

  private static final Logger LOG = Logger.get(AuditDependenciesCommand.class);

  public AuditDependenciesCommand(CommandRunnerParams params) {
    super(params);
  }

  @Override
  AuditDependenciesOptions createOptions(BuckConfig buckConfig) {
    return new AuditDependenciesOptions(buckConfig);
  }

  @Override
  int runCommandWithOptionsInternal(AuditDependenciesOptions options)
      throws IOException, InterruptedException {
    final ImmutableSet<String> fullyQualifiedBuildTargets = ImmutableSet.copyOf(
        options.getArgumentsFormattedAsBuildTargets());

    if (fullyQualifiedBuildTargets.isEmpty()) {
      console.printBuildFailure("Must specify at least one build target.");
      return 1;
    }

    ImmutableSet<BuildTarget> targets = FluentIterable
        .from(options.getArgumentsFormattedAsBuildTargets())
        .transform(
            new Function<String, BuildTarget>() {
              @Override
              public BuildTarget apply(String input) {
                return getParser().getBuildTargetParser().parse(
                    input,
                    BuildTargetPatternParser.fullyQualified(
                        getParser().getBuildTargetParser()));
              }
            })
        .toSet();

    TargetGraph graph;
    try {
      graph = getParser().buildTargetGraphForBuildTargets(
          targets,
          new ParserConfig(options.getBuckConfig()),
          getBuckEventBus(),
          console,
          environment,
          options.getEnableProfiling());
    } catch (BuildTargetException | BuildFileParseException e) {
      console.printBuildFailureWithoutStacktrace(e);
      return 1;
    }

    ImmutableSet<BuildTarget> targetsToPrint = options.shouldShowTransitiveDependencies() ?
        getTransitiveDependencies(targets, graph) :
        getImmediateDependencies(targets, graph);

    Collection<String> namesToPrint = Collections2.transform(
        targetsToPrint, new Function<BuildTarget, String>() {

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

    ImmutableSortedSet<String> sortedNames = ImmutableSortedSet.copyOf(namesToPrint);

    if (options.shouldGenerateJsonOutput()) {
      printJSON(sortedNames);
    } else {
      printToConsole(sortedNames);
    }

    return 0;
  }

  @VisibleForTesting
  ImmutableSet<BuildTarget> getTransitiveDependencies(
      final ImmutableSet<BuildTarget> targets,
      TargetGraph graph) {
    final ImmutableSet.Builder<BuildTarget> builder = ImmutableSet.builder();

    TargetGraph subgraph = graph.getSubgraph(graph.getAll(targets));
    new AbstractBottomUpTraversal<TargetNode<?>, Void>(subgraph) {

      @Override
      public void visit(TargetNode<?> node) {
        LOG.debug("Visiting dependency " + node.getBuildTarget().getFullyQualifiedName());
        // Don't add the requested target to the list of dependencies
        if (!targets.contains(node.getBuildTarget())) {
          builder.add(node.getBuildTarget());
        }
      }

      @Override
      public Void getResult() {
        return null;
      }

    }.traverse();

    return builder.build();
  }

  @VisibleForTesting
  ImmutableSet<BuildTarget> getImmediateDependencies(
      final ImmutableSet<BuildTarget> targets,
      TargetGraph graph) {
    ImmutableSet.Builder<BuildTarget> builder = ImmutableSet.builder();

    for (BuildTarget target : targets) {
      TargetNode<?> targetNode = graph.get(target);
      builder.addAll(targetNode.getDeps());
    }

    return builder.build();
  }

  private void printJSON(Collection<String> names) throws IOException {
    getObjectMapper().writeValue(
        console.getStdOut(),
        names);
  }

  private void printToConsole(Collection<String> names) {
    for (String name : names) {
      getStdOut().println(name);
    }
  }

  @Override
  String getUsageIntro() {
    return "provides facilities to audit build targets' dependencies";
  }

}
