// Copyright 2014 The Bazel Authors. All rights reserved.
//
// 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.google.devtools.build.lib.testutil;

import com.google.common.base.Function;
import com.google.common.base.Joiner;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.Iterables;
import com.google.common.collect.LinkedHashMultimap;
import com.google.common.collect.Lists;
import com.google.common.collect.Multimap;
import com.google.devtools.build.lib.packages.RuleClass;
import com.google.devtools.build.lib.util.Preconditions;

import java.util.Collection;
import java.util.HashMap;
import java.util.Map;

/**
 * Utility for quickly creating BUILD file rules for use in tests.
 *
 * <p>The use case for this class is writing BUILD files where simple
 * readability for the sake of rules' relationship to the test framework
 * is more important than detailed semantics and layout.
 *
 * <p>The behavior provided by this class is not meant to be exhaustive,
 * but should handle a majority of simple cases.
 *
 * <p>Example:
 *
 * <pre>
 *   String text = new BuildRuleBuilder("java_library", "MyRule")
        .setSources("First.java", "Second.java", "Third.java")
        .setDeps(":library", "//java/com/google/common/collect")
        .setResources("schema/myschema.xsd")
        .build();
 * </pre>
 *
 */
public class BuildRuleBuilder {
  protected final RuleClass ruleClass;
  protected final String ruleName;
  private Multimap<String, String> multiValueAttributes;
  private Map<String, Object> singleValueAttributes;
  protected Map<String, RuleClass> ruleClassMap;
  
  /**
   * Create a new instance.
   *
   * @param ruleClass the rule class of the new rule
   * @param ruleName the name of the new rule.
   */
  public BuildRuleBuilder(String ruleClass, String ruleName) {
    this(ruleClass, ruleName, getDefaultRuleClassMap());
  }

  protected static Map<String, RuleClass> getDefaultRuleClassMap() {
    return TestRuleClassProvider.getRuleClassProvider().getRuleClassMap();
  }

  public BuildRuleBuilder(String ruleClass, String ruleName, Map<String, RuleClass> ruleClassMap) {
    this.ruleClass = ruleClassMap.get(ruleClass);
    this.ruleName = ruleName;
    this.multiValueAttributes = LinkedHashMultimap.create();
    this.singleValueAttributes = new HashMap<>();
    this.ruleClassMap = ruleClassMap;
  }

  /**
   * Sets the value of a single valued attribute
   */
  public BuildRuleBuilder setSingleValueAttribute(String attrName, Object value) {
    Preconditions.checkState(
        !singleValueAttributes.containsKey(attrName), "attribute '%s' already set", attrName);
    singleValueAttributes.put(attrName, value);
    return this;
  }

  /**
   * Sets the value of a list type attribute
   */
  public BuildRuleBuilder addMultiValueAttributes(String attrName, String... value) {
    multiValueAttributes.putAll(attrName, Lists.newArrayList(value));
    return this;
  }

  /**
   * Generate the rule
   *
   * @return a string representation of the rule.
   */
  public String build() {
    StringBuilder sb = new StringBuilder();
    sb.append(ruleClass.getName()).append("(");
    printNormal(sb, "name", ruleName);
    for (Map.Entry<String, Collection<String>> entry : multiValueAttributes.asMap().entrySet()) {
      printArray(sb, entry.getKey(), entry.getValue());
    }
    for (Map.Entry<String, Object> entry : singleValueAttributes.entrySet()) {
      printNormal(sb, entry.getKey(), entry.getValue());
    }
    sb.append(")\n");
    return sb.toString();
  }

  private void printArray(StringBuilder sb, String attr, Collection<String> values) {
    if (values == null || values.isEmpty()) {
      return;
    }
    sb.append("      ").append(attr).append(" = ");
    printList(sb, values);
    sb.append(",");
    sb.append("\n");
  }

  private void printNormal(StringBuilder sb, String attr, Object value) {
    if (value == null) {
      return;
    }
    sb.append("      ").append(attr).append(" = ");
    if (value instanceof Integer) {
      sb.append(value);
    } else {
      sb.append("'").append(value).append("'");
    }
    sb.append(",");
    sb.append("\n");
  }

  /**
   * Turns iterable of {a b c} into string "['a', 'b', 'c']", appends to
   * supplied StringBuilder.
   */
  private void printList(StringBuilder sb, Collection<String> elements) {
    sb.append("[");
    Joiner.on(",").appendTo(sb,
        Iterables.transform(elements, new Function<String, String>() {
          @Override
          public String apply(String from) {
            return "'" + from + "'";
          }
        }));
    sb.append("]");
  }

  /**
   * Returns the transitive closure of file names need to be generated in order
   * for this rule to build.
   */
  public Collection<String> getFilesToGenerate() {
    return ImmutableList.of();
  }

  /**
   * Returns the transitive closure of BuildRuleBuilders need to be generated in order
   * for this rule to build.
   */
  public Collection<BuildRuleBuilder> getRulesToGenerate() {
    return ImmutableList.of();
  }

  /**
   * Returns a {@link Dependency} of this {@link BuildRuleBuilder} using attrName.
   */
  public Dependency dependsVia(String attrName) {
    return new Dependency(this, attrName);
  }

  /**
   * Representing a {@link BuildRuleBuilder} depending on an other rule via a certain attribute.
   */
  public class Dependency {
    private BuildRuleBuilder buildRuleBuilder;
    private String attrName;

    private Dependency(BuildRuleBuilder buildRuleBuilder, String attrName) {
      this.buildRuleBuilder = buildRuleBuilder;
      this.attrName = attrName;
    }

    /**
     * Returns this {@link BuildRuleBuilder} with a new dependency on otherRule.
     */
    public BuildRuleBuilder on(BuildRuleBuilder otherRule) {
      buildRuleBuilder.addMultiValueAttributes(attrName, otherRule.ruleName);
      return buildRuleBuilder;
    }
  }
}
