/*
 * 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.gargoylesoftware.htmlunit.javascript.JavaScriptEngine;
import com.gargoylesoftware.htmlunit.javascript.host.Window;
import com.gargoylesoftware.htmlunit.javascript.host.WindowProxy;

import net.sourceforge.htmlunit.corejs.javascript.Context;
import net.sourceforge.htmlunit.corejs.javascript.Function;
import net.sourceforge.htmlunit.corejs.javascript.Scriptable;
import net.sourceforge.htmlunit.corejs.javascript.ScriptableObject;

import java.io.IOException;

/**
 * HTMLUnit object that represents the hosted-mode plugin.
 */
public class HostedModePluginObject extends ScriptableObject {

  /**
   * Function object which implements the connect method on the hosted-mode
   * plugin.
   */
  private class ConnectMethod extends ScriptableObject implements Function {

    private static final long serialVersionUID = -8799481412144205779L;
    private static final int EXPECTED_NUM_ARGS = 5;

    public Object call(Context context, Scriptable scope, Scriptable thisObj,
        Object[] args) {
      // Allow extra arguments for forward compatibility
      if (args.length < EXPECTED_NUM_ARGS) {
        throw Context.reportRuntimeError("Bad number of parameters for function"
            + " connect: expected "
            + EXPECTED_NUM_ARGS
            + ", got "
            + args.length);
      }
      try {
        /*
         * connect arguments: url, sessionKey, ipAddress:port, moduleName,
         * hostedHtmlVersion
         */
        return connect((String) args[0], (String) args[1], (String) args[2],
            (String) args[3], (String) args[4]);
      } catch (ClassCastException e) {
        throw Context.reportRuntimeError("Incorrect parameter types for "
            + " connect: expected String/String/String/String/String");
      }
    }

    public Scriptable construct(Context context, Scriptable scope, Object[] args) {
      throw Context.reportRuntimeError("Function connect can't be used as a "
          + "constructor");
    }

    @Override
    public String getClassName() {
      return "function HostedModePluginObject.connect";
    }
  }

  /**
   * Function object which implements the disconnect method on the hosted-mode
   * plugin.
   */
  private class DisconnectMethod extends ScriptableObject implements Function {

    private static final long serialVersionUID = -8799481412144519779L;

    public Object call(Context context, Scriptable scope, Scriptable thisObj,
        Object[] args) {
      // Allow extra arguments for forward compatibility
      return disconnect();
    }

    public Scriptable construct(Context context, Scriptable scope, Object[] args) {
      throw Context.reportRuntimeError("Function disconnect can't be used as a "
          + "constructor");
    }

    @Override
    public String getClassName() {
      return "function HostedModePluginObject.disconnect";
    }
  }

  /**
   * Function object which implements the init method on the hosted-mode plugin.
   */
  private class InitMethod extends ScriptableObject implements Function {

    private static final long serialVersionUID = -8799481412144205779L;
    private static final String VERSION = "2.0";

    public Object call(Context context, Scriptable scope, Scriptable thisObj,
        Object[] args) {
      // Allow extra arguments for forward compatibility
      if (args.length < 1) {
        throw Context.reportRuntimeError("Bad number of parameters for function"
            + " init: expected 1, got " + args.length);
      }
      try {
        window = ((WindowProxy) args[0]).getDelegee();
        return init(VERSION);
      } catch (ClassCastException e) {
        throw Context.reportRuntimeError("Incorrect parameter types for "
            + " initt: expected String");
      }
    }

    public Scriptable construct(Context context, Scriptable scope, Object[] args) {
      throw Context.reportRuntimeError("Function init can't be used as a "
          + "constructor");
    }

    @Override
    public String getClassName() {
      return "function HostedModePluginObject.init";
    }
  }

  private static final long serialVersionUID = -1815031145376726799L;

  private Scriptable connectMethod;
  private Scriptable disconnectMethod;
  private Scriptable initMethod;
  private Window window;
  private final JavaScriptEngine jsEngine;
  private final TreeLogger logger;

  private BrowserChannelClient browserChannelClient;

  /**
   * Creates a HostedModePluginObject with the passed-in JavaScriptEngine.
   * 
   * @param jsEngine The JavaScriptEngine.
   */
  public HostedModePluginObject(JavaScriptEngine jsEngine, TreeLogger logger) {
    this.jsEngine = jsEngine;
    this.logger = logger;
  }

  /**
   * Initiate a hosted mode connection to the requested port and load the
   * requested module.
   * 
   * @param url the complete url
   * @param sessionKey a length 16 string to identify a "session"
   * @param address "host:port" or "ipAddress:port" to use for the OOPHM server
   * @param module module name to load
   * @param version version string
   * @return true if the connection succeeds
   */
  public boolean connect(String url, String sessionKey, String address,
      String module, String version) {
    String addressParts[] = address.split(":");
    if (addressParts.length < 2) {
      logger.log(TreeLogger.ERROR, "connect failed because address " + address
          + " was not of the form foo.com:8080");
      return false;
    }
    // TODO: add whitelist and default-port support?

    try {
      HtmlUnitSessionHandler htmlUnitSessionHandler = new HtmlUnitSessionHandler(
          window, jsEngine);
      browserChannelClient = new BrowserChannelClient(addressParts, url,
          sessionKey, module, version, htmlUnitSessionHandler);
      htmlUnitSessionHandler.setSessionData(new SessionData(
          htmlUnitSessionHandler, browserChannelClient));
      return browserChannelClient.process();
    } catch (BrowserChannelException e) {
      logger.log(TreeLogger.ERROR,
          "BrowserChannelException returned from connect " + e.getMessage(), e);
      return false;
    } catch (IOException e) {
      logger.log(TreeLogger.ERROR, "IOException returned from connect "
          + e.getMessage(), e);
      return false;
    }
  }

  public boolean disconnect() {
    try {
      return browserChannelClient.disconnectFromHost();
    } catch (IOException e) {
      logger.log(TreeLogger.ERROR, "IOException returned from disconnect "
          + e.getMessage(), e);
      return false;
    }
  }

  @Override
  public Object get(String name, Scriptable start) {
    if ("connect".equals(name)) {
      if (connectMethod == null) {
        connectMethod = new ConnectMethod();
      }
      return connectMethod;
    } else if ("disconnect".equals(name)) {
      if (disconnectMethod == null) {
        disconnectMethod = new DisconnectMethod();
      }
      return disconnectMethod;
    } else if ("init".equals(name)) {
      if (initMethod == null) {
        initMethod = new InitMethod();
      }
      return initMethod;
    }
    return NOT_FOUND;
  }

  @Override
  public String getClassName() {
    return "HostedModePluginObject";
  }

  /**
   * Verify that the plugin can be initialized properly and supports the
   * requested version.
   * 
   * @param version hosted mode protocol version
   * @return true if initialization succeeds, otherwise false
   */
  public boolean init(String version) {
    // TODO: what needs to be done here?
    return true;
  }
}
