/*
 * 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.Arrays;
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, methodName + "(" + Arrays.toString(args) + ")");
        // 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().devModeSessionEnd(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 INT:
        jsval.setInt(val.getInt());
        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().devModeSessionBegin(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;
  }
}
