// 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 'dart:typed_data';

import 'package:meta/meta.dart';

import '../application_package.dart';
import '../base/file_system.dart';
import '../base/io.dart';
import '../base/logger.dart';
import '../build_info.dart';
import '../convert.dart';
import '../daemon.dart';
import '../device.dart';
import '../device_port_forwarder.dart';
import '../project.dart';
import 'file_transfer.dart';

bool _isNullable<T>() => null is T;

T _cast<T>(Object? object) {
  if (!_isNullable<T>() && object == null) {
    throw Exception('Expected $T, received null!');
  } else {
    return object as T;
  }
}

/// A [DeviceDiscovery] that will connect to a flutter daemon and connects to
/// the devices remotely.
///
/// If [deltaFileTransfer] is true, the proxy will use an rsync-like algorithm that
/// only transfers the changed part of the application package for deployment.
class ProxiedDevices extends DeviceDiscovery {
  ProxiedDevices(this.connection, {
    bool deltaFileTransfer = true,
    required Logger logger,
  }) : _deltaFileTransfer = deltaFileTransfer,
       _logger = logger;

  /// [DaemonConnection] used to communicate with the daemon.
  final DaemonConnection connection;

  final Logger _logger;

  final bool _deltaFileTransfer;

  @override
  bool get supportsPlatform => true;

  @override
  bool get canListAnything => true;

  List<Device>? _devices;

  @override
  Future<List<Device>> get devices async =>
      _devices ?? await discoverDevices();

  @override
  Future<List<Device>> discoverDevices({Duration? timeout}) async {
    final List<Map<String, Object?>> discoveredDevices = _cast<List<dynamic>>(await connection.sendRequest('device.discoverDevices')).cast<Map<String, Object?>>();
    final List<ProxiedDevice> devices = <ProxiedDevice>[
      for (final Map<String, Object?> device in discoveredDevices)
        _deviceFromDaemonResult(device),
    ];

    _devices = devices;
    return devices;
  }

  @override
  List<String> get wellKnownIds => const <String>[];

  ProxiedDevice _deviceFromDaemonResult(Map<String, Object?> device) {
    final Map<String, Object?> capabilities = _cast<Map<String, Object?>>(device['capabilities']);
    return ProxiedDevice(
      connection, _cast<String>(device['id']),
      deltaFileTransfer: _deltaFileTransfer,
      category: Category.fromString(_cast<String>(device['category'])),
      platformType: PlatformType.fromString(_cast<String>(device['platformType'])),
      targetPlatform: getTargetPlatformForName(_cast<String>(device['platform'])),
      ephemeral: _cast<bool>(device['ephemeral']),
      name: 'Proxied ${device['name']}',
      isLocalEmulator: _cast<bool>(device['emulator']),
      emulatorId: _cast<String?>(device['emulatorId']),
      sdkNameAndVersion: _cast<String>(device['sdk']),
      supportsHotReload: _cast<bool>(capabilities['hotReload']),
      supportsHotRestart: _cast<bool>(capabilities['hotRestart']),
      supportsFlutterExit: _cast<bool>(capabilities['flutterExit']),
      supportsScreenshot: _cast<bool>(capabilities['screenshot']),
      supportsFastStart: _cast<bool>(capabilities['fastStart']),
      supportsHardwareRendering: _cast<bool>(capabilities['hardwareRendering']),
      logger: _logger,
    );
  }
}

/// A [Device] that acts as a proxy to remotely connected device.
///
/// The communication happens via a flutter daemon.
///
/// If [deltaFileTransfer] is true, the proxy will use an rsync-like algorithm that
/// only transfers the changed part of the application package for deployment.
class ProxiedDevice extends Device {
  ProxiedDevice(this.connection, String id, {
    bool deltaFileTransfer = true,
    required Category? category,
    required PlatformType? platformType,
    required TargetPlatform targetPlatform,
    required bool ephemeral,
    required this.name,
    required bool isLocalEmulator,
    required String? emulatorId,
    required String sdkNameAndVersion,
    required this.supportsHotReload,
    required this.supportsHotRestart,
    required this.supportsFlutterExit,
    required this.supportsScreenshot,
    required this.supportsFastStart,
    required bool supportsHardwareRendering,
    required Logger logger,
  }): _deltaFileTransfer = deltaFileTransfer,
      _isLocalEmulator = isLocalEmulator,
      _emulatorId = emulatorId,
      _sdkNameAndVersion = sdkNameAndVersion,
      _supportsHardwareRendering = supportsHardwareRendering,
      _targetPlatform = targetPlatform,
      _logger = logger,
      super(id,
        category: category,
        platformType: platformType,
        ephemeral: ephemeral);

