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

import com.facebook.buck.model.BuildTarget;
import com.facebook.buck.rules.AnnotationProcessingData;
import com.facebook.buck.rules.BuildRule;
import com.facebook.buck.rules.BuildRuleResolver;
import com.facebook.buck.rules.RuleKey;
import com.facebook.buck.util.BuckConstant;
import com.facebook.buck.util.HumanReadableException;
import com.google.common.base.Preconditions;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableSet;
import com.google.common.collect.ImmutableSortedSet;
import com.google.common.collect.Sets;

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

import javax.annotation.Nullable;

/**
 * Information for annotation processing.
 *
 * Annotation processing involves a set of processors, their classpath(s), and a few other
 * command-line options for javac.  We want to be able to specify all this various information
 * in a BUCK configuration file and use it when we generate the javac command.  This facilitates
 * threading the information through buck in a more descriptive package rather than passing all
 * the components separately.
 */
public class AnnotationProcessingParams implements AnnotationProcessingData {
  public final static AnnotationProcessingParams EMPTY = new AnnotationProcessingParams(
      null,
      ImmutableSet.<String>of(),
      ImmutableSet.<String>of(),
      ImmutableSet.<String>of(),
      ImmutableSortedSet.<BuildRule>of(),
      false);

  @Nullable
  private final BuildTarget ownerTarget;
  private final ImmutableSortedSet<String> searchPathElements;
  private final ImmutableSortedSet<String> names;
  private final ImmutableSortedSet<String> parameters;
  private final ImmutableSortedSet<BuildRule> rules;
  private final boolean processOnly;

  private AnnotationProcessingParams(
      @Nullable BuildTarget ownerTarget,
      Set<String> searchPathElements,
      Set<String> names,
      Set<String> parameters,
      Set<BuildRule> rules,
      boolean processOnly) {
    this.ownerTarget = ownerTarget;
    this.searchPathElements = ImmutableSortedSet.copyOf(searchPathElements);
    this.names = ImmutableSortedSet.copyOf(names);
    this.parameters = ImmutableSortedSet.copyOf(parameters);
    this.rules = ImmutableSortedSet.copyOf(rules);
    this.processOnly = processOnly;
  }

  private String getGeneratedSrcFolder() {
    return String.format("%s/%s__%s_gen__",
        BuckConstant.ANNOTATION_DIR,
        ownerTarget.getBasePathWithSlash(),
        ownerTarget.getShortName());
  }

  @Override
  public boolean isEmpty() {
    return searchPathElements.isEmpty() && names.isEmpty() && parameters.isEmpty();
  }

  @Override
  public ImmutableSortedSet<String> getSearchPathElements() {
    return searchPathElements;
  }

  @Override
  public ImmutableSortedSet<String> getNames() {
    return names;
  }

  @Override
  public ImmutableSortedSet<String> getParameters() {
    return parameters;
  }

  @Override
  public RuleKey.Builder appendToRuleKey(RuleKey.Builder builder) throws IOException {
    if (!isEmpty()) {
      // searchPathElements is not needed here since it comes from rules, which is appended below.
      String owner = (ownerTarget == null) ? null : ownerTarget.getFullyQualifiedName();
      builder.set("owner", owner)
          .set("names", names)
          .set("parameters", parameters)
          .set("processOnly", processOnly);

      ImmutableList.Builder<String> ruleKeyStrings = ImmutableList.builder();
      for (BuildRule rule : rules) {
        ruleKeyStrings.add(rule.getRuleKey().toString());
      }
      builder.set("annotationProcessorRuleKeys", ruleKeyStrings.build());
    }

    return builder;
  }

  @Override
  public boolean getProcessOnly() {
    return processOnly;
  }

  @Override
  @Nullable
  public String getGeneratedSourceFolderName() {
    if ((ownerTarget != null) && !isEmpty()) {
      return getGeneratedSrcFolder();
    } else {
      return null;
    }
  }

  public static class Builder {
    @Nullable
    private BuildTarget ownerTarget;
    private Set<BuildTarget> targets = Sets.newHashSet();
    private Set<String> names = Sets.newHashSet();
    private Set<String> parameters = Sets.newHashSet();
    private boolean processOnly;

    public Builder setOwnerTarget(BuildTarget owner) {
      ownerTarget = owner;
      return this;
    }

    public Builder addProcessorBuildTarget(BuildTarget target) {
      targets.add(target);
      return this;
    }

    public Builder addAllProcessors(Collection<? extends String> processorNames) {
      names.addAll(processorNames);
      return this;
    }

    public Builder addParameter(String parameter) {
      parameters.add(parameter);
      return this;
    }

    public Builder setProcessOnly(boolean processOnly) {
      this.processOnly = processOnly;
      return this;
    }

    public AnnotationProcessingParams build(BuildRuleResolver ruleResolver) {
      Preconditions.checkNotNull(ruleResolver);

      if (names.isEmpty() && targets.isEmpty() && parameters.isEmpty()) {
        return EMPTY;
      }

      Set<String> searchPathElements = Sets.newHashSet();
      ImmutableSortedSet.Builder<BuildRule> rules = ImmutableSortedSet.naturalOrder();

      for (BuildTarget target : targets) {
        BuildRule rule = ruleResolver.get(target);
        String type = rule.getType().getName();

        rules.add(rule);

        // We're using raw strings here to avoid circular dependencies.
        // TODO(simons): don't use raw strings.
        if ("java_binary".equals(type) || "prebuilt_jar".equals(type)) {
          String pathToOutput = rule.getBuildable().getPathToOutputFile();
          if (pathToOutput != null) {
            searchPathElements.add(pathToOutput);
          }
        } else if (rule instanceof HasClasspathEntries) {
          HasClasspathEntries javaLibraryRule = (HasClasspathEntries)rule;
          searchPathElements.addAll(javaLibraryRule.getTransitiveClasspathEntries().values());
        } else {
          throw new HumanReadableException(
              "%1$s: Error adding '%2$s' to annotation_processing_deps: " +
              "must refer only to prebuilt jar, java binary, or java library targets.",
              ownerTarget,
              target.getFullyQualifiedName());
        }
      }

      return new AnnotationProcessingParams(
          ownerTarget,
          searchPathElements,
          names,
          parameters,
          rules.build(),
          processOnly);
    }
  }
}
