/*
 * Copyright 2008 Google Inc.
 * 
 * Licensed under the Apache License, Version 2.0 (the "License"); you may not
 * use this file except in compliance with the License. You may obtain a copy of
 * the License at
 * 
 * http://www.apache.org/licenses/LICENSE-2.0
 * 
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
 * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
 * License for the specific language governing permissions and limitations under
 * the License.
 */
package com.google.gwt.dev.shell;

import com.google.gwt.dev.shell.BrowserChannel.SessionHandler.ExceptionOrReturnValue;
import com.google.gwt.dev.shell.BrowserChannel.SessionHandler.SpecialDispatchId;
import com.google.gwt.dev.shell.BrowserChannel.Value.ValueType;
import com.google.gwt.util.tools.Utility;

import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.io.UnsupportedEncodingException;
import java.net.Socket;
import java.util.Set;

/**
 * 
 */
public abstract class BrowserChannel {

  /**
   * An error indicating that the remote side died and we should unroll the
   * call stack as painlessly as possible to allow cleanup.
   */
  public static class RemoteDeathError extends Error {

    public RemoteDeathError(Throwable cause) {
      super("Remote connection lost", cause);
    }
  }

  /**
   * Class representing a reference to a Java object.
   */
  public static class JavaObjectRef implements RemoteObjectRef {
    private int refId;

    public JavaObjectRef(int refId) {
      this.refId = refId;
    }

    public int getRefid() {
      return Math.abs(refId);
    }

    @Override
    public int hashCode() {
      return refId;
    }

    public boolean isException() {
      return refId < 0;
    }

    @Override
    public String toString() {
      return "JavaObjectRef(ref=" + refId + ")";
    }
  }

  /**
   * Class representing a reference to a JS object.
   */
  public static class JsObjectRef implements RemoteObjectRef  {
    
    private int refId;
    
    public JsObjectRef(int refId) {
      this.refId = refId;
    }

    @Override
    public boolean equals(Object o) {
      return (o instanceof JsObjectRef) && ((JsObjectRef) o).refId == refId;
    }

    public int getRefid() {
      // exceptions are negative, so we get the absolute value
      return Math.abs(refId);
    }

    @Override
    public int hashCode() {
      return refId;
    }

    public boolean isException() {
      return refId < 0;
    }

    @Override
    public String toString() {
      return "JsObjectRef(" + refId + ")";
    }
  }

  /**
   * Enumeration of message type ids.
   * 
   * <p>Ids are used instead of relying on the ordinal to avoid sychronization
   * problems with the client.
   */
  public enum MessageType {
    /**
     * A message to invoke a method on the other side of the wire.  Note that
     * the messages are asymmetric -- see {@link InvokeOnClientMessage} and
     * {@link InvokeOnServerMessage}.
     */
    INVOKE(0),
    
    /**
     * Returns the result of an INVOKE, INVOKE_SPECIAL, or LOAD_MODULE message. 
     */
    RETURN(1),
    
    /**
     * v1 LOAD_MODULE message.
     */
    OLD_LOAD_MODULE(2),
    
    /**
     * Normal closure of the connection.
     */
    QUIT(3),
    
    /**
     * A request by the server to load JSNI source into the client's JS engine.
     */
    LOAD_JSNI(4),
    
    INVOKE_SPECIAL(5),
    
    FREE_VALUE(6),
    
    /**
     * Abnormal termination of the connection.
     */
    FATAL_ERROR(7),
    
    CHECK_VERSIONS(8),
    
    PROTOCOL_VERSION(9),
    
    CHOOSE_TRANSPORT(10),
    
    SWITCH_TRANSPORT(11),
    
    LOAD_MODULE(12),
    
    REQUEST_ICON(13),
    
    USER_AGENT_ICON(14),
    
    REQUEST_PLUGIN(15);
    
    private final int id;
    
    private MessageType(int id) {
      this.id = id;
    }
    
    public int getId() {
      return id;
    }
  }

  /**
   * Represents an object on the other side of the channel, known to this side
   * by an reference ID.
   */
  public interface RemoteObjectRef {
    
    /**
      * @return the reference ID for this object.
      */
    int getRefid();
  }

  /**
   * Hook interface for responding to messages.
   */
  public abstract static class SessionHandler<T extends BrowserChannel> {

    /**
     * Wrapper to return both a return value/exception and a flag as to whether
     * an exception was thrown or not.
     */
    public static class ExceptionOrReturnValue {
      private final boolean isException;
      private final Value returnValue;

      public ExceptionOrReturnValue(boolean isException, Value returnValue) {
        this.isException = isException;
        this.returnValue = returnValue;
      }

      public Value getReturnValue() {
        return returnValue;
      }

      public boolean isException() {
        return isException;
      }
    }

    /**
     * Enumeration of dispatch IDs on object 0 (the ServerMethods object).
     * 
     * <p>Ids are set specifically rather than relying on the ordinal to avoid
     * synchronization problems with the client.
     * 
     * TODO: hasMethod/hasProperty no longer used, remove them!
     */
    public enum SpecialDispatchId {
      HasMethod(0), HasProperty(1), GetProperty(2), SetProperty(3);
      
      private final int id;

      private SpecialDispatchId(int id) {
        this.id = id;
      }
      
      public int getId() {
        return id;
      }
    }

    public abstract void freeValue(T channel, int[] ids);
  }

  /**
   * Represents a value for BrowserChannel.
   */
  public static class Value {
    /**
     * Enum of type tags sent across the wire.
     */
    public enum ValueType {
      /**
       * Primitive values.
       */
      NULL(0), BOOLEAN(1), BYTE(2), CHAR(3), SHORT(4), INT(5), LONG(6),
      FLOAT(7), DOUBLE(8), STRING(9),