  /// [DaemonConnection] used to communicate with the daemon.
  final DaemonConnection connection;

  final Logger _logger;

  final bool _deltaFileTransfer;

  @override
  final String name;

  final bool _isLocalEmulator;
  @override
  Future<bool> get isLocalEmulator async => _isLocalEmulator;

  final String? _emulatorId;
  @override
  Future<String?> get emulatorId async => _emulatorId;

  @override
  Future<bool> supportsRuntimeMode(BuildMode buildMode) async =>
     _cast<bool>(await connection.sendRequest('device.supportsRuntimeMode', <String, Object>{
      'deviceId': id,
      'buildMode': buildMode.toString(),
    }));

  final bool _supportsHardwareRendering;
  @override
  Future<bool> get supportsHardwareRendering async => _supportsHardwareRendering;

  // ProxiedDevice is intended to be used with prebuilt projects. No building
  // is required, so we returns true for all projects.
  @override
  bool isSupportedForProject(FlutterProject flutterProject) => true;

  @override
  Future<bool> isAppInstalled(
    covariant ApplicationPackage app, {
    String? userIdentifier,
  }) => throw UnimplementedError();

  @override
  Future<bool> isLatestBuildInstalled(covariant ApplicationPackage app) => throw UnimplementedError();

  @override
  Future<bool> installApp(
    covariant ApplicationPackage app, {
    String? userIdentifier,
  }) => throw UnimplementedError();

  @override
  Future<bool> uninstallApp(
    covariant ApplicationPackage app, {
    String? userIdentifier,
  }) => throw UnimplementedError();

  @override
  bool isSupported() => true;

  final TargetPlatform _targetPlatform;
  @override
  Future<TargetPlatform> get targetPlatform async => _targetPlatform;
  TargetPlatform get targetPlatformSync => _targetPlatform;

  final String _sdkNameAndVersion;
  @override
  Future<String> get sdkNameAndVersion async => _sdkNameAndVersion;

  @override
  FutureOr<DeviceLogReader> getLogReader({
    covariant PrebuiltApplicationPackage? app,
    bool includePastLogs = false,
  }) => _ProxiedLogReader(connection, this, app);

  ProxiedPortForwarder? _proxiedPortForwarder;
  /// [proxiedPortForwarder] forwards a port from the remote host to local host.
  ProxiedPortForwarder get proxiedPortForwarder => _proxiedPortForwarder ??= ProxiedPortForwarder(connection, logger: _logger);

  DevicePortForwarder? _portForwarder;
  /// [portForwarder] forwards a port from the remote device to remote host, and
  /// then forward the port from remote host to local host.
  @override
  DevicePortForwarder get portForwarder => _portForwarder ??= ProxiedPortForwarder(connection, deviceId: id, logger: _logger);

  @override
  void clearLogs() => throw UnimplementedError();

  @override
  Future<LaunchResult> startApp(
    covariant PrebuiltApplicationPackage package, {
    String? mainPath,
    String? route,
    required DebuggingOptions debuggingOptions,
    Map<String, Object?> platformArgs = const <String, Object?>{},
    bool prebuiltApplication = false,
    bool ipv6 = false,
    String? userIdentifier,
  }) async {
    final Map<String, Object?> result = _cast<Map<String, Object?>>(await connection.sendRequest('device.startApp', <String, Object?>{
      'deviceId': id,
      'applicationPackageId': await applicationPackageId(package),
      'mainPath': mainPath,
      'route': route,
      'debuggingOptions': debuggingOptions.toJson(),
      'platformArgs': platformArgs,
      'prebuiltApplication': prebuiltApplication,
      'ipv6': ipv6,
      'userIdentifier': userIdentifier,
    }));
    final bool started = _cast<bool>(result['started']);
    final String? observatoryUriStr = _cast<String?>(result['observatoryUri']);
    final Uri? observatoryUri = observatoryUriStr == null ? null : Uri.parse(observatoryUriStr);
    if (started) {
      if (observatoryUri != null) {
        final int hostPort = await proxiedPortForwarder.forward(observatoryUri.port);
        return LaunchResult.succeeded(observatoryUri: observatoryUri.replace(port: hostPort));
      } else {
        return LaunchResult.succeeded();
      }
    } else {
      return LaunchResult.failed();
    }
  }

