/*
 * Copyright 2009 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.core.ext.TreeLogger;
import com.google.gwt.dev.shell.BrowserChannel.SessionHandler.ExceptionOrReturnValue;
import com.google.gwt.dev.util.log.PrintWriterTreeLogger;

import java.io.IOException;
import java.net.Socket;
import java.util.Set;

/**
 * Implementation of the BrowserChannel for the client side.
 */
public class BrowserChannelClient extends BrowserChannel {

  /**
   * Hook interface for responding to messages from the server.
   */
  public abstract static class SessionHandlerClient extends
      SessionHandler<BrowserChannelClient> {

    public abstract Object getSynchronizationObject();

    public abstract String getUserAgent();

    public abstract ExceptionOrReturnValue invoke(BrowserChannelClient channel,
        Value thisObj, String methodName, Value[] args);

    public abstract void loadJsni(BrowserChannelClient channel,
        String jsniString);
  }

  private static class ClientObjectRefFactory implements ObjectRefFactory {

    private final RemoteObjectTable<JavaObjectRef> remoteObjectTable;

    public ClientObjectRefFactory() {
      remoteObjectTable = new RemoteObjectTable<JavaObjectRef>();
    }

    public JavaObjectRef getJavaObjectRef(int refId) {
      JavaObjectRef objectRef = remoteObjectTable.getRemoteObjectRef(refId);
      if (objectRef == null) {
        objectRef = new JavaObjectRef(refId);
        remoteObjectTable.putRemoteObjectRef(refId, objectRef);
      }
      return objectRef;
    }

    public JsObjectRef getJsObjectRef(int refId) {
      return new JsObjectRef(refId);
    }

    public Set<Integer> getRefIdsForCleanup() {
      return remoteObjectTable.getRefIdsForCleanup();
    }
  }

  private final SessionHandlerClient handler;
  private final PrintWriterTreeLogger logger = new PrintWriterTreeLogger();
  private final String moduleName;
  private final String tabKey;
  private final String sessionKey;
  private final String url;
  private final String versionString;
  private boolean connected = false;
  private int protocolVersion;

  public BrowserChannelClient(String addressParts[], String url,
      String sessionKey, String moduleName, String versionString,
      SessionHandlerClient sessionHandlerClient) throws IOException {
    super(new Socket(addressParts[0], Integer.parseInt(addressParts[1])),
        new ClientObjectRefFactory());
    connected = true;
    this.url = url;
    this.sessionKey = sessionKey;
    this.moduleName = moduleName;
    this.tabKey = ""; // TODO(jat): update when tab support is added.
    this.versionString = versionString;
    logger.setMaxDetail(TreeLogger.WARN);
    if (logger.isLoggable(TreeLogger.SPAM)) {
      logger.log(TreeLogger.SPAM, "BrowserChannelClient, versionString: "
          + versionString);
    }
    this.handler = sessionHandlerClient;
  }

  public boolean disconnectFromHost() throws IOException {
    if (logger.isLoggable(TreeLogger.DEBUG)) {
      logger.log(TreeLogger.DEBUG, "disconnecting channel " + this);
    }
    if (!isConnected()) {
      if (logger.isLoggable(TreeLogger.DEBUG)) {
        logger.log(TreeLogger.DEBUG,
            "Disconnecting already disconnected channel " + this);
      }
      return false;
    }
    new QuitMessage(this).send();
    endSession();
    connected = false;
    return true;
  }

  /**
   * @return the negotiated protocol version -- only valid after {@link #init}
   *         has returned.
   */
  public int getProtocolVersion() {
    return protocolVersion;
  }

  public boolean isConnected() {
    return connected;
  }

  // TODO (amitmanjhi): refer the state (message?) transition diagram
  /**
   * returns true iff execution completes normally.
   */
  public boolean process() throws IOException, BrowserChannelException {
    if (!init()) {
      disconnectFromHost();
      return false;
    }
    if (logger.isLoggable(TreeLogger.DEBUG)) {
      logger.log(TreeLogger.DEBUG, "sending " + MessageType.LOAD_MODULE
          + " message, userAgent: " + handler.getUserAgent());
    }
    ReturnMessage returnMessage = null;
    synchronized (handler.getSynchronizationObject()) {
      new LoadModuleMessage(this, url, tabKey, sessionKey, moduleName,
          handler.getUserAgent()).send();
      returnMessage = reactToMessages(handler, true);
    }
    if (logger.isLoggable(TreeLogger.DEBUG)) {
      logger.log(TreeLogger.DEBUG, "loaded module, returnValue: "
          + returnMessage.getReturnValue() + ", isException: "
          + returnMessage.isException());
    }
    return !returnMessage.isException();
  }

