// Copyright 2015 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_device.dart';
import 'application_package.dart';
import 'base/common.dart';
import 'base/context.dart';
import 'base/file_system.dart';
import 'base/os.dart';
import 'base/utils.dart';
import 'build_info.dart';
import 'devfs.dart';
import 'globals.dart';
import 'ios/devices.dart';
import 'ios/simulators.dart';

DeviceManager get deviceManager => context[DeviceManager];

/// A class to get all available devices.
class DeviceManager {
  /// Constructing DeviceManagers is cheap; they only do expensive work if some
  /// of their methods are called.
  DeviceManager() {
    // Register the known discoverers.
    _deviceDiscoverers.add(new AndroidDevices());
    _deviceDiscoverers.add(new IOSDevices());
    _deviceDiscoverers.add(new IOSSimulators());
  }

  List<DeviceDiscovery> _deviceDiscoverers = <DeviceDiscovery>[];

  /// A user-specified device ID.
  String specifiedDeviceId;

  bool get hasSpecifiedDeviceId => specifiedDeviceId != null;

  /// Return the devices with a name or id matching [deviceId].
  /// This does a case insentitive compare with [deviceId].
  Future<List<Device>> getDevicesById(String deviceId) async {
    deviceId = deviceId.toLowerCase();
    List<Device> devices = await getAllConnectedDevices();
    Device device = devices.firstWhere(
        (Device device) =>
            device.id.toLowerCase() == deviceId ||
            device.name.toLowerCase() == deviceId,
        orElse: () => null);

    if (device != null)
      return <Device>[device];

    // Match on a id or name starting with [deviceId].
    return devices.where((Device device) {
      return (device.id.toLowerCase().startsWith(deviceId) ||
        device.name.toLowerCase().startsWith(deviceId));
    }).toList();
  }

  /// Return the list of connected devices, filtered by any user-specified device id.
  Future<List<Device>> getDevices() async {
    if (specifiedDeviceId == null) {
      return getAllConnectedDevices();
    } else {
      return getDevicesById(specifiedDeviceId);
    }
  }

  /// Return the list of all connected devices.
  Future<List<Device>> getAllConnectedDevices() async {
    return _deviceDiscoverers
      .where((DeviceDiscovery discoverer) => discoverer.supportsPlatform)
      .expand((DeviceDiscovery discoverer) => discoverer.devices)
      .toList();
  }
}

/// An abstract class to discover and enumerate a specific type of devices.
abstract class DeviceDiscovery {
  bool get supportsPlatform;
  List<Device> get devices;
}

/// A [DeviceDiscovery] implementation that uses polling to discover device adds
/// and removals.
abstract class PollingDeviceDiscovery extends DeviceDiscovery {
  PollingDeviceDiscovery(this.name);

  static const Duration _pollingDuration = const Duration(seconds: 4);

  final String name;
  ItemListNotifier<Device> _items;
  Timer _timer;

  List<Device> pollingGetDevices();

  void startPolling() {
    if (_timer == null) {
      if (_items == null)
        _items = new ItemListNotifier<Device>();
      _timer = new Timer.periodic(_pollingDuration, (Timer timer) {
        _items.updateWithNewList(pollingGetDevices());
      });
    }
  }

  void stopPolling() {
    _timer?.cancel();
    _timer = null;
  }

  @override
  List<Device> get devices {
    if (_items == null)
      _items = new ItemListNotifier<Device>.from(pollingGetDevices());
    return _items.items;
  }

  Stream<Device> get onAdded {
    if (_items == null)
      _items = new ItemListNotifier<Device>();
    return _items.onAdded;
  }

  Stream<Device> get onRemoved {
    if (_items == null)
      _items = new ItemListNotifier<Device>();
    return _items.onRemoved;
  }

  void dispose() => stopPolling();

  @override
  String toString() => '$name device discovery';
}

abstract class Device {
  Device(this.id);

  final String id;

  String get name;

  bool get supportsStartPaused => true;

  /// Whether it is an emulated device running on localhost.
  bool get isLocalEmulator;

  /// Check if a version of the given app is already installed
  bool isAppInstalled(ApplicationPackage app);

  /// Install an app package on the current device
  bool installApp(ApplicationPackage app);

  /// Uninstall an app package from the current device
  bool uninstallApp(ApplicationPackage app);

  /// Check if the device is supported by Flutter
  bool isSupported();

  // String meant to be displayed to the user indicating if the device is
  // supported by Flutter, and, if not, why.
  String supportMessage() => isSupported() ? "Supported" : "Unsupported";

  // TODO(tvolkert): Rename to `targetPlatform`, and remove the "as p"
  // aliases on the `platform.dart` imports where applicable.
  TargetPlatform get platform;

  String get sdkNameAndVersion;

  /// Get a log reader for this device.
  /// If [app] is specified, this will return a log reader specific to that
  /// application. Otherwise, a global log reader will be returned.
  DeviceLogReader getLogReader({ApplicationPackage app});

  /// Get the port forwarder for this device.
  DevicePortForwarder get portForwarder;

  Future<int> forwardPort(int devicePort, {int hostPort}) async {
    try {
      hostPort = await portForwarder
          .forward(devicePort, hostPort: hostPort)
          .timeout(const Duration(seconds: 60), onTimeout: () {
            throw new ToolExit(
                'Timeout while atempting to foward device port $devicePort');
          });
      printTrace('Forwarded host port $hostPort to device port $devicePort');
      return hostPort;
    } catch (e) {
      throw new ToolExit(
          'Unable to forward host port $hostPort to device port $devicePort: $e');
    }
  }