  @override
  final bool supportsHotReload;

  @override
  final bool supportsHotRestart;

  @override
  final bool supportsFlutterExit;

  @override
  final bool supportsScreenshot;

  @override
  final bool supportsFastStart;

  @override
  Future<bool> stopApp(
    covariant PrebuiltApplicationPackage app, {
    String? userIdentifier,
  }) async {
    return _cast<bool>(await connection.sendRequest('device.stopApp', <String, Object?>{
      'deviceId': id,
      'applicationPackageId': await applicationPackageId(app),
      'userIdentifier': userIdentifier,
    }));
  }

  @override
  Future<MemoryInfo> queryMemoryInfo() => throw UnimplementedError();

  @override
  Future<void> takeScreenshot(File outputFile) async {
    final String imageBase64 = _cast<String>(await connection.sendRequest('device.takeScreenshot', <String, Object?>{
      'deviceId': id,
    }));
    await outputFile.writeAsBytes(base64.decode(imageBase64));
  }

  @override
  Future<void> dispose() async {}

  final Map<String, Future<String>> _applicationPackageMap = <String, Future<String>>{};
  Future<String> applicationPackageId(PrebuiltApplicationPackage package) async {
    final File binary = package.applicationPackage as File;
    final String path = binary.absolute.path;
    if (_applicationPackageMap.containsKey(path)) {
      return _applicationPackageMap[path]!;
    }
    final String fileName = binary.basename;
    final Completer<String> idCompleter = Completer<String>();
    _applicationPackageMap[path] = idCompleter.future;

    final Map<String, Object> args = <String, Object>{'path': fileName};

    Map<String, Object?>? rollingHashResultJson;
    if (_deltaFileTransfer) {
     rollingHashResultJson = _cast<Map<String, Object?>?>(await connection.sendRequest('proxy.calculateFileHashes', args));
    }

    if (rollingHashResultJson == null) {
      // Either file not found on the remote end, or deltaFileTransfer is set to false, transfer the file directly.
      if (_deltaFileTransfer) {
        _logger.printTrace('Delta file transfer is enabled but file is not found on the remote end, do a full transfer.');
      }

      await connection.sendRequest('proxy.writeTempFile', args, await binary.readAsBytes());
    } else {
      final BlockHashes rollingHashResult = BlockHashes.fromJson(rollingHashResultJson);
      final List<FileDeltaBlock> delta = await FileTransfer().computeDelta(binary, rollingHashResult);

      // Delta is empty if the file does not need to be updated
      if (delta.isNotEmpty) {
        final List<Map<String, Object>> deltaJson = delta.map((FileDeltaBlock block) => block.toJson()).toList();
        final Uint8List buffer = await FileTransfer().binaryForRebuilding(binary, delta);

        await connection.sendRequest('proxy.updateFile', <String, Object>{
          'path': fileName,
          'delta': deltaJson,
        }, buffer);
      }
    }

    final String id = _cast<String>(await connection.sendRequest('device.uploadApplicationPackage', <String, Object>{
      'targetPlatform': getNameForTargetPlatform(_targetPlatform),
      'applicationBinary': fileName,
    }));
    idCompleter.complete(id);
    return id;
  }
}

/// A [DeviceLogReader] for a proxied device.
class _ProxiedLogReader extends DeviceLogReader {
  _ProxiedLogReader(this.connection, this.device, this.applicationPackage);

  final DaemonConnection connection;
  final ProxiedDevice device;
  final PrebuiltApplicationPackage? applicationPackage;

