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

import "dart:isolate";
import "dart:async";
import "package:expect/expect.dart";
import "package:async_helper/async_helper.dart";

void toplevel(port, message) {
  port.send("toplevel:$message");
}

Function createFuncToplevel() => (p, m) {
      p.send(m);
    };

class C {
  Function initializer;
  Function body;
  C()
      : initializer = ((p, m) {
          throw "initializer";
        }) {
    body = (p, m) {
      throw "body";
    };
  }
  static void staticFunc(port, message) {
    port.send("static:$message");
  }

  static Function createFuncStatic() => (p, m) {
        throw "static expr";
      };
  void instanceMethod(p, m) {
    throw "instanceMethod";
  }

  Function createFuncMember() => (p, m) {
        throw "instance expr";
      };
  void call(n, p) {
    throw "C";
  }
}

class Callable {
  void call(p, m) {
    p.send(["callable", m]);
  }
}

void main() {
  asyncStart();

  // Sendables are top-level functions and static functions only.
  testSendable("toplevel", toplevel);
  testSendable("static", C.staticFunc);
  // Unsendables are any closure - instance methods or function expression.
  var c = new C();
  testUnsendable("instance method", c.instanceMethod);
  testUnsendable("static context expression", createFuncToplevel());
  testUnsendable("static context expression", C.createFuncStatic());
  testUnsendable("initializer context expression", c.initializer);
  testUnsendable("constructor context expression", c.body);
  testUnsendable("instance method context expression", c.createFuncMember());

  // The result of `toplevel.call` and `staticFunc.call` may or may not be
  // identical to `toplevel` and `staticFunc` respectively. If they are not
  // equal, they may or may not be considered toplevel/static functions anyway,
  // and therefore sendable. The VM and dart2js currently disagree on whether
  // `toplevel` and `toplevel.call` are identical, both allow them to be sent.
  // If this is ever specified to something else, use:
  //     testUnsendable("toplevel.call", toplevel.call);
  //     testUnsendable("static.call", C.staticFunc.call);
  // instead.
  // These two tests should be considered canaries for accidental behavior
  // change rather than requirements.
  testSendable("toplevel", toplevel.call);
  testSendable("static", C.staticFunc.call);

  // Callable objects are sendable if general objects are (VM yes, dart2js no).
  // It's unspecified whether arbitrary objects can be sent. If it is specified,
  // add a test that `new Callable()` is either sendable or unsendable.

  // The call method of a callable object is a closure holding the object,
  // not a top-level or static function, so it should be blocked, just as
  // a normal method.
  testUnsendable("callable object", new Callable().call);

  asyncEnd();
  return;
}

// Create a receive port that expects exactly one message.
// Pass the message to `callback` and return the sendPort.
SendPort singleMessagePort(callback) {
  var p;
  p = new RawReceivePort((v) {
    p.close();
    callback(v);
  });
  return p.sendPort;
}

// A singleMessagePort that expects the message to be a specific value.
SendPort expectMessagePort(message) {
  asyncStart();
  return singleMessagePort((v) {
    Expect.equals(message, v);
    asyncEnd();
  });
}

void testSendable(name, func) {
  // Function as spawn message.
  Isolate.spawn(callFunc, [func, expectMessagePort("$name:spawn"), "spawn"]);

  // Send function to same isolate.
  var reply = expectMessagePort("$name:direct");
  singleMessagePort(callFunc).send([func, reply, "direct"]);

  // Send function to other isolate, call it there.
  reply = expectMessagePort("$name:other isolate");
  callPort().then((p) {
    p.send([func, reply, "other isolate"]);
  });

  // Round-trip function trough other isolate.
  echoPort((roundtripFunc) {
    Expect.identical(func, roundtripFunc, "$name:send through isolate");
  }).then((port) {
    port.send(func);
  });
}

// Creates a new isolate and a pair of ports that expect a single message
// to be sent to the other isolate and back to the callback function.
Future<SendPort> echoPort(callback(value)) {
  Completer<SendPort> completer = new Completer<SendPort>();
  SendPort replyPort = singleMessagePort(callback);
  RawReceivePort initPort;
  initPort = new RawReceivePort((p) {
    completer.complete(p);
    initPort.close();
  });
  return Isolate.spawn(_echo, [replyPort, initPort.sendPort]).then(
      (isolate) => completer.future);
}

void _echo(msg) {
  var replyPort = msg[0];
  RawReceivePort requestPort;
  requestPort = new RawReceivePort((msg) {
    replyPort.send(msg);
    requestPort.close(); // Single echo only.
  });
  msg[1].send(requestPort.sendPort);
}

// Creates other isolate that waits for a single message, `msg`, on the returned
// port, and executes it as `msg[0](msg[1],msg[2])` in the other isolate.
Future<SendPort> callPort() {
  Completer<SendPort> completer = new Completer<SendPort>();
  SendPort initPort = singleMessagePort(completer.complete);
  return Isolate.spawn(_call, initPort).then((_) => completer.future);
}

void _call(initPort) {
  initPort.send(singleMessagePort(callFunc));
}

void testUnsendable(name, func) {
  asyncStart();
  Isolate.spawn(nop, func).then((v) => throw "allowed spawn direct?",
      onError: (e, s) {
    asyncEnd();
  });
  asyncStart();
  Isolate.spawn(nop, [func]).then((v) => throw "allowed spawn wrapped?",
      onError: (e, s) {
    asyncEnd();
  });

  asyncStart();
  var noReply = new RawReceivePort((_) {
    throw "Unexpected message: $_";
  });
  Expect.throws(() {
    noReply.sendPort.send(func);
  }, null, "send direct");
  Expect.throws(() {
    noReply.sendPort.send([func]);
  }, null, "send wrapped");
  scheduleMicrotask(() {
    noReply.close();
    asyncEnd();
  });

  // Try sending through other isolate.
  asyncStart();
  echoPort((v) {
    Expect.equals(0, v);
  }).then((p) {
    try {
      p.send(func);
    } finally {
      p.send(0); //   Closes echo port.
    }
  }).then((p) => throw "unreachable 2", onError: (e, s) {
    asyncEnd();
  });
}

void nop(_) {}

void callFunc(message) {
  message[0](message[1], message[2]);
}