      /**
       * Representations of Java or JS objects, sent as an index into a table
       * kept on the side holding the actual object.
       */
      JAVA_OBJECT(10), JS_OBJECT(11),

      /**
       * A Javascript undef value, also used for void returns.
       */
      UNDEFINED(12);

      private final int id;

      private ValueType(int id) {
        this.id = id;
      }

      byte getTag() {
        return (byte) id;
      }
    }

    /**
     * Type tag value.
     */
    private ValueType type = ValueType.UNDEFINED;

    /**
     * Represents a value sent/received across the wire.
     */
    private Object value = null;

    public Value() {
    }

    public Value(Object obj) {
      convertFromJavaValue(obj);
    }

    /**
     * Convert a Java object to a value. Objects must be primitive wrappers,
     * Strings, or JsObjectRef/JavaObjectRef instances.
     * 
     * @param obj value to convert.
     */
    public void convertFromJavaValue(Object obj) {
      if (obj == null) {
        type = ValueType.NULL;
      } else if (obj instanceof Boolean) {
        type = ValueType.BOOLEAN;
      } else if (obj instanceof Byte) {
        type = ValueType.BYTE;
      } else if (obj instanceof Character) {
        type = ValueType.CHAR;
      } else if (obj instanceof Double) {
        type = ValueType.DOUBLE;
      } else if (obj instanceof Float) {
        type = ValueType.FLOAT;
      } else if (obj instanceof Integer) {
        type = ValueType.INT;
      } else if (obj instanceof Long) {
        type = ValueType.LONG;
      } else if (obj instanceof Short) {
        type = ValueType.SHORT;
      } else if (obj instanceof String) {
        type = ValueType.STRING;
      } else if (obj instanceof JsObjectRef) {
        // TODO: exception handling?
        type = ValueType.JS_OBJECT;
      } else if (obj instanceof JavaObjectRef) {
        // TODO: exception handling?
        type = ValueType.JAVA_OBJECT;
      } else {
        throw new RuntimeException(
            "Unexpected Java type in convertFromJavaValue: " + obj);
      }
      value = obj;
    }

    /**
     * Convert a value to the requested Java type.
     * 
     * @param reqType type to convert to
     * @return value as that type.
     */
    public Object convertToJavaType(Class<?> reqType) {
      if (reqType.isArray()) {
        // TODO(jat): handle arrays?
      }
      if (reqType.equals(Boolean.class)) {
        assert type == ValueType.BOOLEAN;
        return value;
      } else if (reqType.equals(Byte.class) || reqType.equals(byte.class)) {
        assert isNumber();
        return Byte.valueOf(((Number) value).byteValue());
      } else if (reqType.equals(Character.class) || reqType.equals(char.class)) {
        if (type == ValueType.CHAR) {
          return value;
        } else {
          assert isNumber();
          return Character.valueOf((char) ((Number) value).shortValue());
        }
      } else if (reqType.equals(Double.class) || reqType.equals(double.class)) {
        assert isNumber();
        return Double.valueOf(((Number) value).doubleValue());
      } else if (reqType.equals(Float.class) || reqType.equals(float.class)) {
        assert isNumber();
        return Float.valueOf(((Number) value).floatValue());
      } else if (reqType.equals(Integer.class) || reqType.equals(int.class)) {
        assert isNumber();
        return Integer.valueOf(((Number) value).intValue());
      } else if (reqType.equals(Long.class) || reqType.equals(long.class)) {
        assert isNumber();
        return Long.valueOf(((Number) value).longValue());
      } else if (reqType.equals(Short.class) || reqType.equals(short.class)) {
        assert isNumber();
        return Short.valueOf(((Number) value).shortValue());
      } else if (reqType.equals(String.class)) {
        assert type == ValueType.STRING;
        return value;
      } else {
        // Wants an object, caller must deal with object references.
        return value;
      }
    }

    public boolean getBoolean() {
      assert type == ValueType.BOOLEAN;
      return ((Boolean) value).booleanValue();
    }

    public byte getByte() {
      assert type == ValueType.BYTE;
      return ((Byte) value).byteValue();
    }

    public char getChar() {
      assert type == ValueType.CHAR;
      return ((Character) value).charValue();
    }

    public double getDouble() {
      assert type == ValueType.DOUBLE;
      return ((Double) value).doubleValue();
    }

    public float getFloat() {
      assert type == ValueType.FLOAT;
      return ((Float) value).floatValue();
    }

    public int getInt() {
      assert type == ValueType.INT;
      return ((Integer) value).intValue();
    }

    public JavaObjectRef getJavaObject() {
      assert type == ValueType.JAVA_OBJECT;
      return (JavaObjectRef) value;
    }

    public JsObjectRef getJsObject() {
      assert type == ValueType.JS_OBJECT;
      return (JsObjectRef) value;
    }

    public long getLong() {
      assert type == ValueType.LONG;
      return ((Long) value).longValue();
    }

    public short getShort() {
      assert type == ValueType.SHORT;
      return ((Short) value).shortValue();
    }

    public String getString() {
      assert type == ValueType.STRING;
      return (String) value;
    }

    public ValueType getType() {
      return type;
    }

    public Object getValue() {
      return value;
    }

    public boolean isBoolean() {
      return type == ValueType.BOOLEAN;
    }

    public boolean isByte() {
      return type == ValueType.BYTE;
    }

    public boolean isChar() {
      return type == ValueType.CHAR;
    }

    public boolean isDouble() {
      return type == ValueType.DOUBLE;
    }

    public boolean isFloat() {
      return type == ValueType.FLOAT;
    }