  @override
  String get name => device.name;

  final StreamController<String> _logLinesStreamController = StreamController<String>();
  Stream<String>? _logLines;

  String? _id;

  @override
  Stream<String> get logLines => _logLines ??= _start();

  Stream<String> _start() {
    final PrebuiltApplicationPackage? package = applicationPackage;
    final Future<String?> applicationPackageId = package != null ? device.applicationPackageId(package) : Future<String?>.value();
    final Future<String> idFuture = applicationPackageId.then((String? applicationPackageId) async =>
       _cast<String>(await connection.sendRequest('device.logReader.start', <String, Object>{
        'deviceId': device.id,
        if (applicationPackageId != null)
          'applicationPackageId': applicationPackageId,
      })));
    idFuture.then((String id) {
      _id = id;
      final Stream<String> stream = connection.listenToEvent('device.logReader.logLines.$_id').map((DaemonEventData event) => event.data! as String);
      _logLinesStreamController.addStream(stream);
    });
    return _logLinesStreamController.stream;
  }

  @override
  void dispose() {
    if (_id != null) {
      connection.sendRequest('device.logReader.stop', <String, Object?>{
        'id': _id,
      });
    }
  }
}

/// A port forwarded by a [ProxiedPortForwarder].
class _ProxiedForwardedPort extends ForwardedPort {
  _ProxiedForwardedPort(this.connection, {
    required int hostPort,
    required int devicePort,
    required this.remoteDevicePort,
    required this.deviceId,
    required this.serverSocket
  }): super(hostPort, devicePort);

  /// [DaemonConnection] used to communicate with the daemon.
  final DaemonConnection connection;

  /// The forwarded port on the remote device.
  final int? remoteDevicePort;

  /// The device identifier of the remote device.
  final String? deviceId;

  /// The [ServerSocket] that is serving the local forwarded port.
  final ServerSocket serverSocket;

  @override
  void dispose() {
    unforward();
  }

  /// Unforwards the remote port, and stops the local server.
  Future<void> unforward() async {
    await serverSocket.close();

    if (remoteDevicePort != null && deviceId != null) {
      await connection.sendRequest('device.unforward', <String, Object>{
        'deviceId': deviceId!,
        'devicePort': remoteDevicePort!,
        'hostPort': devicePort,
      });
    }
  }
}

typedef CreateSocketServer = Future<ServerSocket> Function(Logger logger, int? hostPort);

/// A [DevicePortForwarder] for a proxied device.
///
/// If [deviceId] is not null, the port forwarder forwards ports from the remote
/// device, to the remote host, and then to the local host.
///
/// If [deviceId] is null, then the port forwarder only forwards ports from the
/// remote host to the local host.
@visibleForTesting
class ProxiedPortForwarder extends DevicePortForwarder {
  ProxiedPortForwarder(this.connection, {
    String? deviceId,
    required Logger logger,
    @visibleForTesting CreateSocketServer createSocketServer = _defaultCreateServerSocket,
  }) : _logger = logger,
       _deviceId = deviceId,
       _createSocketServer = createSocketServer;

  final String? _deviceId;

  DaemonConnection connection;

  final Logger _logger;

  final CreateSocketServer _createSocketServer;

  @override
  List<ForwardedPort> get forwardedPorts => _hostPortToForwardedPorts.values.toList();

  final Map<int, _ProxiedForwardedPort> _hostPortToForwardedPorts = <int, _ProxiedForwardedPort>{};

  final List<Socket> _connectedSockets = <Socket>[];

  @override
  Future<int> forward(int devicePort, { int? hostPort }) async {
    int? remoteDevicePort;
    final String? deviceId = _deviceId;

    // If deviceId is set, we need to forward the remote device port to remote host as well.
    // And then, forward the remote host port to a local host port.
    if (deviceId != null) {
      final Map<String, Object?> result = _cast<Map<String, Object?>>(
        await connection.sendRequest('device.forward', <String, Object>{
          'deviceId': deviceId,
          'devicePort': devicePort,
        }));
      remoteDevicePort = devicePort;
      devicePort = result['hostPort']! as int;
    }

    final ServerSocket serverSocket = await _startProxyServer(devicePort, hostPort);

    _hostPortToForwardedPorts[serverSocket.port] = _ProxiedForwardedPort(
      connection,
      hostPort: serverSocket.port,
      devicePort: devicePort,
      remoteDevicePort: remoteDevicePort,
      deviceId: deviceId,
      serverSocket: serverSocket,
    );

    return serverSocket.port;
  }

