// Copyright (c) 2013, the Dart 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.

library android;

import "dart:async";
import "dart:convert" show LineSplitter, UTF8;
import "dart:core";
import "dart:collection";
import "dart:io";

import "path.dart";
import "utils.dart";

class AdbCommandResult {
  final String command;
  final String stdout;
  final String stderr;
  final int exitCode;
  final bool timedOut;

  AdbCommandResult(this.command, this.stdout, this.stderr, this.exitCode,
                   this.timedOut);

  void throwIfFailed() {
    if (exitCode != 0) {
      var error = "Running: $command failed:"
                  "stdout:\n  ${stdout.trim()}\n"
                  "stderr:\n  ${stderr.trim()}\n"
                  "exitCode: $exitCode\n"
                  "timedOut: $timedOut";
      throw new Exception(error);
    }
  }
}

/**
 * [_executeCommand] will write [stdin] to the standard input of the created
 * process and will return a tuple (stdout, stderr).
 *
 * If the exit code of the process was nonzero it will complete with an error.
 * If starting the process failed, it will complete with an error as well.
 */
Future<AdbCommandResult> _executeCommand(
    String executable, List<String> args,
    {String stdin, Duration timeout}) {
  Future<String> getOutput(Stream<List<int>> stream) {
    return stream
        .transform(UTF8.decoder)
        .toList()
        .then((data) => data.join(""));
  }

  return Process.start(executable, args).then((Process process) async {
    if (stdin != null && stdin != '') {
      process.stdin.write(stdin);
    }
    process.stdin.close();

    Timer timer;
    bool timedOut = false;
    if (timeout != null) {
      timer = new Timer(timeout, () {
        timedOut = true;
        process.kill(ProcessSignal.SIGTERM);
        timer = null;
      });
    }

    var results = await Future.wait([
        getOutput(process.stdout),
        getOutput(process.stderr),
        process.exitCode
    ]);
    if (timer != null) timer.cancel();

    String command = "$executable ${args.join(' ')}";
    return new AdbCommandResult(
        command, results[0], results[1], results[2], timedOut);
  });
}

/**
 * Helper class to loop through all adb ports.
 *
 * The ports come in pairs:
 *  - even number: console connection
 *  - odd number: adb connection
 * Note that this code doesn't check if the ports are used.
 */
class AdbServerPortPool {
  static int MIN_PORT = 5554;
  static int MAX_PORT = 5584;

  static int _nextPort = MIN_PORT;

  static int next() {
    var port = _nextPort;
    if (port > MAX_PORT) {
      throw new Exception("All ports are used.");
    }
    _nextPort += 2;
    return port;
  }
}

/**
 * Represents the interface to the emulator.
 * New emulators can be launched by calling the static [launchNewEmulator]
 * method.
 */
class AndroidEmulator {
  int _port;
  Process _emulatorProcess;
  AdbDevice _adbDevice;

  int get port => _port;

  AdbDevice get adbDevice => _adbDevice;

  static Future<AndroidEmulator> launchNewEmulator(String avdName) {
    var portNumber = AdbServerPortPool.next();
    var args = ['-avd', '$avdName', '-port', "$portNumber" /*, '-gpu', 'on'*/];
    return Process.start("emulator64-arm", args).then((Process process) {
      var adbDevice = new AdbDevice('emulator-$portNumber');
      return new AndroidEmulator._private(portNumber, adbDevice, process);
    });
  }

  AndroidEmulator._private(this._port, this._adbDevice, this._emulatorProcess) {
    Stream<String> getLines(Stream s) {
      return s.transform(UTF8.decoder).transform(new LineSplitter());
    }

    getLines(_emulatorProcess.stdout).listen((line) {
      log("stdout: ${line.trim()}");
    });
    getLines(_emulatorProcess.stderr).listen((line) {
      log("stderr: ${line.trim()}");
    });
    _emulatorProcess.exitCode.then((exitCode) {
      log("emulator exited with exitCode: $exitCode.");
    });
  }