    public boolean isInt() {
      return type == ValueType.INT;
    }

    public boolean isJavaObject() {
      return type == ValueType.JAVA_OBJECT;
    }

    public boolean isJsObject() {
      return type == ValueType.JS_OBJECT;
    }

    public boolean isLong() {
      return type == ValueType.LONG;
    }

    public boolean isNull() {
      return type == ValueType.NULL;
    }

    public boolean isNumber() {
      switch (type) {
        case BYTE:
        case CHAR:
        case DOUBLE:
        case FLOAT:
        case INT:
        case LONG:
        case SHORT:
          return true;
        default:
          return false;
      }
    }

    public boolean isPrimitive() {
      switch (type) {
        case BOOLEAN:
        case BYTE:
        case CHAR:
        case DOUBLE:
        case FLOAT:
        case INT:
        case LONG:
        case SHORT:
          return true;
        default:
          return false;
      }
    }

    public boolean isShort() {
      return type == ValueType.SHORT;
    }

    public boolean isString() {
      return type == ValueType.STRING;
    }

    public boolean isUndefined() {
      return type == ValueType.UNDEFINED;
    }

    public void setBoolean(boolean val) {
      type = ValueType.BOOLEAN;
      value = Boolean.valueOf(val);
    }

    public void setByte(byte val) {
      type = ValueType.BYTE;
      value = Byte.valueOf(val);
    }

    public void setChar(char val) {
      type = ValueType.CHAR;
      value = Character.valueOf(val);
    }

    public void setDouble(double val) {
      type = ValueType.DOUBLE;
      value = Double.valueOf(val);
    }

    public void setFloat(float val) {
      type = ValueType.FLOAT;
      value = Float.valueOf(val);
    }

    public void setInt(int val) {
      type = ValueType.INT;
      value = Integer.valueOf(val);
    }

    public void setJavaObject(JavaObjectRef val) {
      type = ValueType.JAVA_OBJECT;
      value = val;
    }

    public void setJsObject(JsObjectRef val) {
      type = ValueType.JS_OBJECT;
      value = val;
    }

    public void setLong(long val) {
      type = ValueType.BOOLEAN;
      value = Long.valueOf(val);
    }

    public void setNull() {
      type = ValueType.NULL;
      value = null;
    }

    public void setShort(short val) {
      type = ValueType.SHORT;
      value = Short.valueOf(val);
    }

    public void setString(String val) {
      type = ValueType.STRING;
      value = val;
    }

    public void setUndefined() {
      type = ValueType.UNDEFINED;
      value = null;
    }

    @Override
    public String toString() {
      return type + ": " + value;
    }
  }

  /**
   * The initial request from the client, supplies a range of supported versions
   * and the version from hosted.html (so stale copies on an external server
   * can be detected).
   */
  protected static class CheckVersionsMessage extends Message {
    
    public static CheckVersionsMessage receive(BrowserChannel channel)
        throws IOException {
      DataInputStream stream = channel.getStreamFromOtherSide();
      int minVersion = stream.readInt();
      int maxVersion = stream.readInt();
      String hostedHtmlVersion = readUtf8String(stream);
      return new CheckVersionsMessage(channel, minVersion, maxVersion,
          hostedHtmlVersion);
    }

    private final String hostedHtmlVersion;

    private final int maxVersion;

    private final int minVersion;

    public CheckVersionsMessage(BrowserChannel channel, int minVersion,
        int maxVersion, String hostedHtmlVersion) {
      super(channel);
      this.minVersion = minVersion;
      this.maxVersion = maxVersion;
      this.hostedHtmlVersion = hostedHtmlVersion;
    }

    public String getHostedHtmlVersion() {
      return hostedHtmlVersion;
    }

    public int getMaxVersion() {
      return maxVersion;
    }

    public int getMinVersion() {
      return minVersion;
    }

    @Override
    public void send() throws IOException {
      DataOutputStream stream = getBrowserChannel().getStreamToOtherSide();
      stream.writeByte(MessageType.CHECK_VERSIONS.getId());
      stream.writeInt(minVersion);
      stream.writeInt(maxVersion);
      writeUtf8String(stream, hostedHtmlVersion);
      stream.flush();
    }
  }

  /**
   * A message from the client giving a list of supported connection methods
   * and requesting the server choose one of them to switch protocol traffic to.
   */
  protected static class ChooseTransportMessage extends Message {
    
    public static ChooseTransportMessage receive(BrowserChannel channel)
        throws IOException {
      DataInputStream stream = channel.getStreamFromOtherSide();
      int n = stream.readInt();
      String[] transports = new String[n];
      for (int i = 0; i < n; ++i) {
        transports[i] = readUtf8String(stream);
      }
      return new ChooseTransportMessage(channel, transports);
    }

    private final String[] transports;

    public ChooseTransportMessage(BrowserChannel channel,
        String[] transports) {
      super(channel);
      this.transports = transports;
    }

    public String[] getTransports() {
      return transports;
    }
    
    @Override
    public void send() throws IOException {
      DataOutputStream stream = getBrowserChannel().getStreamToOtherSide();
      stream.writeByte(MessageType.CHOOSE_TRANSPORT.getId());
      stream.writeInt(transports.length);
      for (String transport : transports) {
        writeUtf8String(stream, transport);
      }
    }
  }

  /**
   * A message reporting a connection error to the client.
   */
  protected static class FatalErrorMessage extends Message {

    public static FatalErrorMessage receive(BrowserChannel channel)
        throws IOException {
      DataInputStream stream = channel.getStreamFromOtherSide();
      // NOTE: Tag has already been read.
      String error = readUtf8String(stream);
      return new FatalErrorMessage(channel, error);
    }

