// Copyright (c) 2017, the R8 project authors. Please see the AUTHORS file
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
package com.android.tools.r8;

import com.android.tools.r8.utils.StringUtils;
import com.google.common.base.Joiner;

import com.android.ddmlib.AdbCommandRejectedException;
import com.android.ddmlib.AndroidDebugBridge;
import com.android.ddmlib.FileListingService;
import com.android.ddmlib.IDevice;
import com.android.ddmlib.IShellOutputReceiver;
import com.android.ddmlib.ShellCommandUnresponsiveException;
import com.android.ddmlib.SyncException;
import com.android.ddmlib.TimeoutException;

import java.io.BufferedReader;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.IOException;
import java.io.OutputStream;
import java.io.PrintStream;
import java.nio.file.Path;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

/**
 * This class is used to run tests on devices (or emulators)
 * using ddmlib.
 */
public class DeviceRunner {

  private static final boolean VERBOSE = false;
  private static final long ADB_CONNECTION_TIMEOUT = 5000;
  private static final long ADB_WAIT_STEP = ADB_CONNECTION_TIMEOUT / 10;
  private static final String TEST_SCRIPT_NAME = "test-exit-status.sh";
  private static final File TEST_SCRIPT_FILE =
      new File(System.getProperty("user.dir"), "scripts/" + TEST_SCRIPT_NAME);
  private static final char PATH_SEPARATOR_CHAR = ':';
  private static final String RUNTIME_NAME = "ART";

  private List<String> vmOptions = Collections.emptyList();
  private Map<String, String> systemProperties = Collections.emptyMap();
  private List<File> classpath = Collections.emptyList();
  private List<File> bootClasspath = Collections.emptyList();
  private String mainClass;
  private List<String> programArguments = Collections.emptyList();
  private OutputStream outRedirectStream = new ByteArrayOutputStream();

  private ShellOutputReceiver hostOutput = new ShellOutputReceiver();

  public static class DeviceRunnerConfigurationException extends Exception {

    public DeviceRunnerConfigurationException(String message) {
      super(message);
    }
  }

  private static class ShellOutputReceiver implements IShellOutputReceiver {

    private final PrintStream out;

    public ShellOutputReceiver() {
      this.out = System.out;
    }

    public ShellOutputReceiver(OutputStream out) {
      this.out = new PrintStream(out);
    }

    @Override
    public void addOutput(byte[] data, int offset, int length) {
      out.print(new String(Arrays.copyOfRange(data, offset, offset + length)));
    }

    @Override
    public void flush() {
    }

    @Override
    public boolean isCancelled() {
      return false;
    }
  }

  private static class ShellOutputToStringReceiver implements IShellOutputReceiver {

    StringBuffer outBuffer = new StringBuffer();

    @Override
    public void addOutput(byte[] data, int offset, int length) {
      outBuffer.append(new String(Arrays.copyOfRange(data, offset, offset + length)));
    }

    @Override
    public void flush() {
    }

    @Override
    public boolean isCancelled() {
      return false;
    }

    public String getOutput() {
      return outBuffer.toString();
    }
  }

  public DeviceRunner() {
    try {
      AndroidDebugBridge.init(/* clientSupport */ false);
    } catch (IllegalStateException ex) {
      // ADB was already initialized, we're fine, so just ignore.
    }
  }

  public DeviceRunner setVmOptions(List<String> vmOptions) {
    this.vmOptions = vmOptions;
    return this;
  }

  public DeviceRunner setSystemProperties(Map<String, String> systemProperties) {
    this.systemProperties = systemProperties;
    return this;
  }

  public DeviceRunner setClasspath(List<File> classpath) {
    this.classpath = classpath;
    return this;
  }

  public DeviceRunner setBootClasspath(List<File> bootClasspath) {
    this.bootClasspath = bootClasspath;
    return this;
  }

  public DeviceRunner setMainClass(String mainClass) {
    this.mainClass = mainClass;
    return this;
  }

  public DeviceRunner setProgramArguments(List<String> programArguments) {
    this.programArguments = programArguments;
    return this;
  }

  public DeviceRunner setOutputStream(OutputStream outputStream) {
    outRedirectStream = outputStream;
    return this;
  }

