/*
 * 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 com.google.gwt.dev.util.log.dashboard.DashboardNotifier;
import com.google.gwt.dev.util.log.dashboard.DashboardNotifierFactory;

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 DevModeSession devModeSession;

  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");
    }
  }

  /**
   * Returns the {@code DevModeSession} representing this browser connection.
   */
  public DevModeSession getDevModeSession() {
    return devModeSession;
  }

  /**
   * @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 {
    getDashboardNotifier().devModeSessionEnded(devModeSession);
    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);

    createDevModeSession();

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

  /**
   * Returns the {@code DashboardNotifier} used to send notices to a dashboard
   * service.
   */
  // @VisibleForTesting
  DashboardNotifier getDashboardNotifier() {
    return DashboardNotifierFactory.getNotifier();
  }

  /**
   * Creates the {@code DevModeSession} that represents the current browser
   * connection, sets it as the "default" session for the current thread, and
   * notifies a GWT Dashboard.
   */
  private void createDevModeSession() {
    devModeSession = new DevModeSession(moduleName, userAgent);
    DevModeSession.setSessionForCurrentThread(devModeSession);
    getDashboardNotifier().devModeSession(devModeSession);
  }

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