/*
 * Copyright 2016 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.idea.blaze.android.run.test;

import com.android.ddmlib.IDevice;
import com.android.tools.idea.run.ConsolePrinter;
import com.android.tools.idea.run.tasks.LaunchTask;
import com.android.tools.idea.run.tasks.LaunchTaskDurations;
import com.android.tools.idea.run.util.LaunchStatus;
import com.android.tools.idea.run.util.ProcessHandlerLaunchStatus;
import com.google.common.util.concurrent.ListenableFuture;
import com.google.idea.blaze.base.async.executor.BlazeExecutor;
import com.google.idea.blaze.base.async.process.ExternalTask;
import com.google.idea.blaze.base.async.process.LineProcessingOutputStream;
import com.google.idea.blaze.base.command.BlazeCommand;
import com.google.idea.blaze.base.command.BlazeCommandName;
import com.google.idea.blaze.base.command.BlazeFlags;
import com.google.idea.blaze.base.filecache.FileCaches;
import com.google.idea.blaze.base.model.primitives.Label;
import com.google.idea.blaze.base.model.primitives.WorkspaceRoot;
import com.google.idea.blaze.base.projectview.ProjectViewManager;
import com.google.idea.blaze.base.projectview.ProjectViewSet;
import com.google.idea.blaze.base.scope.BlazeContext;
import com.google.idea.blaze.base.scope.Scope;
import com.google.idea.blaze.base.scope.ScopedFunction;
import com.google.idea.blaze.base.scope.output.IssueOutput;
import com.google.idea.blaze.base.settings.Blaze;
import com.google.idea.blaze.base.util.SaveUtil;
import com.intellij.execution.process.ProcessAdapter;
import com.intellij.execution.process.ProcessEvent;
import com.intellij.execution.process.ProcessHandler;
import com.intellij.openapi.diagnostic.Logger;
import com.intellij.openapi.project.Project;
import java.util.List;
import java.util.concurrent.Callable;
import java.util.concurrent.CancellationException;
import java.util.concurrent.ExecutionException;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.ide.PooledThreadExecutor;

/**
 * An Android application launcher that invokes `blaze test` on an android_test target, and sets up
 * process handling and debugging for the test run.
 */
class BlazeAndroidTestLaunchTask implements LaunchTask {
  // Uses a local device/emulator attached to adb to run an android_test.
  public static final String TEST_LOCAL_DEVICE =
      BlazeFlags.TEST_ARG + "--device_broker_type=LOCAL_ADB_SERVER";
  // Uses a local device/emulator attached to adb to run an android_test.
  public static final String TEST_DEBUG = BlazeFlags.TEST_ARG + "--enable_debug";
  // Specifies the serial number for a local test device.
  private static final String TEST_DEVICE_SERIAL = "--device_serial_number=";
  private static final Logger LOG = Logger.getInstance(BlazeAndroidTestLaunchTask.class);

  private final Project project;
  private final Label target;
  private final List<String> buildFlags;
  private final BlazeAndroidTestFilter testFilter;

  private ListenableFuture<Boolean> blazeResult;

  private final BlazeAndroidTestRunContext runContext;

  private final boolean debug;

  public BlazeAndroidTestLaunchTask(
      Project project,
      Label target,
      List<String> buildFlags,
      BlazeAndroidTestFilter testFilter,
      BlazeAndroidTestRunContext runContext,
      boolean debug) {
    this.project = project;
    this.target = target;
    this.buildFlags = buildFlags;
    this.testFilter = testFilter;
    this.runContext = runContext;
    this.debug = debug;
  }

  @NotNull
  @Override
  public String getDescription() {
    return String.format("Running %s tests", Blaze.buildSystemName(project));
  }

  @Override
  public int getDuration() {
    return LaunchTaskDurations.LAUNCH_ACTIVITY;
  }

