/*
 * 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;

/**
 * A base class for communication between Dev-mode client and server.
 */
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;
    }

    @Override
    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;
    }

    @Override
    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_UNUSED(6),
      FLOAT_UNUSED(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 Integer) {
        type = ValueType.INT;
      } 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 IllegalArgumentException("Unexpected type: " + obj.getClass());
      }
      value = obj;
    }

    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 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 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 isInt() {
      return type == ValueType.INT;
    }

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

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

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

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

    public boolean isPrimitive() {
      switch (type) {
        case BOOLEAN:
        case BYTE:
        case CHAR:
        case DOUBLE:
        case INT:
        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 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 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 INT:
        value.setInt(stream.readInt());
        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;
      default:
        throw new IllegalArgumentException("Unexpected type: " + tag);
    }
    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.isInt()) {
      writeTaggedInt(stream, value.getInt());
    } else if (value.isString()) {
      writeTaggedString(stream, value.getString());
    } else {
      throw new IllegalArgumentException("Unexpected type: " + value.getType());
    }
  }
}
