/*
 * 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.command.Build;
import com.facebook.buck.rules.DependencyGraph;
import com.facebook.buck.step.ExecutionContext;
import com.facebook.buck.step.Verbosity;
import com.facebook.buck.util.AndroidPlatformTarget;
import com.google.common.annotations.VisibleForTesting;
import com.google.common.base.Optional;
import com.google.common.base.Preconditions;

import org.kohsuke.args4j.Option;

import java.io.File;
import java.io.FileReader;
import java.io.IOException;
import java.io.PrintStream;
import java.util.Properties;

import javax.annotation.Nullable;

public abstract class AbstractCommandOptions {

  @VisibleForTesting static final String HELP_LONG_ARG = "--help";
  @VisibleForTesting static final String VERBOSE_LONG_ARG = "--verbose";
  @VisibleForTesting static final String VERBOSE_SHORT_ARG = "-v";

  @Option(
      name = HELP_LONG_ARG,
      usage = "Prints the available options and exits.")
  private boolean help = false;

  /** Verbosity level to use when running Buck. */
  @Option(
      name = VERBOSE_LONG_ARG,
      aliases = { VERBOSE_SHORT_ARG },
      usage = "Specify a number between 1 and 10.")
  private int verbosityLevel = Verbosity.STANDARD_INFORMATION.ordinal();

  /** Determined by {@link #verbosityLevel}, if not set explicitly. */
  @Nullable
  private Verbosity verbosity;

  private final BuckConfig buckConfig;

  AbstractCommandOptions(BuckConfig buckConfig) {
    this.buckConfig = Preconditions.checkNotNull(buckConfig);
  }

  protected BuckConfig getBuckConfig() {
    return buckConfig;
  }

  public Iterable<String> getDefaultIncludes() {
    return this.buckConfig.getDefaultIncludes();
  }

  public boolean showHelp() {
    return help;
  }

  public Verbosity getVerbosity() {
    if (verbosity != null) {
      return verbosity;
    }

    if (verbosityLevel >= 8) {
      verbosity = Verbosity.ALL;
    } else if (verbosityLevel >= 5) {
      verbosity = Verbosity.COMMANDS_AND_OUTPUT;
    } else if (verbosityLevel >= 2) {
      verbosity = Verbosity.COMMANDS;
    } else if (verbosityLevel >= 1) {
      verbosity = Verbosity.STANDARD_INFORMATION;
    } else {
      verbosity = Verbosity.SILENT;
    }

    return verbosity;
  }

  public void setVerbosity(@Nullable Verbosity verbosity) {
    this.verbosity = verbosity;
  }

  /** @return androidSdkDir */
  protected Optional<File> findAndroidSdkDir() {
    Optional<File> androidSdkDir = findDirectoryByPropertiesThenEnvironmentVariable(
        "sdk.dir", "ANDROID_SDK", "ANDROID_HOME");
    if (androidSdkDir.isPresent()) {
      Preconditions.checkArgument(androidSdkDir.get().isDirectory(),
          "The location of your Android SDK %s must be a directory",
          androidSdkDir.get());
    }
    return androidSdkDir;
  }

  /** @return androidNdkDir */
  protected Optional<File> findAndroidNdkDir() {
    return findDirectoryByPropertiesThenEnvironmentVariable("ndk.dir", "ANDROID_NDK");
  }

  /**
   * @param propertyName The name of the property to look for in local.properties.
   * @param environmentVariable The name of the environment variable to try.
   * @return If present, the value is confirmed to be a directory.
   */
  private Optional<File> findDirectoryByPropertiesThenEnvironmentVariable(
      String propertyName,
      String... environmentVariables) {
    // First, try to find a value in local.properties using the specified propertyName.
    String dirPath = null;
    File propertiesFile = new File("local.properties");
    if (propertiesFile.exists()) {
      Properties localProperties = new Properties();
      try {
        localProperties.load(new FileReader(propertiesFile));
      } catch (IOException e) {
        throw new RuntimeException(
            "Failed reading properties from " + propertiesFile.getAbsolutePath(),
            e);
      }
      dirPath = localProperties.getProperty(propertyName);
    }

    // If dirPath is not set, try each of the environment variables, in order, to find it.
    for (String environmentVariable : environmentVariables) {
      if (dirPath == null) {
        dirPath = System.getenv(environmentVariable);
      } else {
        break;
      }
    }

    // If a dirPath was found, verify that it maps to a directory before returning it.
    if (dirPath == null) {
      return Optional.absent();
    } else {
      File directory = new File(dirPath);
      if (!directory.isDirectory()) {
        throw new RuntimeException(
            directory.getAbsolutePath() + " was not a directory when trying to find " +
              propertyName);
      }
      return Optional.of(directory);
    }
  }

  protected ExecutionContext createExecutionContext(
      AbstractCommandRunner<?> commandRunner,
      File projectDirectoryRoot,
      DependencyGraph dependencyGraph) {
    return new ExecutionContext(
        getVerbosity(),
        projectDirectoryRoot,
        findAndroidPlatformTarget(dependencyGraph, commandRunner.stdErr),
        findAndroidNdkDir(),
        commandRunner.ansi,
        false /* isCodeCoverageEnabled */,
        false /* isDebugEnabled */,
        commandRunner.stdOut,
        commandRunner.stdErr);
  }

  protected Optional<AndroidPlatformTarget> findAndroidPlatformTarget(
      DependencyGraph dependencyGraph, PrintStream stdErr) {
    return Build.findAndroidPlatformTarget(dependencyGraph, findAndroidSdkDir(), stdErr);
  }
}
