/*
 * 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.dev.javac.JsniMethod;
import com.google.gwt.dev.shell.JsValue.DispatchObject;
import com.google.gwt.dev.util.log.speedtracer.DevModeEventType;
import com.google.gwt.dev.util.log.speedtracer.SpeedTracerLogger;
import com.google.gwt.dev.util.log.speedtracer.SpeedTracerLogger.Event;

import java.util.List;

/**
 */
public class ModuleSpaceOOPHM extends ModuleSpace {

  private BrowserChannelServer channel;

  public ModuleSpaceOOPHM(ModuleSpaceHost msh, String moduleName,
      BrowserChannelServer channel) {
    super(msh.getLogger(), msh, moduleName);
    this.channel = channel;
    msh.getLogger().log(TreeLogger.DEBUG,
        "Created ModuleSpaceOOPHM for " + moduleName, null);
  }

  @Override
  public void createNativeMethods(TreeLogger logger,
      List<JsniMethod> jsniMethods, DispatchIdOracle dispatchIdOracle) {
    if (jsniMethods.isEmpty()) {
      return;
    }
    StringBuilder jsni = new StringBuilder();
    for (JsniMethod jsniMethod : jsniMethods) {
      if (jsniMethod.isScriptOnly()) {
        continue;
      }
      String body = Jsni.getJavaScriptForHostedMode(dispatchIdOracle,
          jsniMethod);
      if (body == null) {
        // The error has been logged; just ignore it for now.
        continue;
      }
      jsni.append("// " + jsniMethod.location() + ":" + jsniMethod.line()
          + "\n");
      jsni.append("this[\"" + jsniMethod.name() + "\"] = function(");
      String[] paramNames = jsniMethod.paramNames();
      for (int i = 0; i < paramNames.length; ++i) {
        if (i > 0) {
          jsni.append(", ");
        }
        jsni.append(paramNames[i]);
      }
      jsni.append(") ");
      jsni.append(body);
      jsni.append(";\n\n");
    }
    channel.loadJsni(jsni.toString());
  }

  /**
   *
   */
  @Override
  protected void createStaticDispatcher(TreeLogger logger) {
    channel.loadJsni("function __defineStatic(__arg0) { window.__static = __arg0; }");
  }

  /**
   * Invoke a JS method and return its value.
   *
   * @param name method name to invoke
   * @param jthis object to invoke method on, null if static method
   * @param types argument types
   * @param args argument values
   */
  @Override
  protected JsValue doInvoke(String name, Object jthis, Class<?>[] types,
      Object[] args) throws Throwable {
    TreeLogger branch = host.getLogger().branch(TreeLogger.SPAM,
        "Invoke native method " + name, null);
    Event javaToJsCallEvent =
        SpeedTracerLogger.start(DevModeEventType.JAVA_TO_JS_CALL);
    if (SpeedTracerLogger.jsniCallLoggingEnabled()) {
      javaToJsCallEvent.addData("name", name);
    }

    CompilingClassLoader isolatedClassLoader = getIsolatedClassLoader();
    JsValueOOPHM jsthis = new JsValueOOPHM();
    Class<?> jthisType = (jthis == null) ? Object.class : jthis.getClass();
    JsValueGlue.set(jsthis, isolatedClassLoader, jthisType, jthis);
    if (branch.isLoggable(TreeLogger.SPAM)) {
      branch.log(TreeLogger.SPAM, "  this=" + jsthis);
    }

    int argc = args.length;
    JsValueOOPHM argv[] = new JsValueOOPHM[argc];
    for (int i = 0; i < argc; ++i) {
      argv[i] = new JsValueOOPHM();
      JsValueGlue.set(argv[i], isolatedClassLoader, types[i], args[i]);
      if (branch.isLoggable(TreeLogger.SPAM)) {
        branch.log(TreeLogger.SPAM, "  arg[" + i + "]=" + argv[i]);
      }
    }
    JsValueOOPHM returnVal = new JsValueOOPHM();
    try {
      channel.invokeJavascript(isolatedClassLoader, jsthis, name, argv,
          returnVal);
      if (branch.isLoggable(TreeLogger.SPAM)) {
        branch.log(TreeLogger.SPAM, "  returned " + returnVal);
      }
      return returnVal;
    } catch (Throwable t) {
      branch.log(TreeLogger.SPAM, "exception thrown", t);
      throw t;
    } finally {
      javaToJsCallEvent.end();
    }
  }

  @Override
  protected DispatchObject getStaticDispatcher() {
    return new JsValueOOPHM.DispatchObjectOOPHM(getIsolatedClassLoader());
  }
}
