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

// VMOptions=--enable-isolate-groups --experimental-enable-isolate-groups-jit
// VMOptions=--no-enable-isolate-groups

library MandelIsolateTest;

import 'dart:async';
import 'dart:isolate';
import 'dart:math';

import 'package:async_helper/async_helper.dart';
import 'package:expect/expect.dart';

const TERMINATION_MESSAGE = -1;
const N = 100;
const ISOLATES = 20;

void main([args, port]) {
  final state = new MandelbrotState();
  asyncStart();
  state._validated.future.then((result) {
    Expect.isTrue(result);
    asyncEnd();
  });
  for (int i = 0; i < min(ISOLATES, N); i++) state.startClient(i);
}

class MandelbrotState {
  MandelbrotState() {
    _result = new List<List<int>>(N);
    _lineProcessedBy = new List<LineProcessorClient>(N);
    _sent = 0;
    _missing = N;
    _validated = new Completer<bool>();
  }

  void startClient(int id) {
    assert(_sent < N);
    int line = _sent++;
    LineProcessorClient.create(this, id).then((final client) {
      client.processLine(line);
    });
  }

  void notifyProcessedLine(LineProcessorClient client, int y, List<int> line) {
    assert(_result[y] == null);
    _result[y] = line;
    _lineProcessedBy[y] = client;

    if (_sent != N) {
      client.processLine(_sent++);
    } else {
      client.shutdown();
    }

    // If all lines have been computed, validate the result.
    if (--_missing == 0) {
      _printResult();
      _validateResult();
    }
  }

  void _validateResult() {
    // TODO(ngeoffray): Implement this.
    _validated.complete(true);
  }

  void _printResult() {
    var output = new StringBuffer();
    for (int i = 0; i < _result.length; i++) {
      List<int> line = _result[i];
      for (int j = 0; j < line.length; j++) {
        if (line[j] < 10) output.write("0");
        output.write(line[j]);
      }
      output.write("\n");
    }
    // print(output);
  }

  List<List<int>> _result;
  List<LineProcessorClient> _lineProcessedBy;
  int _sent;
  int _missing;
  Completer<bool> _validated;
}

class LineProcessorClient {
  MandelbrotState _state;
  int _id;
  SendPort _port;

  LineProcessorClient(this._state, this._id, this._port);

  static Future<LineProcessorClient> create(MandelbrotState state, int id) {
    ReceivePort reply = new ReceivePort();
    return Isolate.spawn(processLines, reply.sendPort).then((_) {
      return reply.first.then((port) {
        return new LineProcessorClient(state, id, port);
      });
    });
  }

  void processLine(int y) {
    ReceivePort reply = new ReceivePort();
    _port.send([y, reply.sendPort]);
    reply.first.then((message) {
      _state.notifyProcessedLine(this, y, message as List<int>);
    });
  }

  void shutdown() {
    _port.send(TERMINATION_MESSAGE);
  }
}

List<int> processLine(int y) {
  double inverseN = 2.0 / N;
  double Civ = y * inverseN - 1.0;
  List<int> result = new List<int>(N);
  for (int x = 0; x < N; x++) {
    double Crv = x * inverseN - 1.5;

    double Zrv = Crv;
    double Ziv = Civ;

    double Trv = Crv * Crv;
    double Tiv = Civ * Civ;

    int i = 49;
    do {
      Ziv = (Zrv * Ziv) + (Zrv * Ziv) + Civ;
      Zrv = Trv - Tiv + Crv;

      Trv = Zrv * Zrv;
      Tiv = Ziv * Ziv;
    } while (((Trv + Tiv) <= 4.0) && (--i > 0));

    result[x] = i;
  }
  return result;
}

void processLines(SendPort replyPort) {
  ReceivePort port = new ReceivePort();
  port.listen((message) {
    if (message != TERMINATION_MESSAGE) {
      int line = message[0];
      SendPort replyTo = message[1];
      replyTo.send(processLine(line));
    } else {
      port.close();
    }
  });
  replyPort.send(port.sendPort);
}
