/*
 * 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.json.BuildFileParseException;
import com.facebook.buck.model.BuildTargetException;
import com.facebook.buck.parser.PartialGraph;
import com.facebook.buck.rules.BuildRule;
import com.facebook.buck.rules.BuildRuleType;
import com.facebook.buck.rules.DependencyGraph;
import com.facebook.buck.rules.InputRule;
import com.facebook.buck.util.Ansi;
import com.facebook.buck.util.BuckConstant;
import com.facebook.buck.util.ProjectFilesystem;
import com.google.common.annotations.VisibleForTesting;
import com.google.common.base.Function;
import com.google.common.base.Throwables;
import com.google.common.collect.ImmutableSet;
import com.google.common.collect.ImmutableSetMultimap;
import com.google.common.collect.SetMultimap;
import com.google.common.collect.Sets;
import com.google.common.collect.TreeMultimap;

import java.io.File;
import java.io.IOException;
import java.io.PrintStream;
import java.nio.file.Path;
import java.util.Comparator;
import java.util.Set;

/**
 * Outputs targets that own a specified list of files.
 */
public class AuditOwnerCommand extends AbstractCommandRunner<AuditOwnerOptions> {

  private static final String FILE_INDENT = "    ";

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

  @VisibleForTesting
  static final class OwnersReport {
    final ImmutableSetMultimap<BuildRule, InputRule> owners;
    final ImmutableSet<InputRule> inputsWithNoOwners;
    final ImmutableSet<String> nonExistentInputs;
    final ImmutableSet<String> nonFileInputs;

    public OwnersReport(SetMultimap<BuildRule, InputRule> owners,
                        Set<InputRule> inputsWithNoOwners,
                        Set<String> nonExistentInputs,
                        Set<String> nonFileInputs) {
      this.owners = ImmutableSetMultimap.copyOf(owners);
      this.inputsWithNoOwners = ImmutableSet.copyOf(inputsWithNoOwners);
      this.nonExistentInputs = ImmutableSet.copyOf(nonExistentInputs);
      this.nonFileInputs = ImmutableSet.copyOf(nonFileInputs);
    }
  }

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

  @Override
  int runCommandWithOptionsInternal(AuditOwnerOptions options) throws IOException {

    // Build full graph.
    PartialGraph graph;
    try {
      graph = PartialGraph.createFullGraph(
          getProjectFilesystem(),
          options.getDefaultIncludes(),
          getParser(),
          getBuckEventBus());
    } catch (BuildTargetException | BuildFileParseException e) {
      console.printBuildFailureWithoutStacktrace(e);
      return 1;
    }

    OwnersReport report = generateOwnersReport(graph.getDependencyGraph(), options);
    printReport(options, report);
    return 0;
  }

  @VisibleForTesting
  OwnersReport generateOwnersReport(DependencyGraph graph, AuditOwnerOptions options) {

    // Process arguments assuming they are all relative file paths.
    Set<InputRule> inputs = Sets.newHashSet();
    Set<String> nonExistentInputs = Sets.newHashSet();
    Set<String> nonFileInputs = Sets.newHashSet();

    ProjectFilesystem projectFilesystem = getProjectFilesystem();
    Function<String, Path> pathRelativizer = projectFilesystem.getPathRelativizer();
    for (String filePath : options.getArguments()) {
      File file = projectFilesystem.getFileForRelativePath(filePath);
      if (!file.exists()) {
        nonExistentInputs.add(filePath);
      } else if (!file.isFile()) {
        nonFileInputs.add(filePath);
      } else {
        inputs.add(InputRule.inputPathAsInputRule(filePath, pathRelativizer));
      }
    }

    // Try to find owners for each valid and existing file.
    Set<InputRule> inputsWithNoOwners = Sets.newHashSet(inputs);
    SetMultimap<BuildRule, InputRule> owners = createOwnersMap();
    for (BuildRule rule : graph.getNodes()) {
      for (InputRule ruleInput : rule.getInputs()) {
        if (inputs.contains(ruleInput)) {
          inputsWithNoOwners.remove(ruleInput);
          owners.put(rule, ruleInput);
        }
      }
    }

    // Try to guess owners for nonexistent files.
    if (options.isGuessForDeletedEnabled()) {
      guessOwnersForNonExistentFiles(graph, owners, nonExistentInputs);
    }

    return new OwnersReport(owners, inputsWithNoOwners, nonExistentInputs, nonFileInputs);
  }

