/*
 * 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.JavaObjectRef;
import com.google.gwt.dev.shell.BrowserChannel.JsObjectRef;
import com.google.gwt.dev.shell.BrowserChannel.Value;
import com.google.gwt.dev.shell.BrowserChannel.Value.ValueType;
import com.google.gwt.dev.shell.BrowserChannelClient.SessionHandlerClient;
import com.google.gwt.dev.util.log.PrintWriterTreeLogger;

import com.gargoylesoftware.htmlunit.ScriptException;
import com.gargoylesoftware.htmlunit.ScriptResult;
import com.gargoylesoftware.htmlunit.WebWindow;
import com.gargoylesoftware.htmlunit.html.HtmlPage;
import com.gargoylesoftware.htmlunit.javascript.JavaScriptEngine;
import com.gargoylesoftware.htmlunit.javascript.SimpleScriptable;
import com.gargoylesoftware.htmlunit.javascript.SimpleScriptableProxy;
import com.gargoylesoftware.htmlunit.javascript.host.Window;

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

import java.util.HashMap;
import java.util.IdentityHashMap;
import java.util.Map;

/**
 * Handle session tasks for HtmlUnit.
 */
public class HtmlUnitSessionHandler extends SessionHandlerClient {

  private class ToStringMethod extends ScriptableObject implements Function {