  Future<bool> kill() {
    var completer = new Completer();
    if (_emulatorProcess.kill()) {
      _emulatorProcess.exitCode.then((exitCode) {
        // TODO: Should we use exitCode to do something clever?
        completer.complete(true);
      });
    } else {
      log("Sending kill signal to emulator process failed");
      completer.complete(false);
    }
    return completer.future;
  }

  void log(String msg) {
    DebugLogger.info("AndroidEmulator(${_adbDevice.deviceId}): $msg");
  }
}

/**
 * Helper class to create avd device configurations.
 */
class AndroidHelper {
  static Future createAvd(String name, String target) async {
    var args = [
      '--silent',
      'create',
      'avd',
      '--name',
      '$name',
      '--target',
      '$target',
      '--force',
      '--abi',
      'armeabi-v7a'
    ];
    // We're adding newlines to stdin to simulate <enter>.
    var result = await _executeCommand("android", args, stdin: "\n\n\n\n");
    result.throwIfFailed();
  }
}

/**
 * Used for communicating with an emulator or with a real device.
 */
class AdbDevice {
  static const _adbServerStartupTime = const Duration(seconds: 3);
  String _deviceId;

  String get deviceId => _deviceId;

  AdbDevice(this._deviceId);

  /**
   * Blocks execution until the device is online
   */
  Future waitForDevice() {
    return _adbCommand(['wait-for-device']);
  }

  /**
   * Polls the 'sys.boot_completed' property. Returns as soon as the property is
   * 1.
   */
  Future waitForBootCompleted() async {
    while (true) {
      try {
        AdbCommandResult result =
            await _adbCommand(['shell', 'getprop', 'sys.boot_completed']);
        if (result.stdout.trim() == '1') return;
      } catch (_) { }
      await new Future.delayed(const Duration(seconds: 2));
    }
  }

  /**
   * Put adb in root mode.
   */
  Future adbRoot() {
    var adbRootCompleter = new Completer();
    _adbCommand(['root']).then((_) {
      // TODO: Figure out a way to wait until the adb daemon was restarted in
      // 'root mode' on the device.
      new Timer(_adbServerStartupTime, () => adbRootCompleter.complete(true));
    }).catchError((error) => adbRootCompleter.completeError(error));
    return adbRootCompleter.future;
  }

  /**
   * Download data form the device.
   */
  Future pullData(Path remote, Path local) {
    return _adbCommand(['pull', '$remote', '$local']);
  }

  /**
   * Upload data to the device.
   */
  Future pushData(Path local, Path remote) {
    return _adbCommand(['push', '$local', '$remote']);
  }

  /**
   * Change permission of directory recursively.
   */
  Future chmod(String mode, Path directory) {
    var arguments = ['shell', 'chmod', '-R', mode, '$directory'];
    return _adbCommand(arguments);
  }

  /**
   * Install an application on the device.
   */
  Future installApk(Path filename) {
    return _adbCommand(
        ['install', '-i', 'com.google.android.feedback', '-r', '$filename']);
  }

  /**
   * Start the given intent on the device.
   */
  Future startActivity(Intent intent) {
    var arguments = [
      'shell',
      'am',
      'start',
      '-W',
      '-a',
      intent.action,
      '-n',
      "${intent.package}/${intent.activity}"
    ];
    if (intent.dataUri != null) {
      arguments.addAll(['-d', intent.dataUri]);
    }
    return _adbCommand(arguments);
  }

  /**
   * Force to stop everything associated with [package].
   */
  Future forceStop(String package) {
    var arguments = ['shell', 'am', 'force-stop', package];
    return _adbCommand(arguments);
  }

  /**
   * Set system property name to value.
   */
  Future setProp(String name, String value) {
    return _adbCommand(['shell', 'setprop', name, value]);
  }

  /**
   * Kill all background processes.
   */
  Future killAll() {
    var arguments = ['shell', 'am', 'kill-all'];
    return _adbCommand(arguments);
  }