  public ToolHelper.ProcessResult run() throws DeviceRunnerConfigurationException, IOException {

    AndroidDebugBridge adb = initializeAdb();

    IDevice[] connectedDevices = adb.getDevices();
    if (connectedDevices.length == 0) {
      throw new DeviceRunnerConfigurationException("No device found");
    }

    if (connectedDevices.length != 1) {
      throw new DeviceRunnerConfigurationException(
          "Running tests on more than one device is not yet supported. "
              + "Currently connected devices: ["
              + StringUtils.join(Arrays.asList(connectedDevices), ",") + "]");
    }

    int exitStatus = -1;
    String uuid = java.util.UUID.randomUUID().toString();
    IDevice device = connectedDevices[0];
    try {
      checkDeviceRuntime(device);

      log("Running on device: " + device.getName());

      ensureAdbRoot(device);

      // Remove trailing '\n' returned by emulator
      File testsRootDirFile = new File(device.getMountPoint(IDevice.MNT_DATA).replace("\n", ""),
          "r8-tests-" + uuid);
      String testsRootDir = convertToTargetPath(testsRootDirFile);

      String testScriptPathOnTarget = convertToTargetPath(
          new File(testsRootDirFile, TEST_SCRIPT_NAME));

      ClasspathPair destFilePaths = installTestFiles(device, testsRootDirFile,
          testScriptPathOnTarget);

      File rootDir = new File(device.getMountPoint(IDevice.MNT_ROOT).replace("\n", ""));

      // Bug : exit code return by adb shell is wrong (always 0)
      // https://code.google.com/p/android/issues/detail?id=3254
      // Use go team hack to work this around
      // https://code.google.com/p/go/source/browse/misc/arm/a
      executeShellCommand(testScriptPathOnTarget + ' ' + uuid + ' ' + Joiner.on(' ').join(
          buildCommandLine(rootDir, testsRootDir, destFilePaths.bootclasspath,
              destFilePaths.classpath)), device, new ShellOutputReceiver(outRedirectStream),
          /* maxTimeToOutputResponse = */10000);
      exitStatus = getExitStatus(device, testsRootDir);
      log("Exit status: " + exitStatus);

      if (exitStatus != 0) {
        System.err.println("Execution failed on device '" + device.getName() + "'");
      }

    } catch (IOException t) {
      System.err.println("Error with device '" + device.getName() + "': " + t.getMessage());
      t.printStackTrace();
      throw t;
    } finally {
      deleteTestFiles(device, uuid);
    }

    // Convert target line separator to whatever host is for output comparison-based tests
    String outputAsString = outRedirectStream.toString()
        .replace("\n", ToolHelper.LINE_SEPARATOR);

    return new ToolHelper.ProcessResult(exitStatus, outputAsString, "");
  }

  private AndroidDebugBridge initializeAdb() throws DeviceRunnerConfigurationException {
    AndroidDebugBridge adb = AndroidDebugBridge.createBridge(getAdbLocation(), false);

    long start = System.currentTimeMillis();

    log("Initializing adb...");

    while (!isAdbInitialized(adb)) {
      long timeLeft = start + ADB_CONNECTION_TIMEOUT - System.currentTimeMillis();
      if (timeLeft <= 0) {
        break;
      }
      try {
        Thread.sleep(ADB_WAIT_STEP);
      } catch (InterruptedException e) {
        Thread.currentThread().interrupt();
        throw new AssertionError(e);
      }
    }

    if (!isAdbInitialized(adb)) {
      String userDefinedPathToSdk = System.getProperty("ANDROID_SDK_HOME");
      if (userDefinedPathToSdk != null) {
        throw new DeviceRunnerConfigurationException(
            "Adb not found. Check SDK location '"
                + userDefinedPathToSdk
                + "'");
      } else {
        throw new DeviceRunnerConfigurationException(
            "Adb not found. Set either PATH or ANDROID_SDK_HOME environment variable");
      }
    }

    log("Done");
    return adb;
  }

  private static class ClasspathPair {
    public String[] bootclasspath;
    public String[] classpath;

    ClasspathPair(String[] bootclasspath, String[] classpath) {
      this.bootclasspath = bootclasspath;
      this.classpath = classpath;
    }
  }

