/*
 * Copyright 2013-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.json.ProjectBuildFileParser;
import com.facebook.buck.util.Escaper;
import com.facebook.buck.util.HumanReadableException;
import com.facebook.buck.util.MoreStrings;
import com.facebook.buck.util.ProjectFilesystem;
import com.google.common.annotations.VisibleForTesting;
import com.google.common.base.Predicate;
import com.google.common.base.Strings;
import com.google.common.collect.ImmutableSet;
import com.google.common.collect.Sets;

import java.io.IOException;
import java.io.PrintStream;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.Map;
import java.util.SortedSet;

import javax.annotation.Nullable;

/**
 * Evaluates a build file and prints out an equivalent build file with all includes/macros
 * expanded. When complex macros are in play, this helps clarify what the resulting build rule
 * definitions are.
 */
public class AuditRulesCommand extends AbstractCommandRunner<AuditRulesOptions> {

  /** Indent to use in generated build file. */
  private static String INDENT = "  ";

  /**
   * Properties from the JSON produced by {@code buck.py} that start with this prefix do not
   * correspond to build rule arguments specified by the user. Instead, they contain internal-only
   * metadata, so they should not be printed when the build rule is reproduced.
   */
  private static final String INTERNAL_PROPERTY_NAME_PREFIX = "buck.";

  /**
   * The name of the property in the JSON produced by {@code buck.py} that identifies the type of
   * the build rule being defined.
   * <p>
   * TODO(mbolin): Change this property name to "buck.type" so that all internal properties start
   * with "buck.".
   */
  private static final String TYPE_PROPERTY_NAME = "type";

  /** Properties that should be listed last in the declaration of a build rule. */
  private static final ImmutableSet<String> LAST_PROPERTIES = ImmutableSet.of("deps", "visibility");

  protected AuditRulesCommand(CommandRunnerParams params) {
    super(params);
  }

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

  @Override
  String getUsageIntro() {
    return "List build rule definitions resulting from expanding macros.";
  }

  /** Prints the expanded build rules from the specified build files to the console. */
  @Override
  int runCommandWithOptionsInternal(AuditRulesOptions options) throws IOException {
    ProjectFilesystem projectFilesystem = getProjectFilesystem();
    try (ProjectBuildFileParser parser = new ProjectBuildFileParser(projectFilesystem,
        options.getBuckConfig().getDefaultIncludes(),
        options.getBuckConfig().getPythonInterpreter())) {
      PrintStream out = console.getStdOut();
      for (String pathToBuildFile : options.getArguments()) {
        // Print a comment with the path to the build file.
        out.printf("# %s\n\n", pathToBuildFile);

        // Resolve the path specified by the user.
        Path path = Paths.get(pathToBuildFile);
        if (!path.isAbsolute()) {
          Path root = projectFilesystem.getProjectRoot().toPath();
          path = root.resolve(path);
        }

        // Parse the rules from the build file.
        List<Map<String, Object>> rawRules;
        try {
          rawRules = parser.getAllRules(path.toString());
        } catch (BuildFileParseException e) {
          throw new HumanReadableException(e);
        }

        // Format and print the rules from the raw data, filtered by type.
        final ImmutableSet<String> types = options.getTypes();
        Predicate<String> includeType = new Predicate<String>() {
          @Override
          public boolean apply(String type) {
            return types.isEmpty() || types.contains(type);
          }
        };
        printRulesToStdout(rawRules, includeType);
      }
    } catch (BuildFileParseException e) {
      throw new HumanReadableException("Unable to create parser");
    }

    return 0;
  }

  private void printRulesToStdout(List<Map<String, Object>> rawRules,
      Predicate<String> includeType) {
    PrintStream out = console.getStdOut();

    for (Map<String, Object> rawRule : rawRules) {
      String type = (String)rawRule.get(TYPE_PROPERTY_NAME);
      if (!includeType.apply(type)) {
        continue;
      }

      out.printf("%s(\n", type);

      // The properties in the order they should be displayed for this rule.
      LinkedHashSet<String> properties = Sets.newLinkedHashSet();

      // Always display the "name" property first.
      properties.add("name");

      // Add the properties specific to the rule.
      SortedSet<String> customProperties = Sets.newTreeSet();
      for (String key : rawRule.keySet()) {
        // Ignore keys that start with "buck.".
        if (!(key.equals(TYPE_PROPERTY_NAME) ||
            key.startsWith(INTERNAL_PROPERTY_NAME_PREFIX) ||
            LAST_PROPERTIES.contains(key))) {
          customProperties.add(key);
        }
      }
      properties.addAll(customProperties);

      // Add common properties that should be displayed last.
      properties.addAll(LAST_PROPERTIES);

      // Write out the properties and their corresponding values.
      for (String property : properties) {
        String displayValue = createDisplayString(rawRule.get(property));
        out.printf("%s%s = %s,\n", INDENT, property, displayValue);
      }

      // Close the rule definition.
      out.printf(")\n\n");
    }
  }

  /**
   * @param value in a Map returned by {@link ProjectBuildFileParser#getAllRules(String)}.
   * @return a string that represents the Python equivalent of the value.
   */
  @VisibleForTesting
  static String createDisplayString(@Nullable Object value) {
    if (value == null) {
      return "None";
    } else if (value instanceof Boolean) {
      return MoreStrings.capitalize(value.toString());
    } else if (value instanceof String) {
      return Escaper.escapeAsPythonString(value.toString());
    } else if (value instanceof Number) {
      return value.toString();
    } else if (value instanceof List) {
      StringBuilder out = new StringBuilder("[\n");

      String indent = Strings.repeat(INDENT, 2);
      for (Object item : (List<?>)value) {
        out.append(indent).append(createDisplayString(item)).append(",\n");
      }

      out.append(INDENT).append("]");
      return out.toString();
    } else {
      throw new IllegalStateException();
    }
  }
}
