// 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.

// @dart = 2.8

import 'dart:async';

import 'package:meta/meta.dart';
import 'package:process/process.dart';

import '../android/android_sdk.dart';
import '../android/android_workflow.dart';
import '../base/common.dart';
import '../base/file_system.dart';
import '../base/io.dart';
import '../base/logger.dart';
import '../base/process.dart';
import '../convert.dart';
import '../device.dart';
import '../emulator.dart';
import 'android_sdk.dart';

class AndroidEmulators extends EmulatorDiscovery {
  AndroidEmulators({
    @required AndroidSdk androidSdk,
    @required AndroidWorkflow androidWorkflow,
    @required FileSystem fileSystem,
    @required Logger logger,
    @required ProcessManager processManager,
  }) : _androidSdk = androidSdk,
       _androidWorkflow = androidWorkflow,
       _fileSystem = fileSystem,
       _logger = logger,
       _processManager = processManager,
       _processUtils = ProcessUtils(logger: logger, processManager: processManager);

  final AndroidWorkflow _androidWorkflow;
  final AndroidSdk _androidSdk;
  final FileSystem _fileSystem;
  final Logger _logger;
  final ProcessManager _processManager;
  final ProcessUtils _processUtils;

  @override
  bool get supportsPlatform => true;

  @override
  bool get canListAnything => _androidWorkflow.canListEmulators;

  @override
  bool get canLaunchAnything => _androidWorkflow.canListEmulators
    && _androidSdk.getAvdManagerPath() != null;

  @override
  Future<List<Emulator>> get emulators => _getEmulatorAvds();

  /// Return the list of available emulator AVDs.
  Future<List<AndroidEmulator>> _getEmulatorAvds() async {
    final String emulatorPath = _androidSdk?.emulatorPath;
    if (emulatorPath == null) {
      return <AndroidEmulator>[];
    }

    final String listAvdsOutput = (await _processUtils.run(
      <String>[emulatorPath, '-list-avds'])).stdout.trim();

    final List<AndroidEmulator> emulators = <AndroidEmulator>[];
    if (listAvdsOutput != null) {
      _extractEmulatorAvdInfo(listAvdsOutput, emulators);
    }
    return emulators;
  }

  /// Parse the given `emulator -list-avds` output in [text], and fill out the given list
  /// of emulators by reading information from the relevant ini files.
  void _extractEmulatorAvdInfo(String text, List<AndroidEmulator> emulators) {
    for (final String id in text.trim().split('\n').where((String l) => l != '')) {
      emulators.add(_loadEmulatorInfo(id));
    }
  }

  AndroidEmulator _loadEmulatorInfo(String id) {
    id = id.trim();
    final String avdPath = _androidSdk.getAvdPath();
    final AndroidEmulator androidEmulatorWithoutProperties = AndroidEmulator(
      id,
      processManager: _processManager,
      logger: _logger,
      androidSdk: _androidSdk,
    );
    if (avdPath == null) {
      return androidEmulatorWithoutProperties;
    }
    final File iniFile = _fileSystem.file(_fileSystem.path.join(avdPath, '$id.ini'));
    if (!iniFile.existsSync()) {
      return androidEmulatorWithoutProperties;
    }
    final Map<String, String> ini = parseIniLines(iniFile.readAsLinesSync());
    if (ini['path'] == null) {
      return androidEmulatorWithoutProperties;
    }
    final File configFile = _fileSystem.file(_fileSystem.path.join(ini['path'], 'config.ini'));
    if (!configFile.existsSync()) {
      return androidEmulatorWithoutProperties;
    }
    final Map<String, String> properties = parseIniLines(configFile.readAsLinesSync());
    return AndroidEmulator(
      id,
      properties: properties,
      processManager: _processManager,
      logger: _logger,
      androidSdk: _androidSdk,
    );
  }
}

class AndroidEmulator extends Emulator {
  AndroidEmulator(String id, {
    Map<String, String> properties,
    @required Logger logger,
    @required AndroidSdk androidSdk,
    @required ProcessManager processManager,
  }) : _properties = properties,
       _logger = logger,
       _androidSdk = androidSdk,
       _processUtils = ProcessUtils(logger: logger, processManager: processManager),
       super(id, properties != null && properties.isNotEmpty);

  final Map<String, String> _properties;
  final Logger _logger;
  final ProcessUtils _processUtils;
  final AndroidSdk _androidSdk;

  // Android Studio uses the ID with underscores replaced with spaces
  // for the name if displayname is not set so we do the same.
  @override
  String get name => _prop('avd.ini.displayname') ?? id.replaceAll('_', ' ').trim();

  @override
  String get manufacturer => _prop('hw.device.manufacturer');

  @override
  Category get category => Category.mobile;

  @override
  PlatformType get platformType => PlatformType.android;

  String _prop(String name) => _properties != null ? _properties[name] : null;

  @override
  Future<void> launch() async {
    final Process process = await _processUtils.start(
      <String>[_androidSdk.emulatorPath, '-avd', id],
    );

    // Record output from the emulator process.
    final List<String> stdoutList = <String>[];
    final List<String> stderrList = <String>[];
    final StreamSubscription<String> stdoutSubscription = process.stdout
      .transform<String>(utf8.decoder)
      .transform<String>(const LineSplitter())
      .listen(stdoutList.add);
    final StreamSubscription<String> stderrSubscription = process.stderr
      .transform<String>(utf8.decoder)
      .transform<String>(const LineSplitter())
      .listen(stderrList.add);
    final Future<void> stdioFuture = Future.wait<void>(<Future<void>>[
      stdoutSubscription.asFuture<void>(),
      stderrSubscription.asFuture<void>(),
    ]);

    // The emulator continues running on success, so we don't wait for the
    // process to complete before continuing. However, if the process fails
    // after the startup phase (3 seconds), then we only echo its output if
    // its error code is non-zero and its stderr is non-empty.
    bool earlyFailure = true;
    unawaited(process.exitCode.then((int status) async {
      if (status == 0) {
        _logger.printTrace('The Android emulator exited successfully');
        return;
      }
      // Make sure the process' stdout and stderr are drained.
      await stdioFuture;
      unawaited(stdoutSubscription.cancel());
      unawaited(stderrSubscription.cancel());
      if (stdoutList.isNotEmpty) {
        _logger.printTrace('Android emulator stdout:');
        stdoutList.forEach(_logger.printTrace);
      }
      if (!earlyFailure && stderrList.isEmpty) {
        _logger.printStatus('The Android emulator exited with code $status');
        return;
      }
      final String when = earlyFailure ? 'during startup' : 'after startup';
      _logger.printError('The Android emulator exited with code $status $when');
      _logger.printError('Android emulator stderr:');
      stderrList.forEach(_logger.printError);
      _logger.printError('Address these issues and try again.');
    }));

    // Wait a few seconds for the emulator to start.
    await Future<void>.delayed(const Duration(seconds: 3));
    earlyFailure = false;
    return;
  }
}


@visibleForTesting
Map<String, String> parseIniLines(List<String> contents) {
  final Map<String, String> results = <String, String>{};

  final Iterable<List<String>> properties = contents
      .map<String>((String l) => l.trim())
      // Strip blank lines/comments
      .where((String l) => l != '' && !l.startsWith('#'))
      // Discard anything that isn't simple name=value
      .where((String l) => l.contains('='))
      // Split into name/value
      .map<List<String>>((String l) => l.split('='));

  for (final List<String> property in properties) {
    results[property[0].trim()] = property[1].trim();
  }

  return results;
}
