// Copyright 2018 The Chromium 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:math' as math;

import 'android/android_emulator.dart';
import 'android/android_sdk.dart';
import 'base/context.dart';
import 'base/io.dart' show ProcessResult;
import 'base/process_manager.dart';
import 'globals.dart';
import 'ios/ios_emulators.dart';

EmulatorManager get emulatorManager => context[EmulatorManager];

/// A class to get all available emulators.
class EmulatorManager {
  /// Constructing EmulatorManager is cheap; they only do expensive work if some
  /// of their methods are called.
  EmulatorManager() {
    // Register the known discoverers.
    _emulatorDiscoverers.add(AndroidEmulators());
    _emulatorDiscoverers.add(IOSEmulators());
  }

  final List<EmulatorDiscovery> _emulatorDiscoverers = <EmulatorDiscovery>[];

  Future<List<Emulator>> getEmulatorsMatching(String searchText) async {
    final List<Emulator> emulators = await getAllAvailableEmulators();
    searchText = searchText.toLowerCase();
    bool exactlyMatchesEmulatorId(Emulator emulator) =>
        emulator.id?.toLowerCase() == searchText ||
        emulator.name?.toLowerCase() == searchText;
    bool startsWithEmulatorId(Emulator emulator) =>
        emulator.id?.toLowerCase()?.startsWith(searchText) == true ||
        emulator.name?.toLowerCase()?.startsWith(searchText) == true;

    final Emulator exactMatch =
        emulators.firstWhere(exactlyMatchesEmulatorId, orElse: () => null);
    if (exactMatch != null) {
      return <Emulator>[exactMatch];
    }

    // Match on a id or name starting with [emulatorId].
    return emulators.where(startsWithEmulatorId).toList();
  }

  Iterable<EmulatorDiscovery> get _platformDiscoverers {
    return _emulatorDiscoverers.where((EmulatorDiscovery discoverer) => discoverer.supportsPlatform);
  }

  /// Return the list of all available emulators.
  Future<List<Emulator>> getAllAvailableEmulators() async {
    final List<Emulator> emulators = <Emulator>[];
    await Future.forEach<EmulatorDiscovery>(_platformDiscoverers, (EmulatorDiscovery discoverer) async {
      emulators.addAll(await discoverer.emulators);
    });
    return emulators;
  }

  /// Return the list of all available emulators.
  Future<CreateEmulatorResult> createEmulator({ String name }) async {
    if (name == null || name == '') {
      const String autoName = 'flutter_emulator';
      // Don't use getEmulatorsMatching here, as it will only return one
      // if there's an exact match and we need all those with this prefix
      // so we can keep adding suffixes until we miss.
      final List<Emulator> all = await getAllAvailableEmulators();
      final Set<String> takenNames = all
          .map<String>((Emulator e) => e.id)
          .where((String id) => id.startsWith(autoName))
          .toSet();
      int suffix = 1;
      name = autoName;
      while (takenNames.contains(name)) {
        name = '${autoName}_${++suffix}';
      }
    }

    final String device = await _getPreferredAvailableDevice();
    if (device == null)
      return CreateEmulatorResult(name,
          success: false, error: 'No device definitions are available');

    final String sdkId = await _getPreferredSdkId();
    if (sdkId == null)
      return CreateEmulatorResult(name,
          success: false,
          error:
              'No suitable Android AVD system images are available. You may need to install these'
              ' using sdkmanager, for example:\n'
              '  sdkmanager "system-images;android-27;google_apis_playstore;x86"');

    // Cleans up error output from avdmanager to make it more suitable to show
    // to flutter users. Specifically:
    // - Removes lines that say "null" (!)
    // - Removes lines that tell the user to use '--force' to overwrite emulators
    String cleanError(String error) {
      if (error == null || error.trim() == '')
        return null;
      return error
          .split('\n')
          .where((String l) => l.trim() != 'null')
          .where((String l) =>
              l.trim() != 'Use --force if you want to replace it.')
          .join('\n')
          .trim();
    }

    final List<String> args = <String>[
      getAvdManagerPath(androidSdk),
      'create',
      'avd',
      '-n', name,
      '-k', sdkId,
      '-d', device
    ];
    final ProcessResult runResult = processManager.runSync(args,
        environment: androidSdk?.sdkManagerEnv);
    return CreateEmulatorResult(
      name,
      success: runResult.exitCode == 0,
      output: runResult.stdout,
      error: cleanError(runResult.stderr),
    );
  }