  public ReturnMessage reactToMessagesWhileWaitingForReturn(
      SessionHandlerClient handler) throws IOException, BrowserChannelException {
    ReturnMessage returnMessage = reactToMessages(handler, true);
    return returnMessage;
  }

  /*
   * Perform the initial interaction. Return true if interaction succeeds, false
   * if it fails. Do a check protocol versions, expected with 2.0+ oophm
   * protocol.
   */
  private boolean init() throws IOException, BrowserChannelException {
    if (logger.isLoggable(TreeLogger.DEBUG)) {
      logger.log(TreeLogger.DEBUG, "sending " + MessageType.CHECK_VERSIONS
          + " message");
    }
    new CheckVersionsMessage(this, PROTOCOL_VERSION_OLDEST,
        PROTOCOL_VERSION_CURRENT, versionString).send();
    MessageType type = Message.readMessageType(getStreamFromOtherSide());
    switch (type) {
      case PROTOCOL_VERSION:
        ProtocolVersionMessage protocolMessage = ProtocolVersionMessage.receive(this);
        protocolVersion = protocolMessage.getProtocolVersion();
        if (logger.isLoggable(TreeLogger.DEBUG)) {
          logger.log(TreeLogger.DEBUG, MessageType.PROTOCOL_VERSION
              + ": protocol version = " + protocolVersion);
        }
        break;
      case FATAL_ERROR:
        FatalErrorMessage errorMessage = FatalErrorMessage.receive(this);
        if (logger.isLoggable(TreeLogger.DEBUG)) {
          logger.log(TreeLogger.ERROR, "Received FATAL_ERROR message "
              + errorMessage.getError());
        }
        return false;
      default:
        return false;
    }

    return true;
  }

  private ReturnMessage reactToMessages(SessionHandlerClient handler,
      boolean expectReturn) throws IOException, BrowserChannelException {
    while (true) {
      ExceptionOrReturnValue returnValue;
      MessageType type = Message.readMessageType(getStreamFromOtherSide());
      if (logger.isLoggable(TreeLogger.INFO)) {
        logger.log(TreeLogger.INFO, "client: received " + type + ", thread: "
            + Thread.currentThread().getName());
      }
      try {
        switch (type) {
          case INVOKE:
            InvokeOnClientMessage invokeMessage = InvokeOnClientMessage.receive(this);
            returnValue = handler.invoke(this, invokeMessage.getThis(),
                invokeMessage.getMethodName(), invokeMessage.getArgs());
            new ReturnMessage(this, returnValue.isException(),
                returnValue.getReturnValue()).send();
            break;
          case FREE_VALUE:
            FreeMessage freeMessage = FreeMessage.receive(this);
            if (logger.isLoggable(TreeLogger.DEBUG)) {
              logger.log(TreeLogger.DEBUG, type + " message "
                  + freeMessage.getIds());
            }
            handler.freeValue(this, freeMessage.getIds());
            // no response
            break;
          case LOAD_JSNI:
            LoadJsniMessage loadJsniMessage = LoadJsniMessage.receive(this);
            String jsniString = loadJsniMessage.getJsni();
            handler.loadJsni(this, jsniString);
            // no response
            break;
          case REQUEST_ICON:
            RequestIconMessage.receive(this);
            // no need for icon here
            UserAgentIconMessage.send(this, null);
            break;
          case RETURN:
            if (!expectReturn) {
              logger.log(TreeLogger.ERROR, "Received unexpected "
                  + MessageType.RETURN);
            }
            return ReturnMessage.receive(this);
          case QUIT:
            if (expectReturn) {
              logger.log(TreeLogger.ERROR, "Received " + MessageType.QUIT
                  + " while waiting for return");
            }
            disconnectFromHost();
            return null;
          default:
            logger.log(TreeLogger.ERROR, "Unkown messageType: " + type
                + ", expectReturn: " + expectReturn);
            disconnectFromHost();
            return null;
        }
      } catch (Exception ex) {
        logger.log(TreeLogger.ERROR, "Unknown exception" + ex);
        ex.printStackTrace();
      }
    }
  }
}
