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

import com.facebook.buck.model.AnnotationProcessingData;
import com.facebook.buck.rules.RuleKey;
import com.google.common.base.Function;
import com.google.common.base.Joiner;
import com.google.common.base.Optional;
import com.google.common.base.Preconditions;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.Iterables;

import javax.annotation.Nullable;

/**
 * Represents the command line options that should be passed to javac. Note that the options do not
 * include either the classpath or the directory for storing class files.
 */
public class JavacOptions {

  private static final String DEFAULT_JAVA_TARGET = "6";

  // Fields are initialized in order. We need the default java target level to have been set.
  public static final JavacOptions DEFAULTS = JavacOptions.builder().build();

  private final boolean debug;
  private final boolean verbose;
  private final String sourceLevel;
  private final String targetLevel;
  private final AnnotationProcessingData annotationProcessingData;
  private final Optional<String> bootclasspath;

  private JavacOptions(boolean debug,
      boolean verbose,
      String sourceLevel,
      String targetLevel,
      Optional<String> bootclasspath,
      AnnotationProcessingData annotationProcessingData) {
    this.debug = debug;
    this.verbose = verbose;
    this.sourceLevel = Preconditions.checkNotNull(sourceLevel);
    this.targetLevel = Preconditions.checkNotNull(targetLevel);
    this.bootclasspath = Preconditions.checkNotNull(bootclasspath);
    this.annotationProcessingData = Preconditions.checkNotNull(annotationProcessingData);
  }

  public void appendOptionsToList(ImmutableList.Builder<String> optionsBuilder,
      Function<String, String> pathRelativizer) {
    appendOptionsToList(optionsBuilder,
        pathRelativizer,
        AnnotationProcessingDataDecorators.identity());
  }

  public void appendOptionsToList(ImmutableList.Builder<String> optionsBuilder,
      final Function<String, String> pathRelativizer,
      AnnotationProcessingDataDecorator decorator) {
    Preconditions.checkNotNull(optionsBuilder);

    // Add some standard options.
    optionsBuilder.add("-target", sourceLevel);
    optionsBuilder.add("-source", targetLevel);

    if (debug) {
      optionsBuilder.add("-g");
    }

    if (verbose) {
      optionsBuilder.add("-verbose");
    }

    // Override the bootclasspath if Buck is building Java code for Android.
    if (bootclasspath.isPresent()) {
      optionsBuilder.add("-bootclasspath", bootclasspath.get());
    }

    // Add annotation processors.
    AnnotationProcessingData annotationProcessingData = decorator.decorate(this.annotationProcessingData);
    if (!annotationProcessingData.isEmpty()) {

      // Specify where to generate sources so IntelliJ can pick them up.
      String generateTo = annotationProcessingData.getGeneratedSourceFolderName();
      if (generateTo != null) {
        optionsBuilder.add("-s").add(generateTo);
      }

      // Create a path relativizer that relativizes all processor paths, except for
      // AbiWritingAnnotationProcessingDataDecorator.ABI_PROCESSOR_CLASSPATH, which will already be
      // an absolute path.
      Function<String, String> pathRelativizerThatOmitsAbiProcessor =
          new Function<String, String>() {
        @Override
        public String apply(String searchPathElement) {
          if (AbiWritingAnnotationProcessingDataDecorator.ABI_PROCESSOR_CLASSPATH.equals(
              searchPathElement)) {
            return searchPathElement;
          } else {
            return pathRelativizer.apply(searchPathElement);
          }
        }
      };

      // Specify processorpath to search for processors.
      optionsBuilder.add("-processorpath",
          Joiner.on(':').join(
              Iterables.transform(annotationProcessingData.getSearchPathElements(),
                  pathRelativizerThatOmitsAbiProcessor)));

      // Specify names of processors.
      if (!annotationProcessingData.getNames().isEmpty()) {
        optionsBuilder.add("-processor", Joiner.on(',').join(annotationProcessingData.getNames()));
      }

      // Add processor parameters.
      for (String parameter : annotationProcessingData.getParameters()) {
        optionsBuilder.add("-A" + parameter);
      }

      if (annotationProcessingData.getProcessOnly()) {
        optionsBuilder.add("-proc:only");
      }
    }
  }

  public void appendToRuleKey(RuleKey.Builder builder) {
    // TODO(simons): Include bootclasspath params.
    builder.set("sourceLevel", sourceLevel)
        .set("targetLevel", targetLevel)
        .set("debug", debug)

        // Annotation processing data.
        .set("searchPathElements", annotationProcessingData.getSearchPathElements())
        .set("names", annotationProcessingData.getNames())
        .set("parameters", annotationProcessingData.getParameters())
        .set("generatedSource", annotationProcessingData.getGeneratedSourceFolderName())
        .set("processOnly", annotationProcessingData.getProcessOnly());
  }

  public AnnotationProcessingData getAnnotationProcessingData() {
    return annotationProcessingData;
  }

  public static Builder builder() {
    return new Builder();
  }

  public static Builder builder(JavacOptions options) {
    Builder builder = builder();

    builder.setVerboseOutput(options.verbose);
    if (!options.debug) {
      builder.setProductionBuild();
    }

    builder.setSourceLevel(options.sourceLevel);
    builder.setTargetLevel(options.targetLevel);

    builder.setAnnotationProcessingData(options.annotationProcessingData);
    builder.setBootclasspath(options.bootclasspath.orNull());

    return builder;
  }

  public static class Builder {
    private boolean debug = true;
    private boolean verbose = false;
    private String sourceLevel = DEFAULT_JAVA_TARGET;
    private String targetLevel = DEFAULT_JAVA_TARGET;
    private Optional<String> bootclasspath = Optional.absent();
    private AnnotationProcessingData annotationProcessingData = AnnotationProcessingData.EMPTY;

    private Builder() {
    }

    public Builder setProductionBuild() {
      debug = false;
      return this;
    }

    public Builder setVerboseOutput(boolean verbose) {
      this.verbose = verbose;
      return this;
    }

    public Builder setSourceLevel(String sourceLevel) {
      this.sourceLevel = Preconditions.checkNotNull(sourceLevel);
      return this;
    }

    public Builder setTargetLevel(String targetLevel) {
      this.targetLevel = Preconditions.checkNotNull(targetLevel);
      return this;
    }

    public Builder setBootclasspath(@Nullable String bootclasspath) {
      this.bootclasspath = Optional.fromNullable(bootclasspath);
      return this;
    }

    public Builder setAnnotationProcessingData(AnnotationProcessingData annotationProcessingData) {
      this.annotationProcessingData = annotationProcessingData;
      return this;
    }

    public JavacOptions build() {
      return new JavacOptions(
          debug,
          verbose,
          sourceLevel,
          targetLevel,
          bootclasspath,
          annotationProcessingData
      );
    }
  }
}