  /// Clear the device's logs.
  void clearLogs();

  /// Start an app package on the current device.
  ///
  /// [platformArgs] allows callers to pass platform-specific arguments to the
  /// start call. The build mode is not used by all platforms.
  Future<LaunchResult> startApp(
    ApplicationPackage package,
    BuildMode mode, {
    String mainPath,
    String route,
    DebuggingOptions debuggingOptions,
    Map<String, dynamic> platformArgs,
    DevFSContent kernelContent,
    bool prebuiltApplication: false,
    bool applicationNeedsRebuild: false
  });

  /// Does this device implement support for hot reloading / restarting?
  bool get supportsHotMode => true;

  /// Stop an app package on the current device.
  Future<bool> stopApp(ApplicationPackage app);

  bool get supportsScreenshot => false;

  Future<Null> takeScreenshot(File outputFile) => new Future<Null>.error('unimplemented');

  /// Find the apps that are currently running on this device.
  Future<List<DiscoveredApp>> discoverApps() =>
      new Future<List<DiscoveredApp>>.value(<DiscoveredApp>[]);

  @override
  int get hashCode => id.hashCode;

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

  @override
  String toString() => name;

  static Iterable<String> descriptions(List<Device> devices) {
    if (devices.isEmpty)
      return <String>[];

    // Extract device information
    List<List<String>> table = <List<String>>[];
    for (Device device in devices) {
      String supportIndicator = device.isSupported() ? '' : ' (unsupported)';
      if (device.isLocalEmulator) {
        String type = device.platform == TargetPlatform.ios ? 'simulator' : 'emulator';
        supportIndicator += ' ($type)';
      }
      table.add(<String>[
        device.name,
        device.id,
        '${getNameForTargetPlatform(device.platform)}',
        '${device.sdkNameAndVersion}$supportIndicator',
      ]);
    }

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

    // Join columns into lines of text
    return table.map((List<String> row) =>
        indices.map((int i) => row[i].padRight(widths[i])).join(' • ') +
        ' • ${row.last}');
  }

  static void printDevices(List<Device> devices) {
    descriptions(devices).forEach((String msg) => printStatus(msg));
  }
}

class DebuggingOptions {
  DebuggingOptions.enabled(this.buildMode, {
    this.startPaused: false,
    this.observatoryPort,
    this.diagnosticPort
   }) : debuggingEnabled = true;

  DebuggingOptions.disabled(this.buildMode) :
    debuggingEnabled = false,
    startPaused = false,
    observatoryPort = null,
    diagnosticPort = null;

  final bool debuggingEnabled;

  final BuildMode buildMode;
  final bool startPaused;
  final int observatoryPort;
  final int diagnosticPort;

  bool get hasObservatoryPort => observatoryPort != null;

  /// Return the user specified observatory port. If that isn't available,
  /// return [kDefaultObservatoryPort], or a port close to that one.
  Future<int> findBestObservatoryPort() {
    if (hasObservatoryPort)
      return new Future<int>.value(observatoryPort);
    return findPreferredPort(observatoryPort ?? kDefaultObservatoryPort);
  }

  bool get hasDiagnosticPort => diagnosticPort != null;

  /// Return the user specified diagnostic port. If that isn't available,
  /// return [kDefaultDiagnosticPort], or a port close to that one.
  Future<int> findBestDiagnosticPort() {
    if (hasDiagnosticPort)
      return new Future<int>.value(diagnosticPort);
    return findPreferredPort(diagnosticPort ?? kDefaultDiagnosticPort);
  }
}

class LaunchResult {
  LaunchResult.succeeded({ this.observatoryUri, this.diagnosticUri }) : started = true;
  LaunchResult.failed() : started = false, observatoryUri = null, diagnosticUri = null;

  bool get hasObservatory => observatoryUri != null;

  final bool started;
  final Uri observatoryUri;
  final Uri diagnosticUri;

  @override
  String toString() {
    StringBuffer buf = new StringBuffer('started=$started');
    if (observatoryUri != null)
      buf.write(', observatory=$observatoryUri');
    if (diagnosticUri != null)
      buf.write(', diagnostic=$diagnosticUri');
    return buf.toString();
  }
}

class ForwardedPort {
  ForwardedPort(this.hostPort, this.devicePort) : context = null;
  ForwardedPort.withContext(this.hostPort, this.devicePort, this.context);

  final int hostPort;
  final int devicePort;
  final dynamic context;

  @override
  String toString() => 'ForwardedPort HOST:$hostPort to DEVICE:$devicePort';
}

/// Forward ports from the host machine to the device.
abstract class DevicePortForwarder {
  /// Returns a Future that completes with the current list of forwarded
  /// ports for this device.
  List<ForwardedPort> get forwardedPorts;

  /// Forward [hostPort] on the host to [devicePort] on the device.
  /// If [hostPort] is null, will auto select a host port.
  /// Returns a Future that completes with the host port.
  Future<int> forward(int devicePort, { int hostPort });

  /// Stops forwarding [forwardedPort].
  Future<Null> unforward(ForwardedPort forwardedPort);
}

/// Read the log for a particular device.
abstract class DeviceLogReader {
  String get name;

  /// A broadcast stream where each element in the string is a line of log output.
  Stream<String> get logLines;

  @override
  String toString() => name;
}

/// Describes an app running on the device.
class DiscoveredApp {
  DiscoveredApp(this.id, this.observatoryPort, this.diagnosticPort);
  final String id;
  final int observatoryPort;
  final int diagnosticPort;
}