  Future<AdbCommandResult> runAdbCommand(List<String> adbArgs,
                                         {Duration timeout}) {
    return _executeCommand(
        "adb", _deviceSpecificArgs(adbArgs), timeout: timeout);
  }

  Future<AdbCommandResult> runAdbShellCommand(List<String> shellArgs,
                                              {Duration timeout}) async {
    const MARKER = 'AdbShellExitCode: ';

    // The exitcode of 'adb shell ...' can be 0 even though the command failed
    // with a non-zero exit code. We therefore explicitly print it to stdout and
    // search for it.

    var args = ['shell',
                "${shellArgs.join(' ')} ; echo $MARKER \$?"];
    AdbCommandResult result = await _executeCommand(
        "adb", _deviceSpecificArgs(args), timeout: timeout);
    int exitCode = result.exitCode;
    var lines = result
        .stdout.split('\n')
        .where((line) => line.trim().length > 0)
        .toList();
    if (lines.length > 0) {
      int index = lines.last.indexOf(MARKER);
      if (index >= 0) {
        exitCode = int.parse(
            lines.last.substring(index + MARKER.length).trim());
        if (exitCode > 128 && exitCode <= 128 + 31) {
          // Return negative exit codes for signals 1..31 (128+N for signal N)
          exitCode = 128 - exitCode;
        }
      } else {
        // In case of timeouts, for example, we won't get the exitcode marker.
        assert(result.exitCode != 0);
      }
    }
    return new AdbCommandResult(
        result.command, result.stdout, result.stderr, exitCode,
        result.timedOut);
  }

  Future<AdbCommandResult> _adbCommand(List<String> adbArgs) async {
    var result = await _executeCommand("adb", _deviceSpecificArgs(adbArgs));
    result.throwIfFailed();
    return result;
  }

  List<String> _deviceSpecificArgs(List<String> adbArgs) {
    if (_deviceId != null) {
      var extendedAdbArgs = ['-s', _deviceId];
      extendedAdbArgs.addAll(adbArgs);
      adbArgs = extendedAdbArgs;
    }
    return adbArgs;
  }
}

/**
 * Helper to list all adb devices available.
 */
class AdbHelper {
  static RegExp _deviceLineRegexp =
      new RegExp(r'^([a-zA-Z0-9_-]+)[ \t]+device$', multiLine: true);

  static Future<List<String>> listDevices() {
    return Process.run('adb', ['devices']).then((ProcessResult result) {
      if (result.exitCode != 0) {
        throw new Exception("Could not list devices [stdout: ${result.stdout},"
            "stderr: ${result.stderr}]");
      }
      return _deviceLineRegexp
          .allMatches(result.stdout)
          .map((Match m) => m.group(1))
          .toList();
    });
  }
}

/**
 * Represents an android intent.
 */
class Intent {
  String action;
  String package;
  String activity;
  String dataUri;

  Intent(this.action, this.package, this.activity, [this.dataUri]);
}

/**
 * Discovers all available devices and supports acquire/release.
 */
class AdbDevicePool {
  final Queue<AdbDevice> _idleDevices = new Queue<AdbDevice>();
  final Queue<Completer> _waiter = new Queue<Completer>();

  AdbDevicePool(List<AdbDevice> idleDevices) {
    _idleDevices.addAll(idleDevices);
  }

  static Future<AdbDevicePool> create() async {
    var names = await AdbHelper.listDevices();
    var devices = names.map((id) => new AdbDevice(id)).toList();
    if (devices.length == 0) {
      throw new Exception(
          'No android devices found. '
          'Please make sure "adb devices" shows your device!');
    }
    return new AdbDevicePool(devices);
  }

  Future<AdbDevice> acquireDevice() async {
    if (_idleDevices.length > 0) {
      return _idleDevices.removeFirst();
    } else {
      var completer = new Completer();
      _waiter.add(completer);
      return completer.future;
    }
  }

  void releaseDevice(AdbDevice device) {
    if (_waiter.length > 0) {
      Completer completer = _waiter.removeFirst();
      completer.complete(device);
    } else {
      _idleDevices.add(device);
    }
  }
}
