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

import static org.junit.Assert.assertTrue;

import com.facebook.buck.android.DxStep.Option;
import com.facebook.buck.cli.VerbosityParser;
import com.facebook.buck.step.ExecutionContext;
import com.facebook.buck.step.Step;
import com.facebook.buck.step.TestExecutionContext;
import com.facebook.buck.testutil.MoreAsserts;
import com.facebook.buck.testutil.TestConsole;
import com.facebook.buck.util.AndroidPlatformTarget;
import com.facebook.buck.util.Verbosity;
import com.google.common.base.Function;
import com.google.common.base.Joiner;
import com.google.common.base.Optional;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableSet;
import com.google.common.collect.Iterables;

import org.easymock.EasyMock;
import org.easymock.EasyMockSupport;
import org.junit.Before;
import org.junit.Test;

import java.io.File;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.EnumSet;

public class DxStepTest extends EasyMockSupport {

  private static final String EXPECTED_DX_PREFIX =
      "/usr/bin/dx" +
          " --dex";

  private static Path SAMPLE_OUTPUT_PATH = Paths.get("buck-out/gen/classes.dex");

  private static ImmutableSet<Path> SAMPLE_FILES_TO_DEX = ImmutableSet.of(
      Paths.get("buck-out/gen/foo.dex.jar"),
      Paths.get("buck-out/gen/bar.dex.jar"));

  private Optional<AndroidPlatformTarget> androidPlatformTargetOptional;

  @Before
  public void setUp() {
    AndroidPlatformTarget androidPlatformTarget = createMock(AndroidPlatformTarget.class);
    EasyMock.expect(androidPlatformTarget.getDxExecutable()).andReturn(new File("/usr/bin/dx"));
    androidPlatformTargetOptional = Optional.of(androidPlatformTarget);
    replayAll();
  }

  @Test
  public void testDxCommandNoOptimizeNoJumbo() {
    // Context with --verbose 2.
    ExecutionContext context = createExecutionContext(2);
    Function<Path, Path> pathAbsolutifier = context.getProjectFilesystem().getAbsolutifier();

    DxStep dx = new DxStep(SAMPLE_OUTPUT_PATH.toString(),
        SAMPLE_FILES_TO_DEX,
        EnumSet.of(Option.NO_OPTIMIZE));

    String expected = String.format("%s --no-optimize --output %s %s",
        EXPECTED_DX_PREFIX,
        SAMPLE_OUTPUT_PATH,
        Joiner.on(' ').join(Iterables.transform(SAMPLE_FILES_TO_DEX, pathAbsolutifier)));
    MoreAsserts.assertShellCommands(
        "--no-optimize should be present, but --force-jumbo should not.",
        ImmutableList.of(expected),
        ImmutableList.<Step>of(dx),
        context);
    verifyAll();
  }

  @Test
  public void testDxCommandOptimizeNoJumbo() {
    // Context with --verbose 2.
    ExecutionContext context = createExecutionContext(2);
    Function<Path, Path> pathAbsolutifier = context.getProjectFilesystem().getAbsolutifier();

    DxStep dx = new DxStep(SAMPLE_OUTPUT_PATH.toString(), SAMPLE_FILES_TO_DEX);

    String expected = String.format("%s --output %s %s",
        EXPECTED_DX_PREFIX,
        SAMPLE_OUTPUT_PATH,
        Joiner.on(' ').join(Iterables.transform(SAMPLE_FILES_TO_DEX, pathAbsolutifier)));
    MoreAsserts.assertShellCommands(
        "Neither --no-optimize nor --force-jumbo should be present.",
        ImmutableList.of(expected),
        ImmutableList.<Step>of(dx),
        context);
    verifyAll();
  }

  @Test
  public void testDxCommandNoOptimizeForceJumbo() {
    // Context with --verbose 2.
    ExecutionContext context = createExecutionContext(2);
    Function<Path, Path> pathAbsolutifier = context.getProjectFilesystem().getAbsolutifier();

    DxStep dx = new DxStep(SAMPLE_OUTPUT_PATH.toString(),
        SAMPLE_FILES_TO_DEX,
        EnumSet.of(DxStep.Option.NO_OPTIMIZE, DxStep.Option.FORCE_JUMBO));

    String expected = String.format(
        "%s --no-optimize --force-jumbo --output %s %s",
        EXPECTED_DX_PREFIX,
        SAMPLE_OUTPUT_PATH,
        Joiner.on(' ').join(Iterables.transform(SAMPLE_FILES_TO_DEX, pathAbsolutifier)));
    MoreAsserts.assertShellCommands(
        "Both --no-optimize and --force-jumbo should be present.",
        ImmutableList.of(expected),
        ImmutableList.<Step>of(dx),
        context);
    verifyAll();
  }

  @Test
  public void testVerbose3AddsStatisticsFlag() {
    // Context with --verbose 3.
    ExecutionContext context = createExecutionContext(3);
    Function<Path, Path> pathAbsolutifier = context.getProjectFilesystem().getAbsolutifier();

    DxStep dx = new DxStep(SAMPLE_OUTPUT_PATH.toString(), SAMPLE_FILES_TO_DEX);

    String expected = String.format("%s --statistics --output %s %s",
        EXPECTED_DX_PREFIX,
        SAMPLE_OUTPUT_PATH,
        Joiner.on(' ').join(Iterables.transform(SAMPLE_FILES_TO_DEX, pathAbsolutifier)));
    MoreAsserts.assertShellCommands(
        "Ensure that the --statistics flag is present.",
        ImmutableList.of(expected),
        ImmutableList.<Step>of(dx),
        context);

    assertTrue("Should print stdout to show statistics.",
        dx.shouldPrintStdout(context.getVerbosity()));
    assertTrue("Should print stderr to show statistics.",
        dx.shouldPrintStderr(context.getVerbosity()));
    verifyAll();
  }

  @Test
  public void testVerbose10AddsVerboseFlagToDx() {
    // Context with --verbose 10.
    ExecutionContext context = createExecutionContext(10);
    Function<Path, Path> pathAbsolutifier = context.getProjectFilesystem().getAbsolutifier();

    DxStep dx = new DxStep(SAMPLE_OUTPUT_PATH.toString(), SAMPLE_FILES_TO_DEX);

    String expected = String.format(
        "%s --statistics --verbose --output %s %s",
        EXPECTED_DX_PREFIX,
        SAMPLE_OUTPUT_PATH,
        Joiner.on(' ').join(Iterables.transform(SAMPLE_FILES_TO_DEX, pathAbsolutifier)));
    MoreAsserts.assertShellCommands(
        "Ensure that the --statistics flag is present.",
        ImmutableList.of(expected),
        ImmutableList.<Step>of(dx),
        context);

    assertTrue("Should print stdout since `dx --verbose` is enabled.",
        dx.shouldPrintStdout(context.getVerbosity()));
    assertTrue("Should print stdout since `dx --verbose` is enabled.",
        dx.shouldPrintStderr(context.getVerbosity()));
    verifyAll();
}

  private ExecutionContext createExecutionContext(int verbosityLevel) {
    TestConsole console = new TestConsole();
    Verbosity verbosity = VerbosityParser.getVerbosityForLevel(verbosityLevel);
    console.setVerbosity(verbosity);
    return TestExecutionContext.newBuilder()
        .setConsole(console)
        .setAndroidPlatformTarget(androidPlatformTargetOptional)
        .build();
  }
}
