/*
 * Copyright (c) 2017, the Dart project authors.  Please see the AUTHORS file
 * for details. All rights reserved. Use of this source code is governed by a
 * BSD-style license that can be found in the LICENSE file.
 *
 * @author a.semenov@unipro.ru
 */
import "dart:async";
import "dart:isolate";

Duration ONE_SECOND = new Duration(seconds: 1);
Duration TWO_SECONDS = new Duration(seconds: 2);
Duration THREE_SECONDS = new Duration(seconds: 3);

/**
 * send ping with given payload to given isolate. Returns the response,
 * received from the isolate, which should be equal to payload. If timeout is
 * specified and response is not received during the timeout interval, then
 * value "timeout" is returned.
 */
Future ping(Isolate isolate, payload, [Duration? timeout]) {
  ReceivePort pingPort = new ReceivePort();
  Future result = pingPort.first;
  isolate.ping(pingPort.sendPort, response: payload);
  if (timeout != null) {
    result = result.timeout(timeout, onTimeout: () {
      pingPort.close();
      return "timeout";
    });
  }
  return result;
}

/**
 * Basement for Echo and Error servers
 */
abstract class Server {
  static const String _STOP = "!stop";

  Isolate isolate;
  SendPort sendPort;

  Server(this.isolate, this.sendPort);

  void requestStop() {
    sendPort.send(_STOP);
  }

  Future stop() {
    ReceivePort exitPort = new ReceivePort();
    isolate.addOnExitListener(exitPort.sendPort);
    Future result = exitPort.first; // subscribe first
    requestStop();
    return result;
  }

  Future kill({int priority: Isolate.beforeNextEvent}) {
    ReceivePort exitPort = new ReceivePort();
    isolate.addOnExitListener(exitPort.sendPort);
    Future result = exitPort.first; // subscribe first
    isolate.kill(priority: priority);
    return result;
  }

  void send(message) {
    sendPort.send(message);
  }
}

/**
 * Utility class, that helps to spawn isolates, which sole purpose is
 * to generate errors.
 */
class ErrorServer extends Server {
  ErrorServer(Isolate isolate, SendPort sendPort) : super(isolate, sendPort);

  static Future<ErrorServer> spawn(
      {bool errorsAreFatal = true, SendPort? onExit, SendPort? onError}) async {
    ReceivePort receivePort = new ReceivePort();
    Isolate isolate = await Isolate.spawn(
        isolateEntryPoint, receivePort.sendPort,
        errorsAreFatal: errorsAreFatal, onExit: onExit, onError: onError);
    SendPort sendPort = await receivePort.first;
    return new ErrorServer(isolate, sendPort);
  }

  static void isolateEntryPoint(SendPort sendPort) {
    ReceivePort receivePort = new ReceivePort();
    int i = 0;
    StreamSubscription? ss;
    ss = receivePort.listen((x) {
      if (x == Server._STOP) {
        ss?.cancel();
        receivePort.close();
      } else {
        throw i++;
      }
    });
    sendPort.send(receivePort.sendPort);
  }

  void generateError() {
    sendPort.send("error");
  }
}

/**
 * Utility class, that helps to spawn isolates, which sole purpose is
 * to send back the received data
 */
class EchoServer extends Server {
  EchoServer(Isolate isolate, SendPort sendPort) : super(isolate, sendPort);

  static Future<EchoServer> spawn(SendPort dataSendPort,
      {bool errorsAreFatal = true, SendPort? onExit, SendPort? onError}) async {
    ReceivePort receivePort = new ReceivePort();
    Isolate isolate = await Isolate.spawn(
        isolateEntryPoint, [receivePort.sendPort, dataSendPort],
        errorsAreFatal: errorsAreFatal, onExit: onExit, onError: onError);
    SendPort sendPort = await receivePort.first;
    return new EchoServer(isolate, sendPort);
  }

  static void isolateEntryPoint(List<SendPort> sendPort) {
    ReceivePort receivePort = new ReceivePort();
    StreamSubscription? ss;
    ss = receivePort.listen((dynamic x) {
      if (x == Server._STOP) {
        ss?.cancel();
        receivePort.close();
      } else if ((x is List) && (x.length == 2) && (x[0] is SendPort)) {
        x[0].send(x[1]);
      } else {
        sendPort[1].send(x);
      }
    });
    sendPort[0].send(receivePort.sendPort);
  }

  Future<dynamic> ping(Object message,
      [Duration? timeout, Object? timeoutResponse]) {
    ReceivePort receivePort = new ReceivePort();
    Future<dynamic> result = receivePort.first;
    sendPort.send([receivePort.sendPort, message]);
    if (timeout != null) {
      result = result.timeout(timeout, onTimeout: () {
        receivePort.close();
        return timeoutResponse;
      });
    }
    return result;
  }
}