  static const List<String> preferredDevices = <String>[
    'pixel',
    'pixel_xl',
  ];
  Future<String> _getPreferredAvailableDevice() async {
    final List<String> args = <String>[
      getAvdManagerPath(androidSdk),
      'list',
      'device',
      '-c'
    ];
    final ProcessResult runResult = processManager.runSync(args,
        environment: androidSdk?.sdkManagerEnv);
    if (runResult.exitCode != 0)
      return null;

    final List<String> availableDevices = runResult.stdout
        .split('\n')
        .where((String l) => preferredDevices.contains(l.trim()))
        .toList();

    return preferredDevices.firstWhere(
      (String d) => availableDevices.contains(d),
      orElse: () => null,
    );
  }

  RegExp androidApiVersion = RegExp(r';android-(\d+);');
  Future<String> _getPreferredSdkId() async {
    // It seems that to get the available list of images, we need to send a
    // request to create without the image and it'll provide us a list :-(
    final List<String> args = <String>[
      getAvdManagerPath(androidSdk),
      'create',
      'avd',
      '-n', 'temp',
    ];
    final ProcessResult runResult = processManager.runSync(args,
        environment: androidSdk?.sdkManagerEnv);

    // Get the list of IDs that match our criteria
    final List<String> availableIDs = runResult.stderr
        .split('\n')
        .where((String l) => androidApiVersion.hasMatch(l))
        .where((String l) => l.contains('system-images'))
        .where((String l) => l.contains('google_apis_playstore'))
        .toList();

    final List<int> availableApiVersions = availableIDs
        .map<String>((String id) => androidApiVersion.firstMatch(id).group(1))
        .map<int>((String apiVersion) => int.parse(apiVersion))
        .toList();

    // Get the highest Android API version or whats left
    final int apiVersion = availableApiVersions.isNotEmpty
        ? availableApiVersions.reduce(math.max)
        : -1; // Don't match below

    // We're out of preferences, we just have to return the first one with the high
    // API version.
    return availableIDs.firstWhere(
      (String id) => id.contains(';android-$apiVersion;'),
      orElse: () => null,
    );
  }

  /// Whether we're capable of listing any emulators given the current environment configuration.
  bool get canListAnything {
    return _platformDiscoverers.any((EmulatorDiscovery discoverer) => discoverer.canListAnything);
  }
}

/// An abstract class to discover and enumerate a specific type of emulators.
abstract class EmulatorDiscovery {
  bool get supportsPlatform;

  /// Whether this emulator discovery is capable of listing any emulators given the
  /// current environment configuration.
  bool get canListAnything;

  Future<List<Emulator>> get emulators;
}

abstract class Emulator {
  Emulator(this.id, this.hasConfig);

  final String id;
  final bool hasConfig;
  String get name;
  String get manufacturer;
  String get label;

  @override
  int get hashCode => id.hashCode;

  @override
  bool operator ==(dynamic other) {
    if (identical(this, other))
      return true;
    if (other is! Emulator)
      return false;
    return id == other.id;
  }

  Future<void> launch();

  @override
  String toString() => name;

  static List<String> descriptions(List<Emulator> emulators) {
    if (emulators.isEmpty)
      return <String>[];

    // Extract emulators information
    final List<List<String>> table = <List<String>>[];
    for (Emulator emulator in emulators) {
      table.add(<String>[
        emulator.id ?? '',
        emulator.name ?? '',
        emulator.manufacturer ?? '',
        emulator.label ?? '',
      ]);
    }

    // Calculate column widths
    final List<int> indices = List<int>.generate(table[0].length - 1, (int i) => i);
    List<int> widths = indices.map<int>((int i) => 0).toList();
    for (List<String> row in table) {
      widths = indices.map<int>((int i) => math.max(widths[i], row[i].length)).toList();
    }

    // Join columns into lines of text
    final RegExp whiteSpaceAndDots = RegExp(r'[•\s]+$');
    return table
        .map<String>((List<String> row) {
          return indices
                  .map<String>((int i) => row[i].padRight(widths[i]))
                  .join(' • ') +
              ' • ${row.last}';
        })
        .map<String>((String line) => line.replaceAll(whiteSpaceAndDots, ''))
        .toList();
  }

  static void printEmulators(List<Emulator> emulators) {
    descriptions(emulators).forEach(printStatus);
  }
}

class CreateEmulatorResult {
  CreateEmulatorResult(this.emulatorName, {this.success, this.output, this.error});

  final bool success;
  final String emulatorName;
  final String output;
  final String error;
}
