// Copyright 2016 The Flutter 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' show LineSplitter;
import 'dart:io';

import 'package:meta/meta.dart';

import 'utils.dart';

/// The root of the API for controlling devices.
DeviceDiscovery get devices => DeviceDiscovery();

/// Operating system on the devices that this agent is configured to test.
enum HostType { vm, physical }

/// Operating system on the devices that this agent is configured to test.
enum DeviceOperatingSystem { android, ios, none }

/// Discovers available devices and chooses one to work with.
abstract class DeviceDiscovery {
  factory DeviceDiscovery() {
    switch (config.deviceOperatingSystem) {
      case DeviceOperatingSystem.android:
        return AndroidDeviceDiscovery();
      case DeviceOperatingSystem.ios:
        return IosDeviceDiscovery();
      case DeviceOperatingSystem.none:
        return NoOpDeviceDiscovery();
      default:
        throw StateError(
            'Unsupported device operating system: {config.deviceOperatingSystem}');
    }
  }

  /// Lists all available devices' IDs.
  Future<List<Device>> discoverDevices({int retriesDelayMs = 10000});

  /// Checks the health of the available devices.
  Future<Map<String, HealthCheckResult>> checkDevices();

  /// Prepares the system to run tasks.
  Future<void> performPreflightTasks();
}

/// A proxy for one specific device.
abstract class Device {
  /// A unique device identifier.
  String get deviceId;

  /// Whether the device is awake.
  Future<bool> isAwake();

  /// Whether the device is asleep.
  Future<bool> isAsleep();

  /// Wake up the device if it is not awake.
  Future<void> wakeUp();

  /// Send the device to sleep mode.
  Future<void> sendToSleep();

  /// Emulates pressing the power button, toggling the device's on/off state.
  Future<void> togglePower();

  /// Turns off TalkBack on Android devices, does nothing on iOS devices.
  Future<void> disableAccessibility();

  /// Unlocks the device.
  ///
  /// Assumes the device doesn't have a secure unlock pattern.
  Future<void> unlock();
}

/// Constant battery health values returned from Android Battery Manager.
///
/// https://developer.android.com/reference/android/os/BatteryManager.html
class AndroidBatteryHealth {
  // Match SCREAMING_CAPS to Android constants.
  static const BATTERY_HEALTH_UNKNOWN = 1;
  static const BATTERY_HEALTH_GOOD = 2;
  static const BATTERY_HEALTH_OVERHEAT = 3;
  static const BATTERY_HEALTH_DEAD = 4;
  static const BATTERY_HEALTH_OVER_VOLTAGE = 5;
  static const BATTERY_HEALTH_UNSPECIFIED_FAILURE = 6;
  static const BATTERY_HEALTH_COLD = 7;
}

class AndroidDeviceDiscovery implements DeviceDiscovery {
  factory AndroidDeviceDiscovery() {
    return _instance ??= AndroidDeviceDiscovery._();
  }
  AndroidDeviceDiscovery._();

  @visibleForTesting
  AndroidDeviceDiscovery.testing();

  // Parses information about a device. Example:
  //
  // 015d172c98400a03       device usb:340787200X product:nakasi model:Nexus_7 device:grouper
  static final RegExp _kDeviceRegex = RegExp(r'^(\S+)\s+(\S+)(.*)');

  static AndroidDeviceDiscovery _instance;

  Future<String> deviceListOutput() async {
    return eval(config.adbPath, <String>['devices', '-l'], canFail: false)
        .timeout(Duration(seconds: 15));
  }

  Future<List<String>> deviceListOutputWithRetries(int retriesDelayMs) async {
    int retry = 0;
    while (true) {
      try {
        String result = await deviceListOutput();
        return result.trim().split('\n');
      } on TimeoutException {
        retry++;
        if (retry >= 3) {
          throw new TimeoutException('Can not get devices data');
        }
        killAdbServer();
        await Future<void>.delayed(Duration(milliseconds: retriesDelayMs));
      }
    }
  }

  void killAdbServer() async {
    if (Platform.isWindows) {
      await killAllRunningProcessesOnWindows('adb');
    } else {
      await exec(config.adbPath, <String>['kill-server'], canFail: false);
    }
  }

