// 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.
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 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);
      await process.stdin.flush();
    }
    process.stdin.close();

    Timer timer;
    bool timedOut = false;
    if (timeout != null) {
      timer = 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 AdbCommandResult(command, results[0] as String, results[1] as String,
        results[2] as int, 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 const _minPort = 5554;
  static const _maxPort = 5584;

  static int _nextPort = _minPort;

  static int next() {
    var port = _nextPort;
    if (port > _maxPort) throw 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 = AdbDevice('emulator-$portNumber');
      return AndroidEmulator._private(portNumber, adbDevice, process);
    });
  }

  AndroidEmulator._private(this._port, this._adbDevice, this._emulatorProcess) {
    Stream<String> getLines(Stream s) {
      return s.transform(utf8.decoder).transform(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 = Completer<bool>();
    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 = Duration(seconds: 3);
  String _deviceId;
  Map<String, String> _cachedData = {};

  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<Null> waitForBootCompleted() async {
    while (true) {
      try {
        AdbCommandResult result =
            await _adbCommand(['shell', 'getprop', 'sys.boot_completed']);
        if (result.stdout.trim() == '1') return;
      } catch (_) {}
      await Future<Null>.delayed(const Duration(seconds: 2));
    }
  }

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

  /// Download data from 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']);
  }

  /// Upload data to the device, unless [local] is the same as the most recently
  /// used source for [remote].
  Future<AdbCommandResult> pushCachedData(String local, String remote) {
    if (_cachedData[remote] == local) {
      return Future.value(
          AdbCommandResult("Skipped cached push", "", "", 0, false));
    }
    _cachedData[remote] = local;
    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) {
    return _adbCommand([
      'shell',
      'am',
      'start',
      '-W',
      '-a',
      intent.action,
      '-n',
      "${intent.package}/${intent.activity}",
      if (intent.dataUri != null) ...['-d', intent.dataUri]
    ]);
  }

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

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

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

  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 \$?"];
    var result = await _executeCommand("adb", _deviceSpecificArgs(args),
        timeout: timeout);
    var exitCode = result.exitCode;
    var lines = result.stdout
        .split('\n')
        .where((line) => line.trim().isNotEmpty)
        .toList();
    if (lines.isNotEmpty) {
      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.
        // TODO(mkroghj): Some times tests fail with the assert below. To better
        // investigate, write out debug info.
        DebugLogger.info("======= THIS IS DEBUG INFORMATION =======");
        DebugLogger.info("arguments: $args");
        DebugLogger.info("exitCode: ${result.exitCode}");
        DebugLogger.info("timedOut: ${result.timedOut}");
        DebugLogger.info("---- std out ----");
        DebugLogger.info(result.stdout);
        DebugLogger.info("---- std out end ----");
        DebugLogger.info("---- std error  ----");
        DebugLogger.info(result.stderr);
        DebugLogger.info("---- std error end ----");
        DebugLogger.info("======= THIS IS NO LONGER DEBUG INFORMATION =======");
        assert(result.exitCode != 0);
      }
    }
    return 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 =
      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 Exception("Could not list devices [stdout: ${result.stdout},"
            "stderr: ${result.stderr}]");
      }
      return _deviceLineRegexp
          .allMatches(result.stdout as String)
          .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 = Queue();
  final Queue<Completer<AdbDevice>> _waiter = Queue();

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

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

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

  void releaseDevice(AdbDevice device) {
    if (_waiter.isNotEmpty) {
      var completer = _waiter.removeFirst();
      completer.complete(device);
    } else {
      _idleDevices.add(device);
    }
  }
}