  /**
   * @return path of classpath and bootclasspath files on device
   */
  private ClasspathPair installTestFiles(IDevice device, File testsRootDirFile,
      String testScriptPathOnTarget) throws IOException {

    String testsRootDir = convertToTargetPath(testsRootDirFile);

    String[] desFilePaths = new String[classpath.size()];
    String[] destFileBootCpPaths = new String[bootClasspath.size()];

    executeShellCommand("mkdir " + testsRootDir, device);
    executeShellCommand(
        "rm " + testsRootDir + FileListingService.FILE_SEPARATOR + "*", device);
    executePushCommand(TEST_SCRIPT_FILE.getAbsolutePath(), testScriptPathOnTarget, device);
    executeShellCommand("chmod 777 " + testScriptPathOnTarget, device);

    int i = 0;
    for (File f : bootClasspath) {
      destFileBootCpPaths[i] = convertToTargetPath(
          new File(testsRootDirFile, "f" + i + "_" + f.getName()));
      executePushCommand(f.getAbsolutePath(), destFileBootCpPaths[i], device);
      i++;
    }
    i = 0;
    for (File f : classpath) {
      desFilePaths[i] = convertToTargetPath(
          new File(testsRootDirFile, "f" + i + "_" + f.getName()));
      executePushCommand(f.getAbsolutePath(), desFilePaths[i], device);
      i++;
    }
    return new ClasspathPair(destFileBootCpPaths, desFilePaths);
  }

  private int getExitStatus(IDevice device, String testsRootDir) throws IOException {
    File exitStatusFile = createTempFile("exitStatus", "");
    executePullCommand(
        testsRootDir + "/exitStatus", exitStatusFile.getAbsolutePath(), device);

    try (BufferedReader br = new BufferedReader(new FileReader(exitStatusFile))) {
      String readLine = br.readLine();
      if (readLine == null) {
        throw new FileNotFoundException("Exit status not found at " + exitStatusFile.getPath());
      }
      return Integer.parseInt(readLine);
    }
  }

  private void executeShellCommand(
      String command,
      IDevice device,
      ShellOutputReceiver hostOutput,
      int maxTimeToOutputResponse) throws IOException {
    log("adb -s " + device.getSerialNumber() + " shell " + command);
    try {
      if (maxTimeToOutputResponse != -1) {
        device.executeShellCommand(command, hostOutput, maxTimeToOutputResponse);
      } else {
        device.executeShellCommand(command, hostOutput);
      }
    } catch (IOException
        | ShellCommandUnresponsiveException
        | TimeoutException
        | AdbCommandRejectedException e) {
      throw new IOException(
          "Failed to execute shell command: '" + command + "'", e);
    }
  }

  private void executeShellCommand(String command, IDevice device)
      throws IOException {
    executeShellCommand(command, device, hostOutput, -1);
  }

  private void executePushCommand(
      String srcFile, String destFile, IDevice device) throws IOException {
    log("adb -s " + device.getSerialNumber() + " push " + srcFile + " " + destFile);
    try {
      device.pushFile(srcFile, destFile);
    } catch (IOException | AdbCommandRejectedException | TimeoutException | SyncException e) {
      throw new IOException(
          "Unable to push file '" + srcFile + "' on device into '" + destFile + "'", e);
    }
  }

  private void executePullCommand(
      String srcFile, String destFile, IDevice device) throws IOException {
    log("adb -s " + device.getSerialNumber() + " pull " + srcFile + " " + destFile);
    try {
      device.pullFile(srcFile, destFile);
    } catch (IOException | AdbCommandRejectedException | TimeoutException | SyncException e) {
      throw new IOException(
          "Unable to pull file '" + srcFile + "' from device into '" + destFile + "'", e);
    }
  }

  private boolean isAdbInitialized(AndroidDebugBridge adb) {
    return adb.isConnected() && adb.hasInitialDeviceList();
  }

  private String getAdbLocation() {
    String adbLocation = "adb";
    String userSpecifiedSdkLocation = System.getenv("ANDROID_SDK_HOME");
    if (userSpecifiedSdkLocation != null) {
      adbLocation =
          userSpecifiedSdkLocation
              + File.separatorChar
              + "platform-tools"
              + File.separatorChar
              + "adb";
    }
    return adbLocation;
  }