  Future<ServerSocket> _startProxyServer(int devicePort, int? hostPort) async {
    final ServerSocket serverSocket = await _createSocketServer(_logger, hostPort);

    serverSocket.listen((Socket socket) async {
      final String id = _cast<String>(await connection.sendRequest('proxy.connect', <String, Object>{
        'port': devicePort,
      }));
      final Stream<List<int>> dataStream = connection.listenToEvent('proxy.data.$id').asyncExpand((DaemonEventData event) => event.binary);
      dataStream.listen(socket.add);
      final Future<DaemonEventData> disconnectFuture = connection.listenToEvent('proxy.disconnected.$id').first;
      unawaited(disconnectFuture.then((_) {
        socket.close();
      }).catchError((_) {
        // The event is not guaranteed to be sent if we initiated the disconnection.
        // Do nothing here.
      }));
      socket.listen((Uint8List data) {
        unawaited(connection.sendRequest('proxy.write', <String, Object>{
          'id': id,
        }, data)
        // TODO(srawlins): Fix this static issue,
        // https://github.com/flutter/flutter/issues/105750.
        // ignore: body_might_complete_normally_catch_error
	.catchError((Object error, StackTrace stackTrace) {
          // Log the error, but proceed normally. Network failure should not
          // crash the tool. If this is critical, the place where the connection
          // is being used would crash.
          _logger.printWarning('Write to remote proxy error: $error');
          _logger.printTrace('Write to remote proxy error: $error, stack trace: $stackTrace');
        }));
      });
      _connectedSockets.add(socket);

      unawaited(socket.done.catchError((Object error, StackTrace stackTrace) {
        // Do nothing here. Everything will be handled in the `then` block below.
        return false;
      }).whenComplete(() {
        // Send a proxy disconnect event just in case.
        unawaited(connection.sendRequest('proxy.disconnect', <String, Object>{
          'id': id,
        })
        // TODO(srawlins): Fix this static issue,
        // https://github.com/flutter/flutter/issues/105750.
        // ignore: body_might_complete_normally_catch_error
	.catchError((Object error, StackTrace stackTrace) {
          // Ignore the error here. There might be a race condition when the
          // remote end also disconnects. In any case, this request is just to
          // notify the remote end to disconnect and we should not crash when
          // there is an error here.
        }));
        _connectedSockets.remove(socket);
      }));
    }, onError: (Object error, StackTrace stackTrace) {
      _logger.printWarning('Server socket error: $error');
      _logger.printTrace('Server socket error: $error, stack trace: $stackTrace');
    });

    return serverSocket;
  }

  @override
  Future<void> unforward(ForwardedPort forwardedPort) async {
    // Look for the forwarded port entry in our own map.
    final _ProxiedForwardedPort? proxiedForwardedPort = _hostPortToForwardedPorts.remove(forwardedPort.hostPort);
    await proxiedForwardedPort?.unforward();
  }

  @override
  Future<void> dispose() async {
    for (final _ProxiedForwardedPort forwardedPort in _hostPortToForwardedPorts.values) {
      await forwardedPort.unforward();
    }

    for (final Socket socket in _connectedSockets) {
      await socket.close();
    }
  }
}

Future<ServerSocket> _defaultCreateServerSocket(Logger logger, int? hostPort) async {
  try {
    return await ServerSocket.bind(InternetAddress.loopbackIPv4, hostPort ?? 0);
  } on SocketException {
    logger.printTrace('Bind on $hostPort failed with IPv4, retrying on IPv6');
  }

  // If binding on ipv4 failed, try binding on ipv6.
  // Omit try catch here, let the failure fallthrough.
  return ServerSocket.bind(InternetAddress.loopbackIPv6, hostPort ?? 0);
}