    private final String error;

    public FatalErrorMessage(BrowserChannel channel, String error) {
      super(channel);
      this.error = error;
    }
    
    public String getError() {
      return error;
    }
    
    @Override
    public void send() throws IOException {
      DataOutputStream stream = getBrowserChannel().getStreamToOtherSide();
      stream.writeByte(MessageType.FATAL_ERROR.getId());
      writeUtf8String(stream, error);
    }
  }

  /**
   * A message asking the other side to free object references. Note that there
   * is no response to this message, and this must only be sent immediately
   * before an Invoke or Return message.
   */
  protected static class FreeMessage extends Message {
    public static FreeMessage receive(BrowserChannel channel)
        throws IOException {
      DataInputStream stream = channel.getStreamFromOtherSide();
      int numIds = stream.readInt();
      // TODO: sanity check id count
      int ids[] = new int[numIds];
      for (int i = 0; i < numIds; ++i) {
        ids[i] = stream.readInt();
      }
      return new FreeMessage(channel, ids);
    }

    public static void send(BrowserChannel channel, int[] ids)
        throws IOException {
      DataOutputStream stream = channel.getStreamToOtherSide();
      stream.writeByte(MessageType.FREE_VALUE.getId());
      stream.writeInt(ids.length);
      for (int id : ids) {
        stream.writeInt(id);
      }
      stream.flush();
    }

    private final int ids[];

    public FreeMessage(BrowserChannel channel, int[] ids) {
      super(channel);
      this.ids = ids;
    }

    public int[] getIds() {
      return ids;
    }

    @Override
    public boolean isAsynchronous() {
      return true;
    }

    @Override
    public void send() throws IOException {
      send(getBrowserChannel(), ids);
    }
  }

  /**
   * A request from the server to invoke a function on the client.
   * 
   * Note that MessageType.INVOKE can refer to either this class
   * or {@link InvokeOnServerMessage} depending on the direction, as the
   * protocol is asymmetric (Java needs a dispatch ID, Javascript needs a
   * name).
   */
  protected static class InvokeOnClientMessage extends Message {
    public static InvokeOnClientMessage receive(BrowserChannel channel)
        throws IOException {
      DataInputStream stream = channel.getStreamFromOtherSide();
      // NOTE: Tag has already been read.
      String methodName = readUtf8String(stream);
      Value thisRef = channel.readValue(stream);
      int argLen = stream.readInt();
      Value[] args = new Value[argLen];
      for (int i = 0; i < argLen; i++) {
        args[i] = channel.readValue(stream);
      }
      return new InvokeOnClientMessage(channel, methodName, thisRef, args);
    }

    private final Value[] args;
    private final String methodName;
    private final Value thisRef;

    public InvokeOnClientMessage(BrowserChannel channel, String methodName,
        Value thisRef, Value[] args) {
      super(channel);
      this.thisRef = thisRef;
      this.methodName = methodName;
      this.args = args;
    }

    public Value[] getArgs() {
      return args;
    }

    public String getMethodName() {
      return methodName;
    }

    public Value getThis() {
      return thisRef;
    }

    @Override
    public void send() throws IOException {
      final DataOutputStream stream = getBrowserChannel().getStreamToOtherSide();

      stream.writeByte(MessageType.INVOKE.getId());
      writeUtf8String(stream, methodName);
      getBrowserChannel().writeValue(stream, thisRef);
      stream.writeInt(args.length);
      for (int i = 0; i < args.length; i++) {
        getBrowserChannel().writeValue(stream, args[i]);
      }
      stream.flush();
    }
  }

  /**
   * A request from the client to invoke a function on the server.
   * 
   * Note that MessageType.INVOKE can refer to either this class
   * or {@link InvokeOnClientMessage} depending on the direction, as the
   * protocol is asymmetric (Java needs a dispatch ID, Javascript needs a
   * name).
   */
  protected static class InvokeOnServerMessage extends Message {
    public static InvokeOnServerMessage receive(BrowserChannel channel)
        throws IOException {
      DataInputStream stream = channel.getStreamFromOtherSide();
      // NOTE: Tag has already been read.
      int methodDispatchId = stream.readInt();
      Value thisRef = channel.readValue(stream);
      int argLen = stream.readInt();
      Value[] args = new Value[argLen];
      for (int i = 0; i < argLen; i++) {
        args[i] = channel.readValue(stream);
      }
      return new InvokeOnServerMessage(channel, methodDispatchId, thisRef,
          args);
    }

    private final Value[] args;
    private final int methodDispatchId;
    private final Value thisRef;

    public InvokeOnServerMessage(BrowserChannel channel, int methodDispatchId,
        Value thisRef, Value[] args) {
      super(channel);
      this.thisRef = thisRef;
      this.methodDispatchId = methodDispatchId;
      this.args = args;
    }

    public Value[] getArgs() {
      return args;
    }

    public int getMethodDispatchId() {
      return methodDispatchId;
    }

    public Value getThis() {
      return thisRef;
    }

    @Override
    public void send() throws IOException {
      final DataOutputStream stream = getBrowserChannel().getStreamToOtherSide();

      stream.writeByte(MessageType.INVOKE.getId());
      stream.writeInt(methodDispatchId);
      getBrowserChannel().writeValue(stream, thisRef);
      stream.writeInt(args.length);
      for (int i = 0; i < args.length; i++) {
        getBrowserChannel().writeValue(stream, args[i]);
      }
      stream.flush();
    }
  }

