// Copyright 2013 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.
part of dart.ui;

/// Runs [computation] on the platform thread and returns the result.
///
/// This may run the computation on a separate isolate. That isolate will be
/// reused for subsequent [runOnPlatformThread] calls. This means that global
/// state is maintained in that isolate between calls.
///
/// The [computation] and any state it captures may be sent to that isolate.
/// See [SendPort.send] for information about what types can be sent.
///
/// If [computation] is asynchronous (returns a `Future<R>`) then
/// that future is awaited in the new isolate, completing the entire
/// asynchronous computation, before returning the result.
///
/// If [computation] throws, the `Future` returned by this function completes
/// with that error.
///
/// The [computation] function and its result (or error) must be
/// sendable between isolates. Objects that cannot be sent include open
/// files and sockets (see [SendPort.send] for details).
///
/// This method can only be invoked from the main isolate.
///
/// This API is currently experimental.
Future<R> runOnPlatformThread<R>(FutureOr<R> Function() computation) {
  if (!_platformIsolatesEnabled) {
    throw UnsupportedError(
        'Platform thread isolates are not supported by this platform.');
  }
  if (isRunningOnPlatformThread) {
    return Future<R>(computation);
  }
  final SendPort? sendPort = _platformRunnerSendPort;
  if (sendPort != null) {
    return _sendComputation(sendPort, computation);
  } else {
    return (_platformRunnerSendPortFuture ??= _spawnPlatformIsolate())
        .then((SendPort port) => _sendComputation(port, computation));
  }
}

SendPort? _platformRunnerSendPort;
Future<SendPort>? _platformRunnerSendPortFuture;
final Map<int, Completer<Object?>> _pending = <int, Completer<Object?>>{};
int _nextId = 0;

Future<SendPort> _spawnPlatformIsolate() {
  final Completer<SendPort> sendPortCompleter = Completer<SendPort>();
  final RawReceivePort receiver = RawReceivePort()..keepIsolateAlive = false;
  receiver.handler = (Object? message) {
    if (message == null) {
      // This is the platform isolate's onExit handler.
      // This shouldn't really happen, since Isolate.exit is disabled, the
      // pause and terminate capabilities aren't provided to the parent
      // isolate, and errors are fatal is false. But if the isolate does
      // shutdown unexpectedly, clear the singleton so we can create another.
      for (final Completer<Object?> completer in _pending.values) {
        completer.completeError(RemoteError(
            'PlatformIsolate shutdown unexpectedly',
            StackTrace.empty.toString()));
      }
      _pending.clear();
      _platformRunnerSendPort = null;
      _platformRunnerSendPortFuture = null;
    } else if (message is _PlatformIsolateReadyMessage) {
      _platformRunnerSendPort = message.computationPort;
      sendPortCompleter.complete(message.computationPort);
    } else if (message is _ComputationResult) {
      final Completer<Object?> resultCompleter = _pending.remove(message.id)!;
      final Object? remoteStack = message.remoteStack;
      final Object? remoteError = message.remoteError;
      if (remoteStack != null) {
        if (remoteStack is StackTrace) {
          // Typed error.
          resultCompleter.completeError(remoteError!, remoteStack);
        } else {
          // onError handler message, uncaught async error.
          // Both values are strings, so calling `toString` is efficient.
          final RemoteError error =
              RemoteError(remoteError!.toString(), remoteStack.toString());
          resultCompleter.completeError(error, error.stackTrace);
        }
      } else {
        resultCompleter.complete(message.result);
      }
    } else {
      // We encountered an error while starting the new isolate.
      if (!sendPortCompleter.isCompleted) {
        sendPortCompleter.completeError(
            IsolateSpawnException('Unable to spawn isolate: $message'));
        return;
      }
      // This shouldn't happen.
      throw IsolateSpawnException(
          "Internal error: unexpected message: '$message'");
    }
  };
  final Isolate parentIsolate = Isolate.current;
  final SendPort sendPort = receiver.sendPort;
  try {
    _nativeSpawn(() => _platformIsolateMain(parentIsolate, sendPort));
  } on Object {
    receiver.close();
    rethrow;
  }
  return sendPortCompleter.future;
}

Future<R> _sendComputation<R>(
    SendPort port, FutureOr<R> Function() computation) {
  final int id = ++_nextId;
  final Completer<R> resultCompleter = Completer<R>();
  _pending[id] = resultCompleter;
  port.send(_ComputationRequest(id, computation));
  return resultCompleter.future;
}

void _safeSend(SendPort sendPort, int id, Object? result, Object? error,
    Object? stackTrace) {
  try {
    sendPort.send(_ComputationResult(id, result, error, stackTrace));
  } catch (sendError, sendStack) {
    sendPort.send(_ComputationResult(id, null, sendError, sendStack));
  }
}

void _platformIsolateMain(Isolate parentIsolate, SendPort sendPort) {
  final RawReceivePort computationPort = RawReceivePort();
  computationPort.handler = (_ComputationRequest? message) {
    if (message == null) {
      // The parent isolate has shutdown. Allow this isolate to shutdown.
      computationPort.keepIsolateAlive = false;
      return;
    }

    late final FutureOr<Object?> potentiallyAsyncResult;
    try {
      potentiallyAsyncResult = message.computation();
    } catch (e, s) {
      _safeSend(sendPort, message.id, null, e, s);
      return;
    }

    if (potentiallyAsyncResult is Future<Object?>) {
      potentiallyAsyncResult.then((Object? result) {
        _safeSend(sendPort, message.id, result, null, null);
      }, onError: (Object? e, Object? s) {
        _safeSend(sendPort, message.id, null, e, s ?? StackTrace.empty);
      });
    } else {
      _safeSend(sendPort, message.id, potentiallyAsyncResult, null, null);
    }
  };
  Isolate.current.addOnExitListener(sendPort);
  parentIsolate.addOnExitListener(computationPort.sendPort);
  sendPort.send(_PlatformIsolateReadyMessage(computationPort.sendPort));
}

@Native<Void Function(Handle)>(symbol: 'PlatformIsolateNativeApi::Spawn')
external void _nativeSpawn(Function entryPoint);

/// Whether the current isolate is running on the platform thread.
final bool isRunningOnPlatformThread = _isRunningOnPlatformThread();

@Native<Bool Function()>(
    symbol: 'PlatformIsolateNativeApi::IsRunningOnPlatformThread', isLeaf: true)
external bool _isRunningOnPlatformThread();

class _PlatformIsolateReadyMessage {
  _PlatformIsolateReadyMessage(this.computationPort);

  final SendPort computationPort;
}

class _ComputationRequest {
  _ComputationRequest(this.id, this.computation);

  final int id;
  final FutureOr<Object?> Function() computation;
}

class _ComputationResult {
  _ComputationResult(this.id, this.result, this.remoteError, this.remoteStack);

  final int id;
  final Object? result;
  final Object? remoteError;
  final Object? remoteStack;
}
