/*
 * 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.core.ext.TreeLogger;
import com.google.gwt.core.ext.TreeLogger.HelpInfo;
import com.google.gwt.dev.shell.BrowserChannel.SessionHandler.ExceptionOrReturnValue;
import com.google.gwt.dev.shell.JsValue.DispatchObject;

import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.MalformedURLException;
import java.net.Socket;
import java.net.URL;
import java.util.HashMap;
import java.util.Map;
import java.util.Set;

/**
 * Server-side of the browser channel protocol.
 */
public class BrowserChannelServer extends BrowserChannel
    implements Runnable {
  
  /**
   * Hook interface for responding to messages from the client.
   */
  public abstract static class SessionHandlerServer extends SessionHandler<BrowserChannelServer> {
    public abstract ExceptionOrReturnValue getProperty(BrowserChannelServer channel,
        int refId, int dispId);

    public abstract ExceptionOrReturnValue invoke(BrowserChannelServer channel,
        Value thisObj, int dispId, Value[] args);

    /**
     * Load a new instance of a module.
     *
     * @param channel
     * @param moduleName
     * @param userAgent
     * @param url top-level URL of the main page, null if using an old plugin
     * @param tabKey opaque key of the tab, may be empty if the plugin can't
     *     distinguish tabs or null if using an old plugin
     * @param sessionKey opaque key for this session, null if using an old plugin
     * @param userAgentIcon byte array containing an icon (which fits within
     *     24x24) representing the user agent or null if unavailable
     * @return a TreeLogger to use for the module's logs, or null if the module
     *     load failed
     */
    public abstract TreeLogger loadModule(BrowserChannelServer channel,
        String moduleName, String userAgent, String url, String tabKey,
        String sessionKey, byte[] userAgentIcon);

    public abstract ExceptionOrReturnValue setProperty(BrowserChannelServer channel,
        int refId, int dispId, Value newValue);

    public abstract void unloadModule(BrowserChannelServer channel, String moduleName);
  }

  private static class ServerObjectRefFactory implements ObjectRefFactory {

    private final RemoteObjectTable<JsObjectRef> remoteObjectTable;
    
    public ServerObjectRefFactory() {
      remoteObjectTable = new RemoteObjectTable<JsObjectRef>();
    }

    public JavaObjectRef getJavaObjectRef(int refId) {
      return new JavaObjectRef(refId);
    }

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

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

  /**
   * Full qualified class name of JavaScriptObject.  This must be a string
   * because this class is in a different class loader.
   */
  public static final String JSO_CLASS = "com.google.gwt.core.client.JavaScriptObject";

  private static Map<String, byte[]> iconCache = new HashMap<String, byte[]>();
  
  private static final Object cacheLock = new Object();

  private final SessionHandlerServer handler;

  private final boolean ignoreRemoteDeath;

  private final ServerObjectsTable javaObjectsInBrowser = new ServerObjectsTable();

  private TreeLogger logger;

  private String moduleName;

  private String userAgent;

  private int protocolVersion = -1;

  /**
   * Create a code server for the supplied socket.
   * 
   * @param initialLogger
   * @param socket
   * @param handler
   * @param ignoreRemoteDeath
   * @throws IOException
   */
  public BrowserChannelServer(TreeLogger initialLogger, Socket socket,
      SessionHandlerServer handler, boolean ignoreRemoteDeath) throws IOException {
    super(socket, new ServerObjectRefFactory());
    this.handler = handler;
    this.ignoreRemoteDeath = ignoreRemoteDeath;
    init(initialLogger);
  }

  // @VisibleForTesting
  BrowserChannelServer(TreeLogger initialLogger, InputStream inputStream,
      OutputStream outputStream, SessionHandlerServer handler,
      boolean ignoreRemoteDeath) {
    super(inputStream, outputStream, new ServerObjectRefFactory());
    this.handler = handler;
    this.ignoreRemoteDeath = ignoreRemoteDeath;
    init(initialLogger);
  }

  /**
   * Indicate that Java no longer has references to the supplied JS objects.
   * 
   * @param ids array of JS object IDs that have been freeded
   */
  public void freeJsValue(int[] ids) {
    try {
      new FreeMessage(this, ids).send();
    } catch (IOException e) {
      // TODO(jat): error handling?
      e.printStackTrace();
      throw new HostedModeException("I/O error communicating with client");
    }
  }

  /**
   * @return the table of Java objects which have been sent to the browser.
   */
  public ServerObjectsTable getJavaObjectsExposedInBrowser() {
    return javaObjectsInBrowser;
  }

  /**
   * @return the negotiated protocol version, or -1 if not yet negotiated.
   */
  public int getProtocolVersion() {
    return protocolVersion;
  }

  public ReturnMessage invoke(String methodName, Value vthis, Value[] vargs,
      SessionHandlerServer handler) throws IOException, BrowserChannelException {
    new InvokeOnClientMessage(this, methodName, vthis, vargs).send();
    return reactToMessagesWhileWaitingForReturn(handler);
  }

  /**
   * @param ccl
   * @param jsthis
   * @param methodName
   * @param args
   * @param returnJsValue
   * @throws Throwable
   */
  public void invokeJavascript(CompilingClassLoader ccl, JsValueOOPHM jsthis,
      String methodName, JsValueOOPHM[] args, JsValueOOPHM returnJsValue)
      throws Throwable {
    final ServerObjectsTable remoteObjects = getJavaObjectsExposedInBrowser();
    Value vthis = convertFromJsValue(remoteObjects, jsthis);
    Value[] vargs = new Value[args.length];
    for (int i = 0; i < args.length; ++i) {
      vargs[i] = convertFromJsValue(remoteObjects, args[i]);
    }
    try {
      InvokeOnClientMessage invokeMessage = new InvokeOnClientMessage(this,
          methodName, vthis, vargs);
      invokeMessage.send();
      final ReturnMessage msg = reactToMessagesWhileWaitingForReturn(handler);
      Value returnValue = msg.getReturnValue();
      convertToJsValue(ccl, remoteObjects, returnValue, returnJsValue);
      if (msg.isException()) {
        Object exceptionValue;
        if (returnValue.isNull() || returnValue.isUndefined()) {
          exceptionValue = null;
        } else if (returnValue.isString()) {
          exceptionValue = returnValue.getString();
        } else if (returnValue.isJsObject()) {
          exceptionValue = JsValueGlue.createJavaScriptObject(returnJsValue,
              ccl);
        } else if (returnValue.isJavaObject()) {
          Object object = remoteObjects.get(returnValue.getJavaObject().getRefid());
          Object target = ((JsValueOOPHM.DispatchObjectOOPHM) object).getTarget();
          if (target instanceof Throwable) {
            throw (Throwable) (target);
          } else {
            // JS throwing random Java Objects, which we'll wrap in JSException
            exceptionValue = target;
          }
        } else {
          // JS throwing random primitives, which we'll wrap as a string in
          // JSException
          exceptionValue = returnValue.getValue().toString();
        }
        RuntimeException exception = ModuleSpace.createJavaScriptException(
            ccl, exceptionValue);
        // reset the stack trace to here to minimize GWT infrastructure in
        // the stack trace
        exception.fillInStackTrace();
        throw exception;
      }
    } catch (IOException e) {
      throw new RemoteDeathError(e);
    } catch (BrowserChannelException e) {
      throw new RemoteDeathError(e);
    }
  }

  /**
   * Load the supplied JSNI code into the browser.
   * 
   * @param jsni JSNI source to load into the browser
   */
  public void loadJsni(String jsni) {
    try {
      LoadJsniMessage jsniMessage = new LoadJsniMessage(this, jsni);
      jsniMessage.send();
      // we do not wait for a return value
    } catch (IOException e) {
      throw new RemoteDeathError(e);
    }
  }

  /**
   * React to messages from the other side, where no return value is expected.
   * 
   * @param handler
   * @throws RemoteDeathError
   */
  public void reactToMessages(SessionHandlerServer handler) {
    do {
      try {
        getStreamToOtherSide().flush();
        MessageType messageType = Message.readMessageType(
            getStreamFromOtherSide());
        switch (messageType) {
          case FREE_VALUE:
            final FreeMessage freeMsg = FreeMessage.receive(this);
            handler.freeValue(this, freeMsg.getIds());
            break;
          case INVOKE:
            InvokeOnServerMessage imsg = InvokeOnServerMessage.receive(this);
            ExceptionOrReturnValue result = handler.invoke(this, imsg.getThis(),
                imsg.getMethodDispatchId(), imsg.getArgs());
            sendFreedValues();
            ReturnMessage.send(this, result);
            break;
          case INVOKE_SPECIAL:
            handleInvokeSpecial(handler);
            break;
          case QUIT:
            return;
          default:
            throw new RemoteDeathError(new BrowserChannelException(
                "Invalid message type " + messageType));
        }
      } catch (IOException e) {
        throw new RemoteDeathError(e);
      } catch (BrowserChannelException e) {
        throw new RemoteDeathError(e);
      }
    } while (true);
  }

  /**
   * React to messages from the other side, where a return value is expected.
   * 
   * @param handler
   * @throws BrowserChannelException 
   * @throws RemoteDeathError
   */
  public ReturnMessage reactToMessagesWhileWaitingForReturn(
      SessionHandlerServer handler) throws BrowserChannelException, RemoteDeathError {
    do {
      try {
        getStreamToOtherSide().flush();
        MessageType messageType = Message.readMessageType(
            getStreamFromOtherSide());
        switch (messageType) {
          case FREE_VALUE:
            final FreeMessage freeMsg = FreeMessage.receive(this);
            handler.freeValue(this, freeMsg.getIds());
            break;
          case RETURN:
            return ReturnMessage.receive(this);
          case INVOKE:
            InvokeOnServerMessage imsg = InvokeOnServerMessage.receive(this);
            ExceptionOrReturnValue result = handler.invoke(this, imsg.getThis(),
                imsg.getMethodDispatchId(), imsg.getArgs());
            sendFreedValues();
            ReturnMessage.send(this, result);
            break;
          case INVOKE_SPECIAL:
            handleInvokeSpecial(handler);
            break;
          case QUIT:
            // if we got an unexpected QUIT here, the remote plugin probably
            // realized it was dying and had time to close the socket properly.
            throw new RemoteDeathError(null);
          default:
            throw new BrowserChannelException("Invalid message type "
                + messageType + " received waiting for return.");
        }
      } catch (IOException e) {
        throw new RemoteDeathError(e);
      } catch (BrowserChannelException e) {
        throw new RemoteDeathError(e);
      }
    } while (true);
  }

  public void run() {
    try {
      processConnection();
    } catch (IOException e) {
      logger.log(TreeLogger.WARN, "Client connection lost", e);
    } catch (BrowserChannelException e) {
      logger.log(TreeLogger.ERROR,
          "Unrecognized command for client; closing connection", e);
    } finally {
      try {
        shutdown();
      } catch (IOException ignored) {
      }
      endSession();
    }
  }

  /**
   * Close the connection to the browser.
   * 
   * @throws IOException
   */
  public void shutdown() throws IOException {
    QuitMessage.send(this);
  }

  // @VisibleForTesting
  protected void processConnection() throws IOException, BrowserChannelException {
    MessageType type = Message.readMessageType(getStreamFromOtherSide());
    // TODO(jat): add support for getting the a shim plugin downloading the
    //    real plugin via a GetRealPlugin message before CheckVersions
    String url = null;
    String tabKey = null;
    String sessionKey = null;
    byte[] iconBytes = null;
    switch (type) {
      case OLD_LOAD_MODULE:
        // v1 client
        OldLoadModuleMessage oldLoadModule = OldLoadModuleMessage.receive(this);
        if (oldLoadModule.getProtoVersion() != 1) {
          // This message type was only used in v1, so something is really
          // broken here.
          throw new BrowserChannelException(
              "Old LoadModule message used, but not v1 protocol");
        }
        moduleName = oldLoadModule.getModuleName();
        userAgent = oldLoadModule.getUserAgent();
        protocolVersion = 1;
        HelpInfo helpInfo = new HelpInfo() {
          @Override
          public String getAnchorText() {
            return "UsingOOPHM wiki page";
          }

          @Override
          public URL getURL() {
            try {
              // TODO(jat): better landing page for more info
              return new URL(
                  "http://code.google.com/p/google-web-toolkit/wiki/UsingOOPHM");
            } catch (MalformedURLException e) {
              // can't happen
              return null;
            }
          }
        };
        logger.log(TreeLogger.WARN, "Connection from old browser plugin -- "
            + "please upgrade to a later version for full functionality", null,
            helpInfo);
        break;
      case CHECK_VERSIONS:
        String connectError = null;
        CheckVersionsMessage hello = CheckVersionsMessage.receive(this);
        int minVersion = hello.getMinVersion();
        int maxVersion = hello.getMaxVersion();
        String hostedHtmlVersion = hello.getHostedHtmlVersion();
        if (minVersion > PROTOCOL_VERSION_CURRENT
            || maxVersion < PROTOCOL_VERSION_OLDEST) {
          connectError = "Client supported protocol version range "
              + minVersion + " - " + maxVersion + "; server "
              + PROTOCOL_VERSION_OLDEST + " - " + PROTOCOL_VERSION_CURRENT;
        } else {
          if (!HostedHtmlVersion.validHostedHtmlVersion(logger,
              hostedHtmlVersion)) {
            new FatalErrorMessage(this,
                "Invalid hosted.html version - check log window").send();
            return;
          }
        }
        if (connectError != null) {
          logger.log(TreeLogger.ERROR, "Connection error: " + connectError,
              null);
          new FatalErrorMessage(this, connectError).send();
          return;
        }
        protocolVersion = Math.min(PROTOCOL_VERSION_CURRENT, maxVersion);
        new ProtocolVersionMessage(this, protocolVersion).send();
        type = Message.readMessageType(getStreamFromOtherSide());
        
        // Optionally allow client to request switch of transports.  Inband is
        // always supported, so a return of an empty transport string requires
        // the client to stay in this channel.
        if (type == MessageType.CHOOSE_TRANSPORT) {
          ChooseTransportMessage chooseTransport = ChooseTransportMessage.receive(this);
          String transport = selectTransport(chooseTransport.getTransports());
          String transportArgs = null;
          if (transport != null) {
            transportArgs = createTransport(transport);
          }
          new SwitchTransportMessage(this, transport, transportArgs).send();
          type = Message.readMessageType(getStreamFromOtherSide());
        }
        
        // Now we expect a LoadModule message to load a GWT module.
        if (type != MessageType.LOAD_MODULE) {
          logger.log(TreeLogger.ERROR, "Unexpected message type " + type
              + "; expecting LoadModule");
          return;
        }
        LoadModuleMessage loadModule = LoadModuleMessage.receive(this);
        url = loadModule.getUrl();
        tabKey = loadModule.getTabKey();
        sessionKey = loadModule.getSessionKey();
        moduleName = loadModule.getModuleName();
        userAgent = loadModule.getUserAgent();
        break;
      case REQUEST_PLUGIN:
        logger.log(TreeLogger.ERROR, "Plugin download not supported yet");
        // We can't clear the socket since we don't know how to interpret this
        // message yet -- it is only here now so we can give a better error
        // message with mixed versions once it is supported.
        new FatalErrorMessage(this, "Plugin download not supported").send();
        return;
      default:
        logger.log(TreeLogger.ERROR, "Unexpected message type " + type
            + "; expecting CheckVersions");
        return;
    }
    if (protocolVersion >= PROTOCOL_VERSION_GET_ICON) {
      synchronized (cacheLock) {
        if (iconCache.containsKey(userAgent)) {
          iconBytes = iconCache.get(userAgent);
        } else {
          RequestIconMessage.send(this);
          type = Message.readMessageType(getStreamFromOtherSide());
          if (type != MessageType.USER_AGENT_ICON) {
            logger.log(TreeLogger.ERROR, "Unexpected message type " + type
                + "; expecting UserAgentIcon");
            return;
          }
          UserAgentIconMessage uaIconMessage = UserAgentIconMessage.receive(
              this);
          iconBytes = uaIconMessage.getIconBytes();
          iconCache.put(userAgent, iconBytes);
        }
      }
    }
    Thread.currentThread().setName(
        "Code server for " + moduleName + " from " + userAgent + " on " + url
        + " @ " + sessionKey);
    logger = handler.loadModule(this, moduleName, userAgent, url,
        tabKey, sessionKey, iconBytes);
    if (logger == null) {
      // got an error
      try {
        Value errMsg = new Value();
        errMsg.setString("An error occurred loading the GWT module "
            + moduleName);
        ReturnMessage.send(this, true, errMsg);
        return;
      } catch (IOException e) {
        throw new RemoteDeathError(e);
      }
    }
    try {
      // send LoadModule response
      try {
        ReturnMessage.send(this, false, new Value());
      } catch (IOException e) {
        throw new RemoteDeathError(e);
      }
      reactToMessages(handler);
    } catch (RemoteDeathError e) {
      if (!ignoreRemoteDeath) {
        logger.log(TreeLogger.ERROR, e.getMessage(), e);
      }
    } finally {
      handler.unloadModule(this, moduleName);
    }
  }

  /**
   * Convert a JsValue into a BrowserChannel Value.
   * 
   * @param localObjects lookup table for local objects -- may be null if jsval
   *          is known to be a primitive (including String).
   * @param jsval value to convert
   * @return jsval as a Value object.
   */
  Value convertFromJsValue(ServerObjectsTable localObjects, JsValueOOPHM jsval) {
    Value value = new Value();
    if (jsval.isNull()) {
      value.setNull();
    } else if (jsval.isUndefined()) {
      value.setUndefined();
    } else if (jsval.isBoolean()) {
      value.setBoolean(jsval.getBoolean());
    } else if (jsval.isInt()) {
      value.setInt(jsval.getInt());
    } else if (jsval.isNumber()) {
      value.setDouble(jsval.getNumber());
    } else if (jsval.isString()) {
      value.setString(jsval.getString());
    } else if (jsval.isJavaScriptObject()) {
      value.setJsObject(jsval.getJavascriptObject());
    } else if (jsval.isWrappedJavaObject()) {
      assert localObjects != null;
      DispatchObject javaObj = jsval.getJavaObjectWrapper();
      value.setJavaObject(new JavaObjectRef(localObjects.add(javaObj)));
    } else if (jsval.isWrappedJavaFunction()) {
      assert localObjects != null;
      value.setJavaObject(new JavaObjectRef(
          localObjects.add(jsval.getWrappedJavaFunction())));
    } else {
      throw new RuntimeException("Unknown JsValue type " + jsval);
    }
    return value;
  }

  /**
   * Convert a BrowserChannel Value into a JsValue.
   * 
   * @param ccl Compiling class loader, may be null if val is known to not be a
   *          Java object or exception.
   * @param localObjects table of Java objects, may be null as above.
   * @param val Value to convert
   * @param jsval JsValue object to receive converted value.
   */
  void convertToJsValue(CompilingClassLoader ccl, ServerObjectsTable localObjects,
      Value val, JsValueOOPHM jsval) {
    switch (val.getType()) {
      case NULL:
        jsval.setNull();
        break;
      case BOOLEAN:
        jsval.setBoolean(val.getBoolean());
        break;
      case BYTE:
        jsval.setByte(val.getByte());
        break;
      case CHAR:
        jsval.setChar(val.getChar());
        break;
      case DOUBLE:
        jsval.setDouble(val.getDouble());
        break;
      case FLOAT:
        jsval.setDouble(val.getFloat());
        break;
      case INT:
        jsval.setInt(val.getInt());
        break;
      case LONG:
        jsval.setDouble(val.getLong());
        break;
      case SHORT:
        jsval.setShort(val.getShort());
        break;
      case STRING:
        jsval.setString(val.getString());
        break;
      case UNDEFINED:
        jsval.setUndefined();
        break;
      case JS_OBJECT:
        jsval.setJavascriptObject(val.getJsObject());
        break;
      case JAVA_OBJECT:
        assert ccl != null && localObjects != null;
        jsval.setWrappedJavaObject(ccl,
            localObjects.get(val.getJavaObject().getRefid()));
        break;
    }
  }

  /**
   * Create the requested transport and return the appropriate information so
   * the client can connect to the same transport.
   * 
   * @param transport transport name to create
   * @return transport-specific arguments for the client to use in attaching
   *     to this transport
   */
  private String createTransport(String transport) {
    // TODO(jat): implement support for additional transports
    throw new UnsupportedOperationException(
        "No alternate transports supported");
  }

  private void handleInvokeSpecial(SessionHandlerServer handler) throws IOException,
      BrowserChannelException {
    final InvokeSpecialMessage ismsg = InvokeSpecialMessage.receive(this);
    Value[] args = ismsg.getArgs();
    ExceptionOrReturnValue retExc = null;
    switch (ismsg.getDispatchId()) {
      case GetProperty:
        assert args.length == 2;
        retExc = handler.getProperty(this, args[0].getInt(), args[1].getInt());
        break;
      case SetProperty:
        assert args.length == 3;
        retExc = handler.setProperty(this, args[0].getInt(), args[1].getInt(),
            args[2]);
        break;
      default:
        throw new HostedModeException("Unexpected InvokeSpecial method "
            + ismsg.getDispatchId());
    }
    ReturnMessage.send(this, retExc);
  }

  private void init(TreeLogger initialLogger) {
    this.logger = initialLogger;
    Thread thread = new Thread(this);
    thread.setDaemon(true);
    thread.setName("Code server (initializing)");
    thread.start();
  }

  /**
   * Select a transport from those provided by the client.
   * 
   * @param transports array of supported transports
   * @return null to continue in-band, or a transport type
   */
  private String selectTransport(String[] transports) {
    // TODO(jat): add support for shared memory, others
    return null;
  }
}