  /**
   * Guess target owners for deleted/missing files by finding first
   * BUCK file and assuming that all targets in this file used
   * missing file as input.
   */
  private void guessOwnersForNonExistentFiles(DependencyGraph graph,
      SetMultimap<BuildRule, InputRule> owners, Set<String> nonExistentFiles) {

    ProjectFilesystem projectFilesystem = getProjectFilesystem();
    Function<String, Path> pathRelativizer = projectFilesystem.getPathRelativizer();
    for (String nonExistentFile : nonExistentFiles) {
      File file = projectFilesystem.getFileForRelativePath(nonExistentFile);
      File buck = findBuckFileFor(file);
      for (BuildRule rule : graph.getNodes()) {
        if (rule.getType() == BuildRuleType.PROJECT_CONFIG) {
          continue;
        }
        try {
          File ruleBuck = rule.getBuildTarget().getBuildFile(projectFilesystem);
          if (buck.getCanonicalFile().equals(ruleBuck.getCanonicalFile())) {
            owners.put(rule, InputRule.inputPathAsInputRule(nonExistentFile, pathRelativizer));
          }
        } catch (IOException | BuildTargetException e) {
          throw Throwables.propagate(e);
        }
      }
    }
  }

  private File findBuckFileFor(File file) {
    File dir = file;
    if (!dir.isDirectory()) {
      dir = dir.getParentFile();
    }

    File projectRoot = getProjectFilesystem().getProjectRoot();
    while (dir != null && !dir.equals(projectRoot)) {
      File buck = new File(dir, BuckConstant.BUILD_RULES_FILE_NAME);
      if (buck.exists()) {
        return buck;
      }
      dir = dir.getParentFile();
    }
    throw new RuntimeException("Failed to find BUCK file for " + file.getPath());
  }

  private void printReport(AuditOwnerOptions options, OwnersReport report) {

    if (options.isFullReportEnabled()) {
      printFullReport(report);
    } else {
      printOwnersOnlyReport(report);
    }
  }

  /**
   * Print only targets which were identified as owners.
   */
  private void printOwnersOnlyReport(OwnersReport report) {
    Set<BuildRule> sortedRules = report.owners.keySet();
    for (BuildRule rule : sortedRules) {
      console.getStdOut().println(rule.getFullyQualifiedName());
    }
  }

  /**
   * Print detailed report on all owners.
   */
  private void printFullReport(OwnersReport report) {
    PrintStream out = console.getStdOut();
    Ansi ansi = console.getAnsi();
    if (report.owners.isEmpty()) {
      out.println(ansi.asErrorText("No owners found"));
    } else {
      out.println(ansi.asSuccessText("Owners:"));
      for (BuildRule rule : report.owners.keySet()) {
        out.println(rule.getFullyQualifiedName());
        Set<InputRule> files = report.owners.get(rule);
        for (InputRule input : files) {
          out.println(FILE_INDENT + input);
        }
      }
    }

    if (!report.inputsWithNoOwners.isEmpty()) {
      out.println();
      out.println(ansi.asErrorText("Files without owners:"));
      for (InputRule input : report.inputsWithNoOwners) {
        out.println(FILE_INDENT + input);
      }
    }

    if (!report.nonExistentInputs.isEmpty()) {
      out.println();
      out.println(ansi.asErrorText("Non existent files:"));
      for (String input : report.nonExistentInputs) {
        out.println(FILE_INDENT + input);
      }
    }

    if (!report.nonFileInputs.isEmpty()) {
      out.println();
      out.println(ansi.asErrorText("Non-file inputs:"));
      for (String input : report.nonFileInputs) {
        out.println(FILE_INDENT + input);
      }
    }
  }

  private SetMultimap<BuildRule, InputRule> createOwnersMap() {
    Comparator<BuildRule> keyComparator = new Comparator<BuildRule>() {
      @Override
      public int compare(BuildRule o1, BuildRule o2) {
        return o1.getFullyQualifiedName().compareTo(o2.getFullyQualifiedName());
      }
    };

    Comparator<InputRule> valueComparator = new Comparator<InputRule>() {
      @Override
      public int compare(InputRule o1, InputRule o2) {
        return o1.compareTo(o2);
      }
    };

    return TreeMultimap.create(keyComparator, valueComparator);
  }

  @Override
  String getUsageIntro() {
    return "prints targets that own specified files";
  }

}
