// 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.

import 'dart:async';
import 'dart:isolate';
import 'dart:ui';

import 'package:litetest/litetest.dart';

const int kErrorCode = -1;
const int kStartCode = 0;
const int kCloseCode = 1;
const int kDeletedCode = 2;

class IsolateSpawnInfo {
  IsolateSpawnInfo(this.sendPort, this.portName);

  final SendPort sendPort;
  final String portName;
}

void isolateSpawnEntrypoint(IsolateSpawnInfo info) {
  final SendPort port = info.sendPort;
  final String portName = info.portName;
  void sendHelper(int code, [String message = '']) {
    port.send(<dynamic>[code, message]);
  }

  final SendPort? shared = IsolateNameServer.lookupPortByName(portName);
  if (shared == null) {
    sendHelper(kErrorCode, 'Could not find port: $portName');
    return;
  }

  // ack that the SendPort lookup was successful.
  sendHelper(kStartCode);

  shared.send(portName);
  sendHelper(kCloseCode);

  // We'll fail if the ReceivePort's callback is called more than once. Try to
  // send another message to ensure we don't crash.
  shared.send('garbage');

  final bool result = IsolateNameServer.removePortNameMapping(portName);
  if (result) {
    sendHelper(kDeletedCode);
  } else {
    sendHelper(kErrorCode, 'Was unable to remove mapping for $portName');
  }
}

void main() {
  test('simple isolate name server', () {
    const String portName = 'foobar1';
    try {
      // Mapping for 'foobar' isn't set. Check these cases to ensure correct
      // negative response.
      expect(IsolateNameServer.lookupPortByName(portName), isNull);
      expect(IsolateNameServer.removePortNameMapping(portName), isFalse);

      // Register a SendPort.
      final ReceivePort receivePort = ReceivePort();
      final SendPort sendPort = receivePort.sendPort;
      expect(IsolateNameServer.registerPortWithName(sendPort, portName), isTrue);
      expect(IsolateNameServer.lookupPortByName(portName), sendPort);

      // Check we can't register the same name twice.
      final ReceivePort receivePort2 = ReceivePort();
      final SendPort sendPort2 = receivePort2.sendPort;
      expect(
          IsolateNameServer.registerPortWithName(sendPort2, portName), isFalse);
      expect(IsolateNameServer.lookupPortByName(portName), sendPort);

      // Remove the mapping.
      expect(IsolateNameServer.removePortNameMapping(portName), isTrue);
      expect(IsolateNameServer.lookupPortByName(portName), isNull);

      // Ensure registering a new port with the old name returns the new port.
      expect(
          IsolateNameServer.registerPortWithName(sendPort2, portName), isTrue);
      expect(IsolateNameServer.lookupPortByName(portName), sendPort2);

      // Close so the test runner doesn't hang.
      receivePort.close();
      receivePort2.close();
    } finally {
      IsolateNameServer.removePortNameMapping(portName);
    }
  });

  test('isolate name server multi-isolate', () async {
    const String portName = 'foobar2';
    try {
      // Register our send port with the name server.
      final ReceivePort receivePort = ReceivePort();
      final SendPort sendPort = receivePort.sendPort;
      expect(IsolateNameServer.registerPortWithName(sendPort, portName), isTrue);

      // Test driver.
      final ReceivePort testReceivePort = ReceivePort();
      final Completer<void> testPortCompleter = Completer<void>();
      testReceivePort.listen(expectAsync1<void, dynamic>((dynamic response) {
        final int code = response[0] as int;
        final String message = response[1] as String;
        switch (code) {
          case kStartCode:
            break;
          case kCloseCode:
            receivePort.close();
            break;
          case kDeletedCode:
            expect(IsolateNameServer.lookupPortByName(portName), isNull);
            // Test is done, close the last ReceivePort.
            testReceivePort.close();
            break;
          case kErrorCode:
            throw message;
          default:
            throw 'UNREACHABLE';
        }
      }, count: 3), onDone: testPortCompleter.complete);

      final Completer<void> portCompleter = Completer<void>();
      receivePort.listen(expectAsync1<void, dynamic>((dynamic message) {
        // If we don't get this message, we timeout and fail.
        expect(message, portName);
      }), onDone: portCompleter.complete);

      // Run the test.
      await Isolate.spawn(
        isolateSpawnEntrypoint,
        IsolateSpawnInfo(testReceivePort.sendPort, portName),
      );
      await testPortCompleter.future;
      await portCompleter.future;
    } finally {
      IsolateNameServer.removePortNameMapping(portName);
    }
  });
}
