// Copyright (c) 2020, 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.

// @dart = 2.9

import 'dart:async';
import 'dart:io';
import 'dart:isolate';

export '../../../../../benchmarks/IsolateFibonacci/dart2/IsolateFibonacci.dart'
  show fibonacciRecursive;

final bool isDebugMode = Platform.script.path.contains('Debug');
final bool isSimulator = Platform.script.path.contains('SIM');
final bool isArtificialReloadMode = Platform.executableArguments.any((arg) => [
      '--hot-reload-rollback-test-mode',
      '--hot-reload-test-mode'
    ].contains(arg));

// Implements recursive summation:
//   sum(n) => n == 0 ? 0
//                    : 1 + sum(n-1);
Future sumRecursive(List args) async {
  final SendPort port = args[0];
  final n = args[1];
  if (n == 0) {
    port.send(0);
  } else {
    final rp = ReceivePort();
    await Isolate.spawn(sumRecursive, [rp.sendPort, n - 1]);
    port.send(1 + (await rp.first));
  }
}

// Implements recursive summation via tail calls:
//   sum(n, s) => n == 0 ? s
//                       : sum(n-1, s+1);
Future sumRecursiveTailCall(List args) async {
  final SendPort port = args[0];
  final n = args[1];
  final s = args[2];
  if (n == 0) {
    port.send(s);
  } else {
    await Isolate.spawn(sumRecursiveTailCall, [port, n - 1, s + 1]);
  }
}

enum Command { kRun, kRunAndClose, kClose }

abstract class RingElement {
  Future run(SendPort nextNeighbour, StreamIterator prevNeighbour);
}

class Ring {
  final int size;
  final List<StreamIterator> receivePorts;
  final List<SendPort> controlSendPorts;
  final List<SendPort> dataSendPorts;

  Ring(this.size, this.receivePorts, this.controlSendPorts, this.dataSendPorts);

  static Future<Ring> create(int n) async {
    final ports = <StreamIterator>[];
    final spawnFutures = <Future>[];
    for (int i = 0; i < n; ++i) {
      final port = ReceivePort();
      ports.add(StreamIterator(port));
      spawnFutures
          .add(Isolate.spawn(_ringEntry, port.sendPort, debugName: 'ring-$i'));
    }
    await Future.wait(spawnFutures);
    final controlSendPorts = <SendPort>[];
    final dataSendPorts = <SendPort>[];
    for (int i = 0; i < n; ++i) {
      final si = ports[i];
      await si.moveNext();
      controlSendPorts.add(si.current[0]);
      dataSendPorts.add(si.current[1]);
    }

    return Ring(n, ports, controlSendPorts, dataSendPorts);
  }

  static Future _ringEntry(SendPort port) async {
    final rpControl = ReceivePort();
    final rpData = ReceivePort();
    port.send([rpControl.sendPort, rpData.sendPort]);

    final siControl = StreamIterator(rpControl);
    final siData = StreamIterator(rpData);
    while (await siControl.moveNext()) {
      final List args = siControl.current;
      final command = args[0];
      switch (command) {
        case Command.kRun:
          final RingElement re = args[1];
          final SendPort nextNeighbor = args[2];
          port.send(await re.run(nextNeighbor, siData));
          break;
        case Command.kRunAndClose:
          final RingElement re = args[1];
          final SendPort nextNeighbor = args[2];
          Isolate.exit(port, await re.run(nextNeighbor, siData));
          break;
        case Command.kClose:
          port.send('done');
          rpControl.close();
          rpData.close();
          return;
      }
    }

    throw 'bug';
  }

  Future<List> run(RingElement buildRingElement(int id)) async {
    for (int i = 0; i < size; i++) {
      final nextNeighbor = dataSendPorts[(i + 1) % size];
      controlSendPorts[i]
          .send([Command.kRun, buildRingElement(i), nextNeighbor]);
    }

    final results = await Future.wait(receivePorts.map((si) async {
      await si.moveNext();
      return si.current;
    }).toList());

    return results;
  }

  Future<List> runAndClose(RingElement buildRingElement(int id)) async {
    for (int i = 0; i < size; i++) {
      final nextNeighbor = dataSendPorts[(i + 1) % size];
      controlSendPorts[i]
          .send([Command.kRunAndClose, buildRingElement(i), nextNeighbor]);
    }

    final results = await Future.wait(receivePorts.map((si) async {
      await si.moveNext();
      return si.current;
    }).toList());
    finalize();
    return results;
  }

  Future close() async {
    for (int i = 0; i < size; i++) {
      controlSendPorts[i].send([Command.kClose]);
    }
    final results = await Future.wait(receivePorts.map((si) async {
      await si.moveNext();
      return si.current;
    }).toList());
    finalize();
    return results;
  }

  void finalize() async {
    for (int i = 0; i < size; ++i) {
      await receivePorts[i].cancel();
    }
  }
}

class Tree {
  final int value;
  final Tree left;
  final Tree right;

  Tree(this.value, this.left, this.right);

  int get sum => value + (left?.sum ?? 0) + (right?.sum ?? 0);

  Tree get copy => Tree(value, left?.copy, right?.copy);
}

Tree buildTree(int n) {
  if (n == 0) return Tree(0, null, null);
  Tree left = Tree(0, null, null);
  Tree right = Tree(0, null, null);
  for (int i = 1; i < n; ++i) {
    left = Tree(1, left, right);
    right = left.copy;
  }
  return Tree(1, left, right);
}