    private static final int EXPECTED_NUM_ARGS = 0;
    private static final long serialVersionUID = 1592865718416163348L;

    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"
            + " toString: expected "
            + EXPECTED_NUM_ARGS
            + ", got "
            + args.length);
      }
      // thisObj is the javaObject.
      Value thisValue = makeValueFromJsval(context, thisObj);
      ExceptionOrReturnValue returnValue = JavaObject.getReturnFromJavaMethod(
          context, HtmlUnitSessionHandler.this, sessionData.getChannel(),
          TO_STRING_DISPATCH_ID, thisValue, EMPTY_VALUES);
      return HtmlUnitSessionHandler.this.makeJsvalFromValue(context,
          returnValue.getReturnValue());
    }

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

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

  private static final Value EMPTY_VALUES[] = new Value[0];
  private static final String REPLACE_METHOD_SIGNATURE = "@com.google.gwt.user.client.Window$Location::replace(Ljava/lang/String;)";
  private static final int TO_STRING_DISPATCH_ID = 0;

  Map<Integer, JavaObject> javaObjectCache;

  /**
   * The htmlPage is also used to synchronize calls to Java code.
   */
  private HtmlPage htmlPage;
  private JavaScriptEngine jsEngine;
  private IdentityHashMap<Scriptable, Integer> jsObjectToRef;
  private int nextRefId;
  private Map<Integer, Scriptable> refToJsObject;
  private SessionData sessionData;

  private final PrintWriterTreeLogger logger = new PrintWriterTreeLogger();

  private final ToStringMethod toStringMethod = new ToStringMethod();

  private final Window window;

  HtmlUnitSessionHandler(Window window, JavaScriptEngine jsEngine) {
    this.window = window;
    logger.setMaxDetail(TreeLogger.ERROR);
    this.jsEngine = jsEngine;
    htmlPage = (HtmlPage) this.window.getWebWindow().getEnclosedPage();
    if (logger.isLoggable(TreeLogger.INFO)) {
      logger.log(TreeLogger.INFO, "jsEngine = " + jsEngine + ", HtmlPage = "
          + htmlPage);
    }

    jsObjectToRef = new IdentityHashMap<Scriptable, Integer>();
    nextRefId = 1;
    refToJsObject = new HashMap<Integer, Scriptable>();

    // related to JavaObject cache.
    javaObjectCache = new HashMap<Integer, JavaObject>();
  }

  @Override
  public void freeValue(BrowserChannelClient channel, int[] ids) {
    for (int id : ids) {
      Scriptable scriptable = refToJsObject.remove(id);
      if (scriptable != null) {
        jsObjectToRef.remove(scriptable);
      }
    }
  }

  public JavaObject getOrCreateJavaObject(int refId, Context context) {
    JavaObject javaObject = javaObjectCache.get(refId);
    if (javaObject == null) {
      javaObject = new JavaObject(context, sessionData, refId);
      javaObjectCache.put(refId, javaObject);
    }
    return javaObject;
  }

  @Override
  public HtmlPage getSynchronizationObject() {
    return htmlPage;
  }

  /**
   * @param jsContext the Context
   */
  public Object getToStringTearOff(Context jsContext) {
    return toStringMethod;
  }

  @Override
  public String getUserAgent() {
    return "HtmlUnit-"
        + jsEngine.getWebClient().getBrowserVersion().getUserAgent();
  }

  @SuppressWarnings("unchecked")
  @Override
  public ExceptionOrReturnValue invoke(BrowserChannelClient channel, Value thisObj,
      String methodName, Value[] args) {
    if (logger.isLoggable(TreeLogger.DEBUG)) {
      logger.log(TreeLogger.DEBUG, "INVOKE: thisObj: " + thisObj
          + ", methodName: " + methodName + ", args: " + args);
    }
    /*
     * 1. lookup functions by name. 2. Find context and scope. 3. Convert
     * thisObject to ScriptableObject 4. Convert args 5. Get return value
     */
    Context jsContext = Context.getCurrentContext();
    ScriptableObject jsThis = null;
    if (thisObj.getType() == ValueType.NULL) {
      jsThis = window;
    } else {
      Object obj = makeJsvalFromValue(jsContext, thisObj);
      if (obj instanceof ScriptableObject) {
        jsThis = (ScriptableObject) obj;
      } else if (obj instanceof SimpleScriptableProxy<?>) {
        jsThis = ((SimpleScriptableProxy<SimpleScriptable>) obj).getDelegee();
      } else {
        logger.log(TreeLogger.ERROR, "Unable to convert " + obj + " to either "
            + " ScriptableObject or SimpleScriptableProxy");
        return new ExceptionOrReturnValue(true, new Value(null));
      }
    }
    Object functionObject = ScriptableObject.getProperty(
        window, methodName);
    if (functionObject == ScriptableObject.NOT_FOUND) {
      logger.log(TreeLogger.ERROR, "function " + methodName
          + " NOT FOUND, thisObj: " + jsThis + ", methodName: " + methodName);
      // TODO: see if this maps to QUIT
      return new ExceptionOrReturnValue(true, new Value(null));
    }
    Function jsFunction = (Function) functionObject;
    if (logger.isLoggable(TreeLogger.SPAM)) {
      logger.log(TreeLogger.SPAM, "INVOKE: jsFunction: " + jsFunction);
    }

    Object jsArgs[] = new Object[args.length];
    for (int i = 0; i < args.length; i++) {
      jsArgs[i] = makeJsvalFromValue(jsContext, args[i]);
    }
    Object result = null;
    try {
      if (args.length == 1
          && methodName.indexOf(REPLACE_METHOD_SIGNATURE) != -1) {
        // getUrl() is not visible
        String currentUrl = window.getLocation().toString();
        currentUrl = getUrlBeforeHash(currentUrl);
        String newUrl = getUrlBeforeHash((String) args[0].getValue());
        if (!newUrl.equals(currentUrl)) {
          WebWindow webWindow = window.getWebWindow();
          do {
            webWindow.getJobManager().removeAllJobs();
            webWindow = webWindow.getParentWindow();
          } while (webWindow != webWindow.getTopWindow());
        }
      }
      result = jsEngine.callFunction(htmlPage, jsFunction, window,
          jsThis, jsArgs);     
    } catch (ScriptException se) {
      if (se.getCause() instanceof JavaScriptException) {
        JavaScriptException ex = (JavaScriptException) se.getCause();
        if (logger.isLoggable(TreeLogger.INFO)) {
          logger.log(TreeLogger.INFO, "INVOKE: JavaScriptException " + ex
              + ", message: " + ex.getMessage() + " when invoking "
              + methodName);
        }
        return new ExceptionOrReturnValue(true, makeValueFromJsval(jsContext,
            ex.getValue()));
      } else {
        if (logger.isLoggable(TreeLogger.INFO)) {
          logger.log(TreeLogger.INFO, "INVOKE: exception " + se + ", message: "
            + se.getMessage() + " when invoking " + methodName);
        }
        return new ExceptionOrReturnValue(true, makeValueFromJsval(jsContext,
          Undefined.instance));
      }
    } catch (Exception ex) {
      if (logger.isLoggable(TreeLogger.INFO)) {
        logger.log(TreeLogger.INFO, "INVOKE: exception " + ex + ", message: "
            + ex.getMessage() + " when invoking " + methodName);
      }
      return new ExceptionOrReturnValue(true, makeValueFromJsval(jsContext,
          Undefined.instance));
    }
    if (logger.isLoggable(TreeLogger.INFO)) {
      logger.log(TreeLogger.INFO, "INVOKE: result: " + result
          + " of jsFunction: " + jsFunction);
    }
    return new ExceptionOrReturnValue(false, makeValueFromJsval(jsContext,
        result));
  }

  @Override
  public void loadJsni(BrowserChannelClient channel, String jsniString) {
    if (logger.isLoggable(TreeLogger.SPAM)) {
      logger.log(TreeLogger.SPAM, "LOAD_JSNI: " + jsniString);
    }
    ScriptResult scriptResult = htmlPage.executeJavaScript(jsniString);
    if (logger.isLoggable(TreeLogger.INFO)) {
      logger.log(TreeLogger.INFO, "LOAD_JSNI: scriptResult=" + scriptResult);
    }
  }

  /**
   * @param jsContext the Context
   */
  public Value makeValueFromJsval(Context jsContext, Object value) {
    if (value == Undefined.instance) {
      return new Value();
    }
    if (value instanceof JavaObject) {
      Value returnVal = new Value();
      int refId = ((JavaObject) value).getRefId();
      returnVal.setJavaObject(new JavaObjectRef(refId));
      return returnVal;
    }
    if (value instanceof Scriptable) {
      if (value instanceof ScriptableObject) {
        /*
         * HACK: check for native types like NativeString. NativeString is
         * package-protected. What other types do we need to check?
         */
        ScriptableObject scriptableValue = (ScriptableObject) value;
        String className = scriptableValue.getClassName();
        if (className.equals("String")) {
          return new Value(scriptableValue.toString());
        }
      }
      Integer refId = jsObjectToRef.get(value);
      if (refId == null) {
        refId = nextRefId++;
        jsObjectToRef.put((Scriptable) value, refId);
        refToJsObject.put(refId, (Scriptable) value);
      }
      Value returnVal = new Value();
      returnVal.setJsObject(new JsObjectRef(refId));
      return returnVal;
    }
    if (value instanceof ConsString) {
      return new Value(value.toString());
    }
    if (value instanceof Number) {
      return new Value(convertNumberFromJsval(((Number) value)));
    }
    return new Value(value);
  }

  /**
   * HtmlUnit can return non-js types for numerical values e.g. long for TypedArrays. This method
   * mimics the type conversion for numeric values in other devmode plugins so that we will have
   * similar behavior in HtmlUnit as well.
   */
  private Object convertNumberFromJsval(Number number) {
    if (number instanceof Byte || number instanceof Short || number instanceof Integer) {
      return number.intValue();
    }
    return number.doubleValue();
  }

  public void setSessionData(SessionData sessionData) {
    this.sessionData = sessionData;
  }

  /*
   * Returning java objects works. No need to return NativeNumber, NativeString,
   * NativeBoolean, or Undefined.
   */
  Object makeJsvalFromValue(Context jsContext, Value value) {
    switch (value.getType()) {
      case NULL:
        return null;
      case BOOLEAN:
        if (value.getBoolean()) {
          return Boolean.TRUE;
        }
        return Boolean.FALSE;
      case BYTE:
        return new Byte(value.getByte());
      case CHAR:
        return new Character(value.getChar());
      case SHORT:
        return new Short(value.getShort());
      case INT:
        return new Integer(value.getInt());
      case DOUBLE:
        return new Double(value.getDouble());
      case STRING:
        return value.getString();
      case JAVA_OBJECT:
        JavaObjectRef javaRef = value.getJavaObject();
        return JavaObject.getOrCreateJavaObject(javaRef, sessionData, jsContext);
      case JS_OBJECT:
        Scriptable scriptable = refToJsObject.get(value.getJsObject().getRefid());
        assert scriptable != null;
        return scriptable;
      case UNDEFINED:
        return Undefined.instance;
    }
    return null;
  }

  private String getUrlBeforeHash(String currentUrl) {
    int hashIndex = -1;
    if ((hashIndex = currentUrl.indexOf("#")) != -1) {
      currentUrl = currentUrl.substring(0, hashIndex);
    }
    return currentUrl;
  }
}
