// Copyright 2016 The Vanadium Authors. 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';
import 'dart:math';
import 'dart:io';

import '../mobile/device.dart';
import '../mobile/device_spec.dart';
import '../globals.dart';
import '../util.dart';

Future<List<String>> getAndroidDeviceIDs() async {
  List<String> androidIDs = <String>[];
  Process process = await Process.start('adb', ['devices']);
  RegExp androidIDPattern = new RegExp(r'^(\S+)\s+device$');
  Stream lineStream = process.stdout
                             .transform(new Utf8Decoder())
                             .transform(new LineSplitter());
  await for (var line in lineStream) {
    Match androidIDMatcher = androidIDPattern.firstMatch(line.toString());
    if (androidIDMatcher != null) {
      String androidID = androidIDMatcher.group(1);
      androidIDs.add(androidID);
    }
  }
  return androidIDs;
}

const String lockProp = 'mHoldingWakeLockSuspendBlocker';

/// Check if the device is locked
Future<bool> _deviceIsLocked(Device device) async {
  Process process = await Process.start(
    'adb',
    ['-s', '${device.id}', 'shell', 'dumpsys', 'power']
  );
  bool isLocked;
  RegExp lockStatusPattern = new RegExp(lockProp + r'=(.*)');
  Stream lineStream = process.stdout
                             .transform(new Utf8Decoder())
                             .transform(new LineSplitter());
  await for (var line in lineStream) {
    Match lockMatcher = lockStatusPattern.firstMatch(line.toString());
    if (lockMatcher != null) {
      isLocked = lockMatcher.group(1) == 'false';
      break;
    }
  }

  process.stderr.drain();
  await process.exitCode;

  return isLocked;
}

/// Unlock devices if the device is locked
Future<int> unlockDevice(Device device) async {

  bool isLocked = await _deviceIsLocked(device);

  if (isLocked == null) {
    printError('adb error: cannot find device $lockProp property');
    return 1;
  }

  if (!isLocked) return 0;

  Process wakeUpAndUnlockProcess = await Process.start(
    'adb',
    ['-s', '${device.id}', 'shell', 'input', 'keyevent', 'KEYCODE_MENU']
  );
  wakeUpAndUnlockProcess.stdout.drain();
  wakeUpAndUnlockProcess.stderr.drain();

  return await wakeUpAndUnlockProcess.exitCode;
}

// Uninstall an Android app
Future<int> uninstallAndroidTestedApp(DeviceSpec spec, Device device) async {
  String androidManifestPath
    = normalizePath(spec.appRootPath, 'android/AndroidManifest.xml');
  String androidManifest = await new File(androidManifestPath).readAsString();

  RegExp packagePattern
    = new RegExp(r'<manifest[\s\S]*?package="(\S+)"\s+[\s\S]*?>', multiLine: true);
  Match packageMatcher = packagePattern.firstMatch(androidManifest);
  if (packageMatcher == null) {
    printError('Package name not found in $androidManifestPath');
    return 1;
  }
  String packageName = packageMatcher.group(1);

  Process uninstallProcess = await Process.start(
    'adb',
    ['-s', '${device.id}', 'uninstall', '$packageName']
  );

  Stream lineStream = uninstallProcess.stdout
                       .transform(new Utf8Decoder())
                       .transform(new LineSplitter());
  await for (var line in lineStream) {
    printTrace(
      'Uninstall $packageName on device ${device.id}: ${line.toString().trim()}'
    );
  }

  uninstallProcess.stderr.drain();
  return uninstallProcess.exitCode;
}

/// Get device property
Future<String> getAndroidProperty(String deviceID, String propName) async {
  ProcessResult results = await Process.run(
    'adb',
    ['-s', deviceID, 'shell', 'getprop', propName]
  );
  return results.stdout.toString().trim();
}

/// Get device pixels and dpi to compute screen diagonal size in inches
Future<String> getAndroidScreenSize(String deviceID) async {
  Process sizeProcess = await Process.start(
    'adb',
    ['-s', '$deviceID', 'shell', 'wm', 'size']
  );
  RegExp sizePattern = new RegExp(r'Physical size:\s*(\d+)x(\d+)');
  Stream sizeLineStream = sizeProcess.stdout
                                     .transform(new Utf8Decoder())
                                    .transform(new LineSplitter());
  int xSize;
  int ySize;
  await for (var line in sizeLineStream) {
    Match sizeMatcher = sizePattern.firstMatch(line.toString());
    if (sizeMatcher != null) {
      xSize = int.parse(sizeMatcher.group(1));
      ySize = int.parse(sizeMatcher.group(2));
      break;
    }
  }

  if (xSize == null || ySize == null) {
    printError('Screen size not found.');
    return null;
  }

  sizeProcess.stderr.drain();

  Process densityProcess = await Process.start(
    'adb',
    ['-s', '$deviceID', 'shell', 'wm', 'density']
  );
  RegExp densityPattern = new RegExp(r'Physical density:\s*(\d+)');
  Stream densityLineStream = densityProcess.stdout
                                           .transform(new Utf8Decoder())
                                           .transform(new LineSplitter());
  int density;
  await for (var line in densityLineStream) {
    Match densityMatcher = densityPattern.firstMatch(line.toString());
    if (densityMatcher != null) {
      density = int.parse(densityMatcher.group(1));
      break;
    }
  }

  if (density == null) {
    printError('Density not found.');
    return null;
  }

  densityProcess.stderr.drain();

  double xInch = xSize / density;
  double yInch = ySize / density;
  double diagonalSize = sqrt(xInch * xInch + yInch * yInch);

  return categorizeScreenSize(diagonalSize);
}

Future<Device> collectAndroidDeviceProps(String deviceID, {String groupKey}) async {
  return new Device(
    properties: <String, String> {
      'platform': 'android',
      'device-id': deviceID,
      'model-name': await getAndroidProperty(deviceID, 'ro.product.model'),
      'os-version': expandOSVersion(
        await getAndroidProperty(deviceID, 'ro.build.version.release')
      ),
      'screen-size': await getAndroidScreenSize(deviceID)
    },
    groupKey: groupKey
  );
}