  @override
  Future<List<Device>> discoverDevices({int retriesDelayMs = 10000}) async {
    List<String> output = await deviceListOutputWithRetries(retriesDelayMs);
    List<String> results = <String>[];
    for (String line in output) {
      // Skip lines like: * daemon started successfully *
      if (line.startsWith('* daemon ')) continue;

      if (line.startsWith('List of devices')) continue;

      if (_kDeviceRegex.hasMatch(line)) {
        Match match = _kDeviceRegex.firstMatch(line);

        String deviceID = match[1];
        String deviceState = match[2];

        if (!const ['unauthorized', 'offline'].contains(deviceState)) {
          results.add(deviceID);
        }
      } else {
        throw 'Failed to parse device from adb output: $line';
      }
    }
    return results.map((String id) => AndroidDevice(deviceId: id)).toList();
  }

  @override
  Future<Map<String, HealthCheckResult>> checkDevices() async {
    Map<String, HealthCheckResult> results = <String, HealthCheckResult>{};
    for (Device device in await discoverDevices()) {
      final String deviceResultKey = 'android-device-${device.deviceId}';
      if (device is AndroidDevice) {
        try {
          // Just a smoke test that we can read wakefulness state
          await device._getWakefulness();
          results[deviceResultKey] = await device.batteryHealth();
        } catch (e, s) {
          results[deviceResultKey] = HealthCheckResult.error(e, s);
        }
      }
    }
    return results;
  }

  @override
  Future<void> performPreflightTasks() async {
    // Checks required for the agent to start.
  }
}

class AndroidDevice implements Device {
  AndroidDevice({@required this.deviceId});

  @override
  final String deviceId;

  /// Whether the device is awake.
  @override
  Future<bool> isAwake() async {
    return await _getWakefulness() == 'Awake';
  }

  /// Whether the device is asleep.
  @override
  Future<bool> isAsleep() async {
    return await _getWakefulness() == 'Asleep';
  }

  /// Wake up the device if it is not awake using [togglePower].
  @override
  Future<void> wakeUp() async {
    if (!(await isAwake())) await togglePower();
  }

  /// Send the device to sleep mode if it is not asleep using [togglePower].
  @override
  Future<void> sendToSleep() async {
    if (!(await isAsleep())) await togglePower();
  }

  /// Sends `KEYCODE_POWER` (26), which causes the device to toggle its mode
  /// between awake and asleep.
  @override
  Future<void> togglePower() async {
    await shellExec('input', const ['keyevent', '26']);
  }

  /// Unlocks the device by sending `KEYCODE_MENU` (82).
  ///
  /// This only works when the device doesn't have a secure unlock pattern.
  @override
  Future<void> unlock() async {
    await wakeUp();
    await shellExec('input', const ['keyevent', '82']);
  }

  @override
  Future<void> disableAccessibility() async {
    await shellExec('settings',
        ['put', 'secure', 'enabled_accessibility_services', 'null']);
  }

  /// Retrieves device's wakefulness state.
  ///
  /// See: https://android.googlesource.com/platform/frameworks/base/+/master/core/java/android/os/PowerManagerInternal.java
  Future<String> _getWakefulness() async {
    String powerInfo = await shellEval('dumpsys', ['power']);
    String wakefulness =
        grep('mWakefulness=', from: powerInfo).single.split('=')[1].trim();
    return wakefulness;
  }

