// Copyright 2014 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 'package:meta/meta.dart';
import 'package:process/process.dart';

import '../base/common.dart';
import '../base/file_system.dart';
import '../base/io.dart';
import '../base/logger.dart';
import '../base/platform.dart';
import '../base/process.dart';
import '../device.dart';
import '../globals.dart' as globals;
import 'adb.dart';
import 'android_device.dart';
import 'android_sdk.dart';
import 'android_workflow.dart' hide androidWorkflow;
import 'android_workflow.dart' as workflow show androidWorkflow;

/// Device discovery for Android physical devices and emulators.s
class AndroidDevices extends PollingDeviceDiscovery {
  // TODO(jonahwilliams): make these required after google3 is updated.
  AndroidDevices({
    AndroidWorkflow androidWorkflow,
    ProcessManager processManager,
    Logger logger,
    AndroidSdk androidSdk,
  }) : _androidWorkflow = androidWorkflow ?? workflow.androidWorkflow,
       _androidSdk = androidSdk ?? globals.androidSdk,
       _processUtils = ProcessUtils(
         logger: logger ?? globals.logger,
         processManager: processManager ?? globals.processManager,
        ),
       super('Android devices');

  final AndroidWorkflow _androidWorkflow;
  final ProcessUtils _processUtils;
  final AndroidSdk _androidSdk;

  @override
  bool get supportsPlatform => true;

  @override
  bool get canListAnything => _androidWorkflow.canListDevices;

  @override
  Future<List<Device>> pollingGetDevices({ Duration timeout }) async {
    final String adbPath = getAdbPath(_androidSdk);
    if (adbPath == null) {
      return <AndroidDevice>[];
    }
    String text;
    try {
      text = (await _processUtils.run(
        <String>[adbPath, 'devices', '-l'],
        throwOnError: true,
      )).stdout.trim();
    } on ArgumentError catch (exception) {
      throwToolExit('Unable to find "adb", check your Android SDK installation and '
        '$kAndroidSdkRoot environment variable: ${exception.message}');
    } on ProcessException catch (exception) {
      throwToolExit('Unable to run "adb", check your Android SDK installation and '
        '$kAndroidSdkRoot environment variable: ${exception.executable}');
    }
    final List<AndroidDevice> devices = <AndroidDevice>[];
    parseADBDeviceOutput(
      text,
      devices: devices,
      timeoutConfiguration: timeoutConfiguration,
    );
    return devices;
  }

  @override
  Future<List<String>> getDiagnostics() async {
    final String adbPath = getAdbPath(_androidSdk);
    if (adbPath == null) {
      return <String>[];
    }

    final RunResult result = await _processUtils.run(<String>[adbPath, 'devices', '-l']);
    if (result.exitCode != 0) {
      return <String>[];
    } else {
      final String text = result.stdout;
      final List<String> diagnostics = <String>[];
      parseADBDeviceOutput(
        text,
        diagnostics: diagnostics,
        timeoutConfiguration: timeoutConfiguration,
      );
      return diagnostics;
    }
  }

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

  /// Parse the given `adb devices` output in [text], and fill out the given list
  /// of devices and possible device issue diagnostics. Either argument can be null,
  /// in which case information for that parameter won't be populated.
  @visibleForTesting
  static void parseADBDeviceOutput(
    String text, {
    List<AndroidDevice> devices,
    List<String> diagnostics,
    AndroidSdk androidSdk,
    FileSystem fileSystem,
    Logger logger,
    Platform platform,
    ProcessManager processManager,
    @required TimeoutConfiguration timeoutConfiguration,
  }) {
    // Check for error messages from adb
    if (!text.contains('List of devices')) {
      diagnostics?.add(text);
      return;
    }

    for (final String line in text.trim().split('\n')) {
      // Skip lines like: * daemon started successfully *
      if (line.startsWith('* daemon ')) {
        continue;
      }

      // Skip lines about adb server and client version not matching
      if (line.startsWith(RegExp(r'adb server (version|is out of date)'))) {
        diagnostics?.add(line);
        continue;
      }

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

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

        final String deviceID = match[1];
        final String deviceState = match[2];
        String rest = match[3];

        final Map<String, String> info = <String, String>{};
        if (rest != null && rest.isNotEmpty) {
          rest = rest.trim();
          for (final String data in rest.split(' ')) {
            if (data.contains(':')) {
              final List<String> fields = data.split(':');
              info[fields[0]] = fields[1];
            }
          }
        }

        if (info['model'] != null) {
          info['model'] = cleanAdbDeviceName(info['model']);
        }

        if (deviceState == 'unauthorized') {
          diagnostics?.add(
            'Device $deviceID is not authorized.\n'
            'You might need to check your device for an authorization dialog.'
          );
        } else if (deviceState == 'offline') {
          diagnostics?.add('Device $deviceID is offline.');
        } else {
          devices?.add(AndroidDevice(
            deviceID,
            productID: info['product'],
            modelID: info['model'] ?? deviceID,
            deviceCodeName: info['device'],
            androidSdk: androidSdk ?? globals.androidSdk,
            fileSystem: fileSystem ?? globals.fs,
            logger: logger ?? globals.logger,
            platform: platform ?? globals.platform,
            processManager: processManager ?? globals.processManager,
            timeoutConfiguration: timeoutConfiguration,
          ));
        }
      } else {
        diagnostics?.add(
          'Unexpected failure parsing device information from adb output:\n'
          '$line\n'
          '${globals.userMessages.flutterToolBugInstructions}');
      }
    }
  }
}