  @Override
  public boolean perform(
      @NotNull IDevice device,
      @NotNull LaunchStatus launchStatus,
      @NotNull ConsolePrinter printer) {
    BlazeExecutor executor = BlazeExecutor.getInstance();

    ProcessHandlerLaunchStatus processHandlerLaunchStatus =
        (ProcessHandlerLaunchStatus) launchStatus;
    final ProcessHandler processHandler = processHandlerLaunchStatus.getProcessHandler();

    blazeResult =
        executor.submit(
            new Callable<Boolean>() {
              @Override
              public Boolean call() throws Exception {
                return Scope.root(
                    new ScopedFunction<Boolean>() {
                      @Override
                      public Boolean execute(@NotNull BlazeContext context) {
                        ProjectViewSet projectViewSet =
                            ProjectViewManager.getInstance(project).getProjectViewSet();
                        if (projectViewSet == null) {
                          IssueOutput.error("Could not load project view. Please resync project.")
                              .submit(context);
                          return false;
                        }

                        BlazeCommand.Builder commandBuilder =
                            BlazeCommand.builder(
                                    Blaze.getBuildSystem(project), BlazeCommandName.TEST)
                                .addTargets(target);
                        // Build flags must match BlazeBeforeRunTask.
                        commandBuilder.addBlazeFlags(buildFlags);
                        // Run the test on the selected local device/emulator.
                        commandBuilder
                            .addBlazeFlags(TEST_LOCAL_DEVICE, BlazeFlags.TEST_OUTPUT_STREAMED)
                            .addBlazeFlags(testDeviceSerialFlags(device.getSerialNumber()))
                            .addBlazeFlags(testFilter.getBlazeFlags());
                        if (debug) {
                          commandBuilder.addBlazeFlags(
                              TEST_DEBUG, BlazeFlags.NO_CACHE_TEST_RESULTS);
                        }
                        BlazeCommand command = commandBuilder.build();

                        printer.stdout(
                            String.format("Starting %s test...\n", Blaze.buildSystemName(project)));
                        printer.stdout(command + "\n");
                        LineProcessingOutputStream.LineProcessor stdoutLineProcessor =
                            line -> {
                              printer.stdout(line);
                              return true;
                            };
                        LineProcessingOutputStream.LineProcessor stderrLineProcessor =
                            line -> {
                              printer.stderr(line);
                              return true;
                            };
                        SaveUtil.saveAllFiles();
                        int retVal =
                            ExternalTask.builder(WorkspaceRoot.fromProject(project))
                                .addBlazeCommand(command)
                                .context(context)
                                .stdout(LineProcessingOutputStream.of(stdoutLineProcessor))
                                .stderr(LineProcessingOutputStream.of(stderrLineProcessor))
                                .build()
                                .run();
                        FileCaches.refresh(project);

                        if (retVal != 0) {
                          context.setHasError();
                        }

                        return !context.hasErrors();
                      }
                    });
              }
            });

    blazeResult.addListener(runContext::onLaunchTaskComplete, PooledThreadExecutor.INSTANCE);

    // The debug case is set up in ConnectBlazeTestDebuggerTask
    if (!debug) {
      waitAndSetUpForKillingBlazeOnStop(processHandler, launchStatus);
    }
    return true;
  }

  /**
   * Hooks up the Blaze process to be killed if the user hits the 'Stop' button, then waits for the
   * Blaze process to stop. In non-debug mode, we wait for test execution to finish before returning
   * from launch() (this matches the behavior of the stock ddmlib runner).
   */
  private void waitAndSetUpForKillingBlazeOnStop(
      @NotNull final ProcessHandler processHandler, @NotNull LaunchStatus launchStatus) {
    processHandler.addProcessListener(
        new ProcessAdapter() {
          @Override
          public void processWillTerminate(ProcessEvent event, boolean willBeDestroyed) {
            blazeResult.cancel(true /* mayInterruptIfRunning */);
            launchStatus.terminateLaunch("Test run stopped.\n");
          }
        });

    try {
      blazeResult.get();
      launchStatus.terminateLaunch("Tests ran to completion.\n");
    } catch (CancellationException e) {
      // The user has canceled the test.
      launchStatus.terminateLaunch("Test run stopped.\n");
    } catch (InterruptedException e) {
      // We've been interrupted - cancel the underlying Blaze process.
      blazeResult.cancel(true /* mayInterruptIfRunning */);
      launchStatus.terminateLaunch("Test run stopped.\n");
    } catch (ExecutionException e) {
      LOG.error(e);
      launchStatus.terminateLaunch(
          "Test run stopped due to internal exception. Please file a bug report.\n");
    }
  }

  @NotNull
  private static String testDeviceSerialFlags(@NotNull String serial) {
    return BlazeFlags.TEST_ARG + TEST_DEVICE_SERIAL + serial;
  }
}
