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

// Patch file for the dart:isolate library.

import 'dart:_js_helper' show patch;
import 'dart:_isolate_helper'
    show CapabilityImpl, IsolateNatives, ReceivePortImpl, RawReceivePortImpl;

typedef _UnaryFunction(arg);

@patch
class Isolate {
  static final _currentIsolateCache = IsolateNatives.currentIsolate;

  // `current` must be a getter, not just a final field,
  // to match the external declaration.
  @patch
  static Isolate get current => _currentIsolateCache;

  @patch
  static Future<Uri> get packageRoot {
    throw new UnsupportedError("Isolate.packageRoot");
  }

  @patch
  static Future<Uri> get packageConfig {
    throw new UnsupportedError("Isolate.packageConfig");
  }

  static Uri _packageBase = Uri.base.resolve(IsolateNatives.packagesBase);

  @patch
  static Future<Uri> resolvePackageUri(Uri packageUri) async {
    if (packageUri.scheme != 'package') return packageUri;
    return _packageBase.resolveUri(packageUri.replace(scheme: ''));
  }

  @patch
  static Future<Isolate> spawn(void entryPoint(message), var message,
      {bool paused: false,
      bool errorsAreFatal,
      SendPort onExit,
      SendPort onError}) {
    bool forcePause =
        (errorsAreFatal != null) || (onExit != null) || (onError != null);
    try {
      // Check for the type of `entryPoint` on the spawning isolate to make
      // error-handling easier.
      if (entryPoint is! _UnaryFunction) {
        throw new ArgumentError(entryPoint);
      }
      // TODO: Consider passing the errorsAreFatal/onExit/onError values
      //       as arguments to the internal spawnUri instead of setting
      //       them after the isolate has been created.
      return IsolateNatives
          .spawnFunction(entryPoint, message, paused || forcePause)
          .then((msg) {
        var isolate = new Isolate(msg[1],
            pauseCapability: msg[2], terminateCapability: msg[3]);
        if (forcePause) {
          if (errorsAreFatal != null) {
            isolate.setErrorsFatal(errorsAreFatal);
          }
          if (onExit != null) {
            isolate.addOnExitListener(onExit);
          }
          if (onError != null) {
            isolate.addErrorListener(onError);
          }
          if (!paused) {
            isolate.resume(isolate.pauseCapability);
          }
        }
        return isolate;
      });
    } catch (e, st) {
      return new Future<Isolate>.error(e, st);
    }
  }

  @patch
  static Future<Isolate> spawnUri(Uri uri, List<String> args, var message,
      {bool paused: false,
      SendPort onExit,
      SendPort onError,
      bool errorsAreFatal,
      bool checked,
      Map<String, String> environment,
      Uri packageRoot,
      Uri packageConfig,
      bool automaticPackageResolution: false}) {
    if (environment != null) throw new UnimplementedError("environment");
    if (packageRoot != null) throw new UnimplementedError("packageRoot");
    if (packageConfig != null) throw new UnimplementedError("packageConfig");
    // TODO(lrn): Figure out how to handle the automaticPackageResolution
    // parameter.
    bool forcePause =
        (errorsAreFatal != null) || (onExit != null) || (onError != null);
    try {
      if (args is List<String>) {
        for (int i = 0; i < args.length; i++) {
          if (args[i] is! String) {
            throw new ArgumentError("Args must be a list of Strings $args");
          }
        }
      } else if (args != null) {
        throw new ArgumentError("Args must be a list of Strings $args");
      }
      // TODO: Handle [packageRoot] somehow, possibly by throwing.
      // TODO: Consider passing the errorsAreFatal/onExit/onError values
      //       as arguments to the internal spawnUri instead of setting
      //       them after the isolate has been created.
      return IsolateNatives
          .spawnUri(uri, args, message, paused || forcePause)
          .then((msg) {
        var isolate = new Isolate(msg[1],
            pauseCapability: msg[2], terminateCapability: msg[3]);
        if (forcePause) {
          if (errorsAreFatal != null) {
            isolate.setErrorsFatal(errorsAreFatal);
          }
          if (onExit != null) {
            isolate.addOnExitListener(onExit);
          }
          if (onError != null) {
            isolate.addErrorListener(onError);
          }
          if (!paused) {
            isolate.resume(isolate.pauseCapability);
          }
        }
        return isolate;
      });
    } catch (e, st) {
      return new Future<Isolate>.error(e, st);
    }
  }

  @patch
  void _pause(Capability resumeCapability) {
    var message = new List(3)
      ..[0] = "pause"
      ..[1] = pauseCapability
      ..[2] = resumeCapability;
    controlPort.send(message);
  }

  @patch
  void resume(Capability resumeCapability) {
    var message = new List(2)
      ..[0] = "resume"
      ..[1] = resumeCapability;
    controlPort.send(message);
  }

  @patch
  void addOnExitListener(SendPort responsePort, {Object response}) {
    // TODO(lrn): Can we have an internal method that checks if the receiving
    // isolate of a SendPort is still alive?
    var message = new List(3)
      ..[0] = "add-ondone"
      ..[1] = responsePort
      ..[2] = response;
    controlPort.send(message);
  }

  @patch
  void removeOnExitListener(SendPort responsePort) {
    var message = new List(2)
      ..[0] = "remove-ondone"
      ..[1] = responsePort;
    controlPort.send(message);
  }

  @patch
  void setErrorsFatal(bool errorsAreFatal) {
    var message = new List(3)
      ..[0] = "set-errors-fatal"
      ..[1] = terminateCapability
      ..[2] = errorsAreFatal;
    controlPort.send(message);
  }

  @patch
  void kill({int priority: BEFORE_NEXT_EVENT}) {
    controlPort.send(["kill", terminateCapability, priority]);
  }

  @patch
  void ping(SendPort responsePort, {Object response, int priority: IMMEDIATE}) {
    var message = new List(4)
      ..[0] = "ping"
      ..[1] = responsePort
      ..[2] = priority
      ..[3] = response;
    controlPort.send(message);
  }

  @patch
  void addErrorListener(SendPort port) {
    var message = new List(2)
      ..[0] = "getErrors"
      ..[1] = port;
    controlPort.send(message);
  }

  @patch
  void removeErrorListener(SendPort port) {
    var message = new List(2)
      ..[0] = "stopErrors"
      ..[1] = port;
    controlPort.send(message);
  }
}

/** Default factory for receive ports. */
@patch
class ReceivePort {
  @patch
  factory ReceivePort() = ReceivePortImpl;

  @patch
  factory ReceivePort.fromRawReceivePort(RawReceivePort rawPort) {
    return new ReceivePortImpl.fromRawReceivePort(rawPort);
  }
}

@patch
class RawReceivePort {
  @patch
  factory RawReceivePort([void handler(event)]) {
    return new RawReceivePortImpl(handler);
  }
}

@patch
class Capability {
  @patch
  factory Capability() = CapabilityImpl;
}