  /**
   * A request from the to invoke a function on the other side.
   */
  protected static class InvokeSpecialMessage extends Message {
    public static InvokeSpecialMessage receive(BrowserChannel channel)
        throws IOException, BrowserChannelException {
      final DataInputStream stream = channel.getStreamFromOtherSide();
      // NOTE: Tag has already been read.
      final int specialMethodInt = stream.readByte();
      SpecialDispatchId[] ids = SpecialDispatchId.values();
      if (specialMethodInt < 0 || specialMethodInt >= ids.length) {
        throw new BrowserChannelException("Invalid dispatch id "
            + specialMethodInt);
      }
      final SpecialDispatchId dispatchId = ids[specialMethodInt];
      final int argLen = stream.readInt();
      final Value[] args = new Value[argLen];
      for (int i = 0; i < argLen; i++) {
        args[i] = channel.readValue(stream);
      }
      return new InvokeSpecialMessage(channel, dispatchId, args);
    }

    private final Value[] args;
    private final SpecialDispatchId dispatchId;

    public InvokeSpecialMessage(BrowserChannel channel,
        SpecialDispatchId dispatchId, Value[] args) {
      super(channel);
      this.dispatchId = dispatchId;
      this.args = args;
    }

    public Value[] getArgs() {
      return args;
    }

    public SpecialDispatchId getDispatchId() {
      return dispatchId;
    }

    @Override
    public void send() throws IOException {
      final DataOutputStream stream = getBrowserChannel().getStreamToOtherSide();

      stream.writeByte(MessageType.INVOKE_SPECIAL.getId());
      stream.writeByte(dispatchId.getId());
      stream.writeInt(args.length);
      for (int i = 0; i < args.length; i++) {
        getBrowserChannel().writeValue(stream, args[i]);
      }
      stream.flush();
    }
  }

  /**
   * A message sending JSNI code to be evaluated. Note that there is no response
   * to this message, and this must only be sent immediately before an Invoke or
   * Return message.
   */
  protected static class LoadJsniMessage extends Message {
    public static LoadJsniMessage receive(BrowserChannel channel)
        throws IOException {
      DataInputStream stream = channel.getStreamFromOtherSide();
      String js = readUtf8String(stream);
      return new LoadJsniMessage(channel, js);
    }

    public static void send(BrowserChannel channel, String js)
        throws IOException {
      DataOutputStream stream = channel.getStreamToOtherSide();
      stream.write(MessageType.LOAD_JSNI.getId());
      writeUtf8String(stream, js);
      stream.flush();
    }

    private final String js;

    public LoadJsniMessage(BrowserChannel channel, String js) {
      super(channel);
      this.js = js;
    }

    public String getJsni() {
      return js;
    }

    @Override
    public boolean isAsynchronous() {
      return true;
    }

    @Override
    public void send() throws IOException {
      send(getBrowserChannel(), js);
    }
  }

  /**
   * A request from the client that the server load and initialize a given
   * module.
   */
  protected static class LoadModuleMessage extends Message {
    public static LoadModuleMessage receive(BrowserChannel channel)
        throws IOException {
      DataInputStream stream = channel.getStreamFromOtherSide();
      String url = readUtf8String(stream);
      String tabKey = readUtf8String(stream);
      String sessionKey = readUtf8String(stream);
      String moduleName = readUtf8String(stream);
      String userAgent = readUtf8String(stream);
      return new LoadModuleMessage(channel, url, tabKey, sessionKey, moduleName,
          userAgent);
    }

    private final String moduleName;

    private final String sessionKey;

    private final String tabKey;
    
    private final String url;

    private final String userAgent;

    /**
     * Creates a LoadModule message to be sent to the server.
     * 
     * @param channel BrowserChannel instance
     * @param url URL of main top-level window - may not be null
     * @param tabKey opaque key identifying the tab in the browser, or an
     *     empty string if it cannot be determined - may not be null
     * @param sessionKey opaque key identifying a particular session (ie,
     *     group of modules) - may not be null
     * @param moduleName name of GWT module to load - may not be null
     * @param userAgent user agent identifier of the browser - may not be null
     */
    public LoadModuleMessage(BrowserChannel channel, String url,
        String tabKey, String sessionKey, String moduleName, String userAgent) {
      super(channel);
      assert url != null;
      assert tabKey != null;
      assert sessionKey != null;
      assert moduleName != null;
      assert userAgent != null;
      this.url = url;
      this.tabKey = tabKey;
      this.sessionKey = sessionKey;
      this.moduleName = moduleName;
      this.userAgent = userAgent;
    }

    public String getModuleName() {
      return moduleName;
    }

    public String getSessionKey() {
      return sessionKey;
    }

    public String getTabKey() {
      return tabKey;
    }

    public String getUrl() {
      return url;
    }

    public String getUserAgent() {
      return userAgent;
    }

    @Override
    public void send() throws IOException {
      DataOutputStream stream = getBrowserChannel().getStreamToOtherSide();
      stream.writeByte(MessageType.LOAD_MODULE.getId());
      writeUtf8String(stream, url);
      writeUtf8String(stream, tabKey);
      writeUtf8String(stream, sessionKey);
      writeUtf8String(stream, moduleName);
      writeUtf8String(stream, userAgent);
      stream.flush();
    }
  }

  /**
   * Abstract base class of OOPHM messages.
   */
  protected abstract static class Message {
    public static MessageType readMessageType(DataInputStream stream)
        throws IOException, BrowserChannelException {
      stream.mark(1);
      int type = stream.readByte();
      MessageType[] types = MessageType.values();
      if (type < 0 || type >= types.length) {
        stream.reset();
        throw new BrowserChannelException("Invalid message type " + type);
      }
      return types[type];
    }

    private final BrowserChannel channel;

    public Message(BrowserChannel channel) {
      this.channel = channel;
    }

