/*
 * 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.dev.shell.BrowserChannel.InvokeOnServerMessage;
import com.google.gwt.dev.shell.BrowserChannel.JavaObjectRef;
import com.google.gwt.dev.shell.BrowserChannel.ReturnMessage;
import com.google.gwt.dev.shell.BrowserChannel.SessionHandler.ExceptionOrReturnValue;
import com.google.gwt.dev.shell.BrowserChannel.Value;

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 net.sourceforge.htmlunit.corejs.javascript.Undefined;

import java.io.IOException;

/**
 * Class to encapsulate JavaObject on the server side.
 */
public class JavaObject extends ScriptableObject implements Function {

  private static final long serialVersionUID = -7923090130737830902L;
  private static final ExceptionOrReturnValue DEFAULT_VALUE = new ExceptionOrReturnValue(
      true, new Value());

  public static JavaObject getOrCreateJavaObject(JavaObjectRef javaRef,
      SessionData sessionData, Context context) {
    return sessionData.getSessionHandler().getOrCreateJavaObject(
        javaRef.getRefid(), context);
  }

  /**
   * @param cx the Context
   */
  static ExceptionOrReturnValue getReturnFromJavaMethod(Context cx,
      HtmlUnitSessionHandler sessionHandler, BrowserChannelClient channel,
      int dispatchId, Value thisValue, Value valueArgs[]) {

    synchronized (sessionHandler.getSynchronizationObject()) {
      try {
        new InvokeOnServerMessage(channel, dispatchId, thisValue, valueArgs).send();
      } catch (IOException e) {
        return DEFAULT_VALUE;
      }
      try {
        ReturnMessage returnMessage = channel.reactToMessagesWhileWaitingForReturn(sessionHandler);
        return new ExceptionOrReturnValue(returnMessage.isException(),
            returnMessage.getReturnValue());
      } catch (IOException e) {
        return DEFAULT_VALUE;
      } catch (BrowserChannelException e) {
        return DEFAULT_VALUE;
      }
    }
  }

  /**
   * @param jsContext the Context
   */
  static boolean isJavaObject(Context jsContext, ScriptableObject javaObject) {
    return javaObject instanceof JavaObject;
  }

  private Context jsContext;

  private final int objectRef;

  private final SessionData sessionData;

  public JavaObject(Context jsContext, SessionData sessionData, int objectRef) {
    this.objectRef = objectRef;
    this.sessionData = sessionData;
    this.jsContext = jsContext;
  }

  /*
   * If this function fails for any reason, we return Undefined instead of
   * throwing an Exception in all cases except when Java throws an Exception.
   */
  @Override
  public Object call(Context cx, Scriptable scope, Scriptable thisObj,
      Object[] args) {

    if (args.length < 2) {
      return Undefined.instance;
    }
    Value valueArgs[] = new Value[args.length - 2];
    for (int i = 0; i < valueArgs.length; i++) {
      valueArgs[i] = sessionData.getSessionHandler().makeValueFromJsval(cx,
          args[i + 2]);
    }

    /**
     * Called when the JavaObject is invoked as a function. We ignore the
     * thisObj argument, which is usually the window object.
     *
     * Returns a JS array, with the first element being a boolean indicating
     * that an exception occured, and the second element is either the return
     * value or the exception which was thrown. In this case, we always return
     * false and raise the exception ourselves.
     */

    Value thisValue = sessionData.getSessionHandler().makeValueFromJsval(cx,
        args[1]);
    int dispatchId = ((Number) args[0]).intValue();

    ExceptionOrReturnValue returnValue = getReturnFromJavaMethod(cx,
        sessionData.getSessionHandler(), sessionData.getChannel(), dispatchId,
        thisValue, valueArgs);
    /*
     * Return a object array ret. ret[0] is a boolean indicating whether an
     * exception was thrown or not. ret[1] is the exception or the return value.
     */
    Object ret[] = new Object[2];
    ret[0] = returnValue.isException();
    ret[1] = sessionData.getSessionHandler().makeJsvalFromValue(cx,
        returnValue.getReturnValue());
    return ret;
  }

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

  // ignoring the 'start' argument.
  @Override
  public Object get(int index, Scriptable start) {
    Value value = ServerMethods.getProperty(sessionData.getChannel(),
        sessionData.getSessionHandler(), objectRef, index);
    return sessionData.getSessionHandler().makeJsvalFromValue(jsContext, value);
  }

  // ignoring the 'start' argument.
  @Override
  public Object get(String name, Scriptable start) {
    if ("toString".equals(name)) {
      return sessionData.getSessionHandler().getToStringTearOff(jsContext);
    }
    if ("id".equals(name)) {
      return objectRef;
    }
    if ("__noSuchMethod__".equals(name)) {
      return Undefined.instance;
    }
    System.err.println("Unknown property name in get " + name);
    return Undefined.instance;
  }

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

  @Override
  public void put(int dispatchId, Scriptable start, Object value) {
    HtmlUnitSessionHandler sessionHandler = sessionData.getSessionHandler();
    if (!ServerMethods.setProperty(sessionData.getChannel(), sessionHandler,
        objectRef, dispatchId, sessionHandler.makeValueFromJsval(jsContext,
            value))) {
      // TODO: fix later.
      throw new RuntimeException("setProperty failed");
    }
  }

  int getRefId() {
    return objectRef;
  }
}
