// Copyright 2014 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

define("mojo/public/js/router", [
  "mojo/public/js/connector",
  "mojo/public/js/core",
  "mojo/public/js/interface_types",
  "mojo/public/js/lib/interface_endpoint_handle",
  "mojo/public/js/lib/pipe_control_message_handler",
  "mojo/public/js/lib/pipe_control_message_proxy",
  "mojo/public/js/validator",
  "timer",
], function(connector, core, types, interfaceEndpointHandle,
      controlMessageHandler, controlMessageProxy, validator, timer) {

  var Connector = connector.Connector;
  var PipeControlMessageHandler =
      controlMessageHandler.PipeControlMessageHandler;
  var PipeControlMessageProxy = controlMessageProxy.PipeControlMessageProxy;
  var Validator = validator.Validator;
  var InterfaceEndpointHandle = interfaceEndpointHandle.InterfaceEndpointHandle;

  /**
   * The state of |endpoint|. If both the endpoint and its peer have been
   * closed, removes it from |endpoints_|.
   * @enum {string}
   */
  var EndpointStateUpdateType = {
    ENDPOINT_CLOSED: 'endpoint_closed',
    PEER_ENDPOINT_CLOSED: 'peer_endpoint_closed'
  };

  function check(condition, output) {
    if (!condition) {
      // testharness.js does not rethrow errors so the error stack needs to be
      // included as a string in the error we throw for debugging layout tests.
      throw new Error((new Error()).stack);
    }
  }

  function InterfaceEndpoint(router, interfaceId) {
    this.router_ = router;
    this.id = interfaceId;
    this.closed = false;
    this.peerClosed = false;
    this.handleCreated = false;
    this.disconnectReason = null;
    this.client = null;
  }

  InterfaceEndpoint.prototype.sendMessage = function(message) {
    message.setInterfaceId(this.id);
    return this.router_.connector_.accept(message);
  };

  function Router(handle, setInterfaceIdNamespaceBit) {
    if (!core.isHandle(handle)) {
      throw new Error("Router constructor: Not a handle");
    }
    if (setInterfaceIdNamespaceBit === undefined) {
      setInterfaceIdNamespaceBit = false;
    }

    this.connector_ = new Connector(handle);

    this.connector_.setIncomingReceiver({
        accept: this.accept.bind(this),
    });
    this.connector_.setErrorHandler({
        onError: this.onPipeConnectionError.bind(this),
    });

    this.setInterfaceIdNamespaceBit_ = setInterfaceIdNamespaceBit;
    // |cachedMessageData| caches infomation about a message, so it can be
    // processed later if a client is not yet attached to the target endpoint.
    this.cachedMessageData = null;
    this.controlMessageHandler_ = new PipeControlMessageHandler(this);
    this.controlMessageProxy_ = new PipeControlMessageProxy(this.connector_);
    this.nextInterfaceIdValue_ = 1;
    this.encounteredError_ = false;
    this.endpoints_ = new Map();
  }

  Router.prototype.associateInterface = function(handleToSend) {
    if (!handleToSend.pendingAssociation()) {
      return types.kInvalidInterfaceId;
    }

    var id = 0;
    do {
      if (this.nextInterfaceIdValue_ >= types.kInterfaceIdNamespaceMask) {
        this.nextInterfaceIdValue_ = 1;
      }
      id = this.nextInterfaceIdValue_++;
      if (this.setInterfaceIdNamespaceBit_) {
        id += types.kInterfaceIdNamespaceMask;
      }
    } while (this.endpoints_.has(id));

    var endpoint = new InterfaceEndpoint(this, id);
    this.endpoints_.set(id, endpoint);
    if (this.encounteredError_) {
      this.updateEndpointStateMayRemove(endpoint,
          EndpointStateUpdateType.PEER_ENDPOINT_CLOSED);
    }
    endpoint.handleCreated = true;

    if (!handleToSend.notifyAssociation(id, this)) {
      // The peer handle of |handleToSend|, which is supposed to join this
      // associated group, has been closed.
      this.updateEndpointStateMayRemove(endpoint,
          EndpointStateUpdateType.ENDPOINT_CLOSED);

      pipeControlMessageproxy.notifyPeerEndpointClosed(id,
          handleToSend.disconnectReason());
    }

    return id;
  };

  Router.prototype.attachEndpointClient = function(
      interfaceEndpointHandle, interfaceEndpointClient) {
    check(types.isValidInterfaceId(interfaceEndpointHandle.id()));
    check(interfaceEndpointClient);

    var endpoint = this.endpoints_.get(interfaceEndpointHandle.id());
    check(endpoint);
    check(!endpoint.client);
    check(!endpoint.closed);
    endpoint.client = interfaceEndpointClient;

    if (endpoint.peerClosed) {
      timer.createOneShot(0,
          endpoint.client.notifyError.bind(endpoint.client));
    }

    if (this.cachedMessageData && interfaceEndpointHandle.id() ===
        this.cachedMessageData.message.getInterfaceId()) {
      timer.createOneShot(0, (function() {
        if (!this.cachedMessageData) {
          return;
        }

        var targetEndpoint = this.endpoints_.get(
            this.cachedMessageData.message.getInterfaceId());
        // Check that the target endpoint's client still exists.
        if (targetEndpoint && targetEndpoint.client) {
          var message = this.cachedMessageData.message;
          var messageValidator = this.cachedMessageData.messageValidator;
          this.cachedMessageData = null;
          this.connector_.resumeIncomingMethodCallProcessing();
          var ok = endpoint.client.handleIncomingMessage(message,
              messageValidator);

          // Handle invalid cached incoming message.
          if (!validator.isTestingMode() && !ok) {
            this.connector_.handleError(true, true);
          }
        }
      }).bind(this));
    }

    return endpoint;
  };

  Router.prototype.detachEndpointClient = function(
      interfaceEndpointHandle) {
    check(types.isValidInterfaceId(interfaceEndpointHandle.id()));
    var endpoint = this.endpoints_.get(interfaceEndpointHandle.id());
    check(endpoint);
    check(endpoint.client);
    check(!endpoint.closed);

    endpoint.client = null;
  };

  Router.prototype.createLocalEndpointHandle = function(
      interfaceId) {
    if (!types.isValidInterfaceId(interfaceId)) {
      return new InterfaceEndpointHandle();
    }

    var endpoint = this.endpoints_.get(interfaceId);

    if (!endpoint) {
      endpoint = new InterfaceEndpoint(this, interfaceId);
      this.endpoints_.set(interfaceId, endpoint);

      check(!endpoint.handleCreated);

      if (this.encounteredError_) {
        this.updateEndpointStateMayRemove(endpoint,
            EndpointStateUpdateType.PEER_ENDPOINT_CLOSED);
      }
    } else {
      if (endpoint.handleCreated) {
        return new InterfaceEndpointHandle();
      }

      // If the endpoint already exist, it is because we have received a
      // notification that the peer endpoint has closed.
      check(!endpoint.closed);
      check(endpoint.peerClosed);
    }

    endpoint.handleCreated = true;
    return new InterfaceEndpointHandle(interfaceId, this);
  };

  Router.prototype.accept = function(message) {
    var messageValidator = new Validator(message);
    var err = messageValidator.validateMessageHeader();

    var ok = false;
    if (err !== validator.validationError.NONE) {
      validator.reportValidationError(err);
    } else if (message.deserializeAssociatedEndpointHandles(this)) {
      if (controlMessageHandler.isPipeControlMessage(message)) {
        ok = this.controlMessageHandler_.accept(message);
      } else {
        var interfaceId = message.getInterfaceId();
        var endpoint = this.endpoints_.get(interfaceId);
        if (!endpoint || endpoint.closed) {
          return true;
        }

        if (!endpoint.client) {
          // We need to wait until a client is attached in order to dispatch
          // further messages.
          this.cachedMessageData = {message: message,
              messageValidator: messageValidator};
          this.connector_.pauseIncomingMethodCallProcessing();
          return true;
        }
        ok = endpoint.client.handleIncomingMessage(message, messageValidator);
      }
    }
    return ok;
  };

  Router.prototype.close = function() {
    this.connector_.close();
    // Closing the message pipe won't trigger connection error handler.
    // Explicitly call onPipeConnectionError() so that associated endpoints
    // will get notified.
    this.onPipeConnectionError();
  };

  Router.prototype.waitForNextMessageForTesting = function() {
    this.connector_.waitForNextMessageForTesting();
  };

  Router.prototype.onPeerAssociatedEndpointClosed = function(interfaceId,
      reason) {
    check(!types.isMasterInterfaceId(interfaceId) || reason);

    var endpoint = this.endpoints_.get(interfaceId);
    if (!endpoint) {
      endpoint = new InterfaceEndpoint(this, interfaceId);
      this.endpoints_.set(interfaceId, endpoint);
    }

    if (reason) {
      endpoint.disconnectReason = reason;
    }

    if (!endpoint.peerClosed) {
      if (endpoint.client) {
        timer.createOneShot(0,
            endpoint.client.notifyError.bind(endpoint.client, reason));
      }
      this.updateEndpointStateMayRemove(endpoint,
          EndpointStateUpdateType.PEER_ENDPOINT_CLOSED);
    }
    return true;
  };

  Router.prototype.onPipeConnectionError = function() {
    this.encounteredError_ = true;

    for (var endpoint of this.endpoints_.values()) {
      if (endpoint.client) {
        timer.createOneShot(0,
            endpoint.client.notifyError.bind(endpoint.client,
              endpoint.disconnectReason));
      }
      this.updateEndpointStateMayRemove(endpoint,
          EndpointStateUpdateType.PEER_ENDPOINT_CLOSED);
    }
  };

  Router.prototype.closeEndpointHandle = function(interfaceId, reason) {
    if (!types.isValidInterfaceId(interfaceId)) {
      return;
    }
    var endpoint = this.endpoints_.get(interfaceId);
    check(endpoint);
    check(!endpoint.client);
    check(!endpoint.closed);

    this.updateEndpointStateMayRemove(endpoint,
        EndpointStateUpdateType.ENDPOINT_CLOSED);

    if (!types.isMasterInterfaceId(interfaceId) || reason) {
      this.controlMessageProxy_.notifyPeerEndpointClosed(interfaceId, reason);
    }

    if (this.cachedMessageData && interfaceId ===
        this.cachedMessageData.message.getInterfaceId()) {
      this.cachedMessageData = null;
      this.connector_.resumeIncomingMethodCallProcessing();
    }
  };

  Router.prototype.updateEndpointStateMayRemove = function(endpoint,
      endpointStateUpdateType) {
    if (endpointStateUpdateType === EndpointStateUpdateType.ENDPOINT_CLOSED) {
      endpoint.closed = true;
    } else {
      endpoint.peerClosed = true;
    }
    if (endpoint.closed && endpoint.peerClosed) {
      this.endpoints_.delete(endpoint.id);
    }
  };

  var exports = {};
  exports.Router = Router;
  return exports;
});
