// 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 '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 '../base/utils.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 = getEmulatorPath(_androidSdk);
    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 = 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>[getEmulatorPath(_androidSdk), '-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 = waitGroup<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;
}