    public final BrowserChannel getBrowserChannel() {
      return channel;
    }

    /**
     * @return true if this message type is asynchronous and does not expect a
     *         return message.
     */
    public boolean isAsynchronous() {
      return false;
    }

    /**
     * @throws IOException if a subclass encounters an I/O error
     */
    public void send() throws IOException {
      throw new UnsupportedOperationException(getClass().getName()
          + " is a message format that can only be received.");
    }
  }

  /**
   * Provides a way of allocating JS and Java object ids without knowing
   * which one is the remote type, so code can be shared between client and
   * server.
   */
  protected interface ObjectRefFactory {

    JavaObjectRef getJavaObjectRef(int refId);

    JsObjectRef getJsObjectRef(int refId);

    Set<Integer> getRefIdsForCleanup();
  }

  /**
   * A request from the client that the server load and initialize a given
   * module (original v1 version).
   */
  protected static class OldLoadModuleMessage extends Message {
    public static OldLoadModuleMessage receive(BrowserChannel channel)
        throws IOException {
      DataInputStream stream = channel.getStreamFromOtherSide();
      int protoVersion = stream.readInt();
      String moduleName = readUtf8String(stream);
      String userAgent = readUtf8String(stream);
      return new OldLoadModuleMessage(channel, protoVersion, moduleName,
          userAgent);
    }

    private final String moduleName;

    private final int protoVersion;

    private final String userAgent;
    
    public OldLoadModuleMessage(BrowserChannel channel, int protoVersion,
        String moduleName, String userAgent) {
      super(channel);
      this.protoVersion = protoVersion;
      this.moduleName = moduleName;
      this.userAgent = userAgent;
    }

    public String getModuleName() {
      return moduleName;
    }

    public int getProtoVersion() {
      return protoVersion;
    }

    public String getUserAgent() {
      return userAgent;
    }

    @Override
    public void send() throws IOException {
      DataOutputStream stream = getBrowserChannel().getStreamToOtherSide();
      stream.writeByte(MessageType.OLD_LOAD_MODULE.getId());
      stream.writeInt(protoVersion);
      writeUtf8String(stream, moduleName);
      writeUtf8String(stream, userAgent);
      stream.flush();
    }
  }

  /**
   * Reports the selected protocol version.
   */
  protected static class ProtocolVersionMessage extends Message {
    
    public static ProtocolVersionMessage receive(BrowserChannel channel)
        throws IOException {
      DataInputStream stream = channel.getStreamFromOtherSide();
      int protocolVersion = stream.readInt();
      return new ProtocolVersionMessage(channel, protocolVersion);
    }

    private final int protocolVersion;

    public ProtocolVersionMessage(BrowserChannel channel, int protocolVersion) {
      super(channel);
      this.protocolVersion = protocolVersion;
    }

    public int getProtocolVersion() {
      return protocolVersion;
    }

    @Override
    public void send() throws IOException {
      DataOutputStream stream = getBrowserChannel().getStreamToOtherSide();
      stream.writeByte(MessageType.PROTOCOL_VERSION.getId());
      stream.writeInt(protocolVersion);
      stream.flush();
    }
  }

  /**
   * A message signifying a soft close of the communications channel.
   */
  protected static class QuitMessage extends Message {
    public static QuitMessage receive(BrowserChannel channel) {
      return new QuitMessage(channel);
    }

    public static void send(BrowserChannel channel) throws IOException {
      final DataOutputStream stream = channel.getStreamToOtherSide();
      stream.writeByte(MessageType.QUIT.getId());
      stream.flush();
    }

    public QuitMessage(BrowserChannel channel) {
      super(channel);
    }

    @Override
    public void send() throws IOException {
      send(getBrowserChannel());
    }
  }

  /**
   * A message asking the client to send an icon suitable for use in the UI.
   * <p>See {@link UserAgentIconMessage}.
   */
  protected static class RequestIconMessage extends Message {

    /**
     * Receive a RequestIconMessage, assuming the message tag has already been
     * read.
     * 
     * @throws IOException
     */
    public static RequestIconMessage receive(BrowserChannel channel)
        throws IOException {
      return new RequestIconMessage(channel);
    }

    public static void send(BrowserChannel channel)
        throws IOException {
      DataOutputStream stream = channel.getStreamToOtherSide();
      stream.writeByte(MessageType.REQUEST_ICON.getId());
      stream.flush();
    }

    public RequestIconMessage(BrowserChannel channel) {
      super(channel);
    }

    @Override
    public void send() throws IOException {
      send(getBrowserChannel());
    }
  }

  /**
   * Signifies a return from a previous invoke.
   */
  protected static class ReturnMessage extends Message {
    public static ReturnMessage receive(BrowserChannel channel)
        throws IOException {
      final DataInputStream stream = channel.getStreamFromOtherSide();
      final boolean isException = stream.readBoolean();
      final Value returnValue = channel.readValue(stream);
      return new ReturnMessage(channel, isException, returnValue);
    }

    public static void send(BrowserChannel channel, boolean isException,
        Value returnValue) throws IOException {
      final DataOutputStream stream = channel.getStreamToOtherSide();
      stream.writeByte(MessageType.RETURN.getId());
      stream.writeBoolean(isException);
      channel.writeValue(stream, returnValue);
      stream.flush();
    }

    public static void send(BrowserChannel channel,
        ExceptionOrReturnValue returnOrException) throws IOException {
      send(channel, returnOrException.isException(),
          returnOrException.getReturnValue());
    }

    private final boolean isException;
    private final Value returnValue;

    public ReturnMessage(BrowserChannel channel, boolean isException,
        Value returnValue) {
      super(channel);
      this.returnValue = returnValue;
      this.isException = isException;
    }