  /// Retrieves battery health reported from dumpsys battery.
  Future<HealthCheckResult> batteryHealth() async {
    try {
      String batteryInfo = await shellEval('dumpsys', ['battery']);
      String batteryTemperatureString =
          grep('health: ', from: batteryInfo).single.split(': ')[1].trim();
      int batteryHeath = int.parse(batteryTemperatureString);
      switch (batteryHeath) {
        case AndroidBatteryHealth.BATTERY_HEALTH_OVERHEAT:
          return HealthCheckResult.failure('Battery overheated');
        case AndroidBatteryHealth.BATTERY_HEALTH_DEAD:
          return HealthCheckResult.failure('Battery dead');
        case AndroidBatteryHealth.BATTERY_HEALTH_OVER_VOLTAGE:
          return HealthCheckResult.failure('Battery over voltage');
        case AndroidBatteryHealth.BATTERY_HEALTH_UNSPECIFIED_FAILURE:
          return HealthCheckResult.failure('Unspecified battery failure');
        case AndroidBatteryHealth.BATTERY_HEALTH_COLD:
          return HealthCheckResult.failure('Battery cold');
        case AndroidBatteryHealth.BATTERY_HEALTH_UNKNOWN:
          return HealthCheckResult.success('Battery health unknown');
        case AndroidBatteryHealth.BATTERY_HEALTH_GOOD:
          return HealthCheckResult.success();
        default:
          // Unknown code.
          return HealthCheckResult.success(
              'Unknown battery health value $batteryHeath');
      }
    } catch (e) {
      // dumpsys battery not supported.
      return HealthCheckResult.success('Unknown battery health');
    }
  }

  /// Executes [command] on `adb shell` and returns its exit code.
  Future<void> shellExec(String command, List<String> arguments,
      {Map<String, String> env}) async {
    await exec(config.adbPath, ['shell', command]..addAll(arguments),
        env: env, canFail: false);
  }

  /// Executes [command] on `adb shell` and returns its standard output as a [String].
  Future<String> shellEval(String command, List<String> arguments,
      {Map<String, String> env}) {
    return eval(config.adbPath, ['shell', command]..addAll(arguments),
        env: env, canFail: false);
  }
}

class IosDeviceDiscovery implements DeviceDiscovery {
  factory IosDeviceDiscovery() {
    return _instance ??= IosDeviceDiscovery._();
  }

  IosDeviceDiscovery._();

  static IosDeviceDiscovery _instance;

  @override
  Future<List<Device>> discoverDevices({int retriesDelayMs = 10000}) async {
    List<String> iosDeviceIds =
        LineSplitter.split(await eval('idevice_id', ['-l'])).toList();
    if (iosDeviceIds.isEmpty) throw 'No connected iOS devices found.';
    return iosDeviceIds.map((String id) => IosDevice(deviceId: id)).toList();
  }

  @override
  Future<Map<String, HealthCheckResult>> checkDevices() async {
    Map<String, HealthCheckResult> results = <String, HealthCheckResult>{};
    for (Device device in await discoverDevices()) {
      // TODO: do a more meaningful connectivity check than just recording the ID
      results['ios-device-${device.deviceId}'] = HealthCheckResult.success();
    }
    return results;
  }

  @override
  Future<void> performPreflightTasks() async {
    // Currently we do not have preflight tasks for iOS.
    return null;
  }
}

class NoOpDeviceDiscovery implements DeviceDiscovery {
  factory NoOpDeviceDiscovery() {
    return _instance ??= NoOpDeviceDiscovery._();
  }

  NoOpDeviceDiscovery._();

  static NoOpDeviceDiscovery _instance;

  @override
  Future<List<Device>> discoverDevices({int retriesDelayMs = 10000}) async {
    return [];
  }

  @override
  Future<Map<String, HealthCheckResult>> checkDevices() async {
    Map<String, HealthCheckResult> results = <String, HealthCheckResult>{};
    results['no-device'] = HealthCheckResult.success();
    return results;
  }

  @override
  Future<void> performPreflightTasks() async {
    // Currently we do not have preflight tasks for hosts without attached devices.
    return null;
  }
}

/// iOS device.
class IosDevice implements Device {
  const IosDevice({@required this.deviceId});

  @override
  final String deviceId;

  // The methods below are stubs for now. They will need to be expanded.
  // We currently do not have a way to lock/unlock iOS devices. So we assume the
  // devices are already unlocked. For now we'll just keep them at minimum
  // screen brightness so they don't drain battery too fast.

  @override
  Future<bool> isAwake() async => true;

  @override
  Future<bool> isAsleep() async => false;

  @override
  Future<void> wakeUp() async {}

  @override
  Future<void> sendToSleep() async {}

  @override
  Future<void> togglePower() async {}

  @override
  Future<void> unlock() async {}

  @override
  Future<void> disableAccessibility() async {}
}