  private void ensureAdbRoot(IDevice device) throws IOException {
    boolean isRoot;
    try {
      isRoot = device.isRoot();
    } catch (TimeoutException
        | AdbCommandRejectedException
        | IOException
        | ShellCommandUnresponsiveException e) {
      throw new IOException(
          "Cannot fetch root status for device '"
              + device.getName()
              + "("
              + device.getSerialNumber()
              + ")"
              + "': "
              + e.getMessage(),
          e);
    }

    int numberOfTries = 0;
    while (!isRoot && numberOfTries < 5) {
      try {
        isRoot = device.root();
      } catch (TimeoutException
          | AdbCommandRejectedException
          | IOException
          | ShellCommandUnresponsiveException e1) {
        // root() seems to throw an IOException: EOF, and it tends
        // to make the subsequent call to isRoot() fail with
        // AdbCommandRejectedException: device offline, until adbd is
        // restarted as root.
      } finally {
        try {
          Thread.sleep(1000);
        } catch (InterruptedException e1) {
          Thread.currentThread().interrupt();
        }
      }
      numberOfTries++;
    }

    if (!isRoot) {
      throw new IOException(
          "Cannot switch to root on device '"
              + device.getName()
              + "("
              + device.getSerialNumber()
              + ")"
              + "'");
    }
  }

  private void checkDeviceRuntime(IDevice device)
      throws DeviceRunnerConfigurationException, IOException {
    ShellOutputToStringReceiver outputToString = new ShellOutputToStringReceiver();
    try {
      device.executeShellCommand("dalvikvm -showversion", outputToString);
      if (!outputToString.getOutput().contains(RUNTIME_NAME)) {
        throw new DeviceRunnerConfigurationException(
            "The plugged device does not run the required runtime: '" + RUNTIME_NAME + "'");
      }
    } catch (TimeoutException
        | AdbCommandRejectedException
        | ShellCommandUnresponsiveException
        | IOException e) {
      throw new IOException("Could not check device runtime", e);
    }
  }

  private String convertToTargetPath(File file) {
    String path = file.getPath();
    Path root = file.toPath().getRoot();
    if (root != null) {
      path = path.replace(root.toString(), FileListingService.FILE_SEPARATOR);
    }
    return path.replace(File.separator, FileListingService.FILE_SEPARATOR);
  }

  private static File createTempFile(String prefix, String suffix) throws IOException {
    File tmp = File.createTempFile("r8-tests-" + prefix, suffix);
    tmp.deleteOnExit();
    return tmp;
  }

  private void deleteTestFiles(IDevice device, String uuid) throws IOException {
    String deleteCommand = "find data -name '*r8-tests-" + uuid + "*' -exec rm -rf {} +";
    log("adb -s " + device.getSerialNumber() + " shell " + deleteCommand);
    try {
      device.executeShellCommand(deleteCommand, hostOutput);
    } catch (TimeoutException
        | AdbCommandRejectedException
        | ShellCommandUnresponsiveException
        | IOException e) {
      throw new IOException("Error while deleting test file on device", e);
    }
  }

  private List<String> buildCommandLine(File rootDir, String testRootDir,
      String[] bootClasspathFiles, String[] classpathFiles) {
    List<String> result = new ArrayList<>();

    result.add(convertToTargetPath(new File(rootDir, "/bin/dalvikvm")));

    for (String option : vmOptions) {
      result.add(option);
    }
    for (Map.Entry<String, String> entry : systemProperties.entrySet()) {
      StringBuilder builder = new StringBuilder("-D");
      builder.append(entry.getKey());
      builder.append("=");
      builder.append(entry.getValue());
      result.add(builder.toString());
    }

    if (classpathFiles.length > 0) {
      result.add("-cp");
      result.add(Joiner.on(PATH_SEPARATOR_CHAR).join(
          Arrays.asList(classpathFiles).stream()
              .map(filePath -> convertToTargetPath(new File(filePath)))
              .collect(Collectors.toList())));
    }
    if (bootClasspathFiles.length > 0) {
      result.add("-Xbootclasspath:" + Joiner.on(PATH_SEPARATOR_CHAR).join(
          Arrays.asList(bootClasspathFiles).stream()
              .map(filePath -> convertToTargetPath(new File(filePath)))
              .collect(Collectors.toList())));
    }

    if (mainClass != null) {
      result.add(mainClass);
    }
    for (String argument : programArguments) {
      result.add(argument);
    }
    return result;
  }

  private void log(String message) {
    if (VERBOSE) {
      System.out.println(message);
    }
  }
}