    public Value getReturnValue() {
      return returnValue;
    }

    public boolean isException() {
      return isException;
    }

    @Override
    public void send() throws IOException {
      send(getBrowserChannel(), isException, returnValue);
    }
  }

  /**
   * A response to ChooseTransport telling the client which transport should
   * be used for the remainder of the protocol. 
   */
  protected static class SwitchTransportMessage extends Message {
    
    public static SwitchTransportMessage receive(BrowserChannel channel)
        throws IOException {
      DataInputStream stream = channel.getStreamFromOtherSide();
      String transport = readUtf8String(stream);
      String transportArgs = readUtf8String(stream);
      return new SwitchTransportMessage(channel, transport, transportArgs);
    }

    private final String transport;

    private final String transportArgs;

    public SwitchTransportMessage(BrowserChannel channel,
        String transport, String transportArgs) {
      super(channel);
      // Change nulls to empty strings
      if (transport == null) {
        transport = "";
      }
      if (transportArgs == null) {
        transportArgs = "";
      }
      this.transport = transport;
      this.transportArgs = transportArgs;
    }
    
    public String getTransport() {
      return transport;
    }

    public String getTransportArgs() {
      return transportArgs;
    }
    
    @Override
    public void send() throws IOException {
      DataOutputStream stream = getBrowserChannel().getStreamToOtherSide();
      stream.writeByte(MessageType.SWITCH_TRANSPORT.getId());
      writeUtf8String(stream, transport);
      writeUtf8String(stream, transportArgs);
      stream.flush();
    }
  }

  /**
   * A message supplying an icon, which fits in 24x24 and in a standard image
   * format such as PNG or GIF, suitable for use in the UI.
   * <p>See {@link RequestIconMessage}.
   */
  protected static class UserAgentIconMessage extends Message {
    public static UserAgentIconMessage receive(BrowserChannel channel)
        throws IOException {
      byte[] iconBytes = null;
      DataInputStream stream = channel.getStreamFromOtherSide();
      int len = stream.readInt();
      if (len > 0) {
        iconBytes = new byte[len];
        for (int i = 0; i < len; ++i) {
          iconBytes[i] = stream.readByte();
        }
      }
      return new UserAgentIconMessage(channel, iconBytes);
    }

    public static void send(BrowserChannel channel, byte[] iconBytes)
        throws IOException {
      DataOutputStream stream = channel.getStreamToOtherSide();
      stream.writeByte(MessageType.USER_AGENT_ICON.getId());
      if (iconBytes == null) {
        stream.writeInt(0);
      } else {
        stream.writeInt(iconBytes.length);
        for (byte b : iconBytes) {
          stream.writeByte(b);
        }
      }
      stream.flush();
    }

    private byte[] iconBytes;

    public UserAgentIconMessage(BrowserChannel channel, byte[] iconBytes) {
      super(channel);
      this.iconBytes = iconBytes;
    }

    public byte[] getIconBytes() {
      return iconBytes;
    }

    @Override
    public void send() throws IOException {
      send(getBrowserChannel(), iconBytes);
    }
  }

  /**
   * The current version of the protocol.
   */
  public static final int PROTOCOL_VERSION_CURRENT = 3;

  /**
   * The oldest protocol version supported by this code.
   */
  public static final int PROTOCOL_VERSION_OLDEST = 2;
  
  /**
   * The protocol version that added the GetIcon message.
   */
  public static final int PROTOCOL_VERSION_GET_ICON = 3;
  
  public static final int SPECIAL_CLIENTMETHODS_OBJECT = 0;

  public static final int SPECIAL_SERVERMETHODS_OBJECT = 0;

  protected static JavaObjectRef getJavaObjectRef(int refId) {
    return new JavaObjectRef(refId);
  }

  protected static String readUtf8String(DataInputStream stream)
      throws IOException {
    final int len = stream.readInt();
    final byte[] data = new byte[len];
    stream.readFully(data);
    return new String(data, "UTF8");
  }

  protected static ValueType readValueType(DataInputStream stream)
      throws IOException, BrowserChannelException {
    int type = stream.readByte();
    ValueType[] types = ValueType.values();
    if (type < 0 || type >= types.length) {
      throw new BrowserChannelException("Invalid value type " + type);
    }
    return types[type];
  }

  protected static void writeJavaObject(DataOutputStream stream,
      JavaObjectRef value) throws IOException {
    stream.writeByte(ValueType.JAVA_OBJECT.getTag());
    stream.writeInt(value.getRefid());
  }

  protected static void writeJsObject(DataOutputStream stream,
      JsObjectRef value) throws IOException {
    stream.writeByte(ValueType.JS_OBJECT.getTag());
    stream.writeInt(value.getRefid());
  }

  protected static void writeNull(DataOutputStream stream) throws IOException {
    stream.writeByte(ValueType.NULL.getTag());
  }

  protected static void writeTaggedBoolean(DataOutputStream stream,
      boolean value) throws IOException {
    stream.writeByte(ValueType.BOOLEAN.getTag());
    stream.writeBoolean(value);
  }

  protected static void writeTaggedByte(DataOutputStream stream, byte value)
      throws IOException {
    stream.writeByte(ValueType.BYTE.getTag());
    stream.writeByte(value);
  }

  protected static void writeTaggedChar(DataOutputStream stream, char value)
      throws IOException {
    stream.writeByte(ValueType.CHAR.getTag());
    stream.writeChar(value);
  }

  protected static void writeTaggedDouble(DataOutputStream stream, double value)
      throws IOException {
    stream.writeByte(ValueType.DOUBLE.getTag());
    stream.writeDouble(value);
  }

  protected static void writeTaggedFloat(DataOutputStream stream, float value)
      throws IOException {
    stream.writeByte(ValueType.FLOAT.getTag());
    stream.writeFloat(value);
  }

  protected static void writeTaggedInt(DataOutputStream stream, int value)
      throws IOException {
    stream.writeByte(ValueType.INT.getTag());
    stream.writeInt(value);
  }

  protected static void writeTaggedShort(DataOutputStream stream, short value)
      throws IOException {
    stream.writeByte(ValueType.SHORT.getTag());
    stream.writeShort(value);
  }

  protected static void writeTaggedString(DataOutputStream stream, String data)
      throws IOException {
    stream.writeByte(ValueType.STRING.getTag());
    writeUtf8String(stream, data);
  }

  protected static void writeUtf8String(DataOutputStream stream, String data)
      throws IOException {
    try {
      final byte[] bytes = data.getBytes("UTF8");
      stream.writeInt(bytes.length);
      stream.write(bytes);
    } catch (UnsupportedEncodingException e) {
      // TODO: Add description.
      throw new RuntimeException();
    }
  }

  private static void writeUndefined(DataOutputStream stream)
      throws IOException {
    stream.writeByte(ValueType.UNDEFINED.getTag());
  }

  private final ObjectRefFactory objectRefFactory;

  private Socket socket;

  private final DataInputStream streamFromOtherSide;

  private final DataOutputStream streamToOtherSide;

  public BrowserChannel(Socket socket, ObjectRefFactory objectRefFactory)
      throws IOException {
    this(new BufferedInputStream(socket.getInputStream()),
        new BufferedOutputStream(socket.getOutputStream()),
        objectRefFactory);
    this.socket = socket;
  }

  protected BrowserChannel(InputStream inputStream, OutputStream outputStream,
      ObjectRefFactory objectRefFactory) {
    streamFromOtherSide = new DataInputStream(inputStream);
    streamToOtherSide = new DataOutputStream(outputStream);
    socket = null;
    this.objectRefFactory = objectRefFactory;
  }

  public void endSession() {
    Utility.close(streamFromOtherSide);
    Utility.close(streamToOtherSide);
    Utility.close(socket);
  }

  /**
   * @return a set of remote object reference IDs to be freed.
   */
  public Set<Integer> getRefIdsForCleanup() {
    return objectRefFactory.getRefIdsForCleanup();
  }

  public String getRemoteEndpoint() {
    if (socket == null) {
      return "";
    }
    return socket.getInetAddress().getCanonicalHostName() + ":"
        + socket.getPort();
  }

  protected DataInputStream getStreamFromOtherSide() {
    return streamFromOtherSide;
  }

  protected DataOutputStream getStreamToOtherSide() {
    return streamToOtherSide;
  }

  protected Value readValue(DataInputStream stream) throws IOException {
    ValueType tag;
    try {
      tag = readValueType(stream);
    } catch (BrowserChannelException e) {
      IOException ee = new IOException();
      ee.initCause(e);
      throw ee;
    }
    Value value = new Value();
    switch (tag) {
      case NULL:
        value.setNull();
        break;
      case UNDEFINED:
        value.setUndefined();
        break;
      case BOOLEAN:
        value.setBoolean(stream.readByte() != 0);
        break;
      case BYTE:
        value.setByte(stream.readByte());
        break;
      case CHAR:
        value.setChar(stream.readChar());
        break;
      case FLOAT:
        value.setFloat(stream.readFloat());
        break;
      case INT:
        value.setInt(stream.readInt());
        break;
      case LONG:
        value.setLong(stream.readLong());
        break;
      case DOUBLE:
        value.setDouble(stream.readDouble());
        break;
      case SHORT:
        value.setShort(stream.readShort());
        break;
      case STRING:
        value.setString(readUtf8String(stream));
        break;
      case JS_OBJECT:
        value.setJsObject(objectRefFactory.getJsObjectRef(stream.readInt()));
        break;
      case JAVA_OBJECT:
        value.setJavaObject(objectRefFactory.getJavaObjectRef(
            stream.readInt()));
        break;
    }
    return value;
  }

  protected void sendFreedValues() throws IOException {
    Set<Integer> freed = objectRefFactory.getRefIdsForCleanup();
    int n = freed.size();
    if (n > 0) {
      int[] ids = new int[n];
      int i = 0;
      for (Integer id : freed) {
        ids[i++] = id;
      }
      FreeMessage.send(this, ids);
    }
  }

  protected void writeValue(DataOutputStream stream, Value value)
      throws IOException {
    if (value.isNull()) {
      writeNull(stream);
    } else if (value.isUndefined()) {
      writeUndefined(stream);
    } else if (value.isJsObject()) {
      writeJsObject(stream, value.getJsObject());
    } else if (value.isJavaObject()) {
      writeJavaObject(stream, value.getJavaObject());
    } else if (value.isBoolean()) {
      writeTaggedBoolean(stream, value.getBoolean());
    } else if (value.isByte()) {
      writeTaggedByte(stream, value.getByte());
    } else if (value.isChar()) {
      writeTaggedChar(stream, value.getChar());
    } else if (value.isShort()) {
      writeTaggedShort(stream, value.getShort());
    } else if (value.isDouble()) {
      writeTaggedDouble(stream, value.getDouble());
    } else if (value.isFloat()) {
      writeTaggedFloat(stream, value.getFloat());
    } else if (value.isInt()) {
      writeTaggedInt(stream, value.getInt());
    } else if (value.isString()) {
      writeTaggedString(stream, value.getString());
    } else {
      assert false;
    }
  }
}
