/*
 * 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.UnableToCompleteException;
import com.google.gwt.dev.util.Name;
import com.google.gwt.dev.util.Name.BinaryName;
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.io.PrintWriter;
import java.io.StringWriter;
import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.ListIterator;

/**
 * The interface to the low-level browser, this class serves as a 'domain' for a
 * module, loading all of its classes in a separate, isolated class loader. This
 * allows us to run multiple modules, both in succession and simultaneously.
 */
public abstract class ModuleSpace implements ShellJavaScriptHost {

  private static ThreadLocal<Throwable> sCaughtJavaExceptionObject = new ThreadLocal<Throwable>();

  private static ThreadLocal<Throwable> sThrownJavaExceptionObject = new ThreadLocal<Throwable>();

  /**
   * Logger is thread local.
   */
  private static ThreadLocal<TreeLogger> threadLocalLogger = new ThreadLocal<TreeLogger>();

  public static void setThrownJavaException(Throwable t) {
    sThrownJavaExceptionObject.set(t);
  }

  /**
   * Create a JavaScriptException object. This must be done reflectively, since
   * this class will have been loaded from a ClassLoader other than the
   * session's thread.
   */
  protected static RuntimeException createJavaScriptException(ClassLoader cl,
      Object exception) {
    Exception caught;
    try {
      Class<?> javaScriptExceptionClass = Class.forName(
          "com.google.gwt.core.client.JavaScriptException", true, cl);
      Constructor<?> ctor = javaScriptExceptionClass.getDeclaredConstructor(
          Object.class);
      return (RuntimeException) ctor.newInstance(new Object[] {exception});
    } catch (InstantiationException e) {
      caught = e;
    } catch (IllegalAccessException e) {
      caught = e;
    } catch (SecurityException e) {
      caught = e;
    } catch (ClassNotFoundException e) {
      caught = e;
    } catch (NoSuchMethodException e) {
      caught = e;
    } catch (IllegalArgumentException e) {
      caught = e;
    } catch (InvocationTargetException e) {
      caught = e;
    }
    throw new RuntimeException("Error creating JavaScriptException", caught);
  }

  protected static TreeLogger getLogger() {
    return threadLocalLogger.get();
  }

  /**
   * Get the JavaScriptObject wrapped by a JavaScriptException. We have to do
   * this reflectively, since the JavaScriptException object is from an
   * arbitrary classloader. If the object is not a JavaScriptException, or is
   * not from the given ClassLoader, we'll return null.
   */
  static Object getJavaScriptExceptionException(ClassLoader cl,
      Object javaScriptException) {
    if (javaScriptException.getClass().getClassLoader() != cl) {
      return null;
    }

    Exception caught;
    try {
      Class<?> javaScriptExceptionClass = Class.forName(
          "com.google.gwt.core.client.JavaScriptException", true, cl);

      if (!javaScriptExceptionClass.isInstance(javaScriptException)) {
        // Not a JavaScriptException
        return null;
      }
      Method getException = javaScriptExceptionClass.getMethod("getException");
      return getException.invoke(javaScriptException);
    } catch (NoSuchMethodException e) {
      caught = e;
    } catch (ClassNotFoundException e) {
      caught = e;
    } catch (IllegalArgumentException e) {
      caught = e;
    } catch (IllegalAccessException e) {
      caught = e;
    } catch (InvocationTargetException e) {
      caught = e;
    }
    throw new RuntimeException("Error getting exception value", caught);
  }

  protected final ModuleSpaceHost host;

  private final TreeLogger logger;

  private final String moduleName;

  protected ModuleSpace(TreeLogger logger, ModuleSpaceHost host,
      String moduleName) {
    this.host = host;
    this.moduleName = moduleName;
    this.logger = logger;
    threadLocalLogger.set(host.getLogger());
  }

  public void dispose() {
    // Clear our class loader.
    getIsolatedClassLoader().clear();
  }

  public void exceptionCaught(Object exception) {
    Throwable caught;
    Throwable thrown = sThrownJavaExceptionObject.get();
    if (thrown != null && isExceptionSame(thrown, exception)) {
      // The caught exception was thrown by us.
      caught = thrown;
      sThrownJavaExceptionObject.set(null);
    } else if (exception instanceof Throwable) {
      caught = (Throwable) exception;
    } else {
      caught = createJavaScriptException(getIsolatedClassLoader(), exception);
      // Remove excess stack frames from the new exception.
      caught.fillInStackTrace();
      StackTraceElement[] trace = caught.getStackTrace();
      assert trace.length > 1;
      assert trace[1].getClassName().equals(JavaScriptHost.class.getName());
      assert trace[1].getMethodName().equals("exceptionCaught");
      StackTraceElement[] newTrace = new StackTraceElement[trace.length - 1];
      System.arraycopy(trace, 1, newTrace, 0, newTrace.length);
      caught.setStackTrace(newTrace);
    }
    sCaughtJavaExceptionObject.set(caught);
  }

  /**
   * Get the module name.
   * 
   * @return the module name
   */
  public String getModuleName() {
    return moduleName;
  }

  public boolean invokeNativeBoolean(String name, Object jthis,
      Class<?>[] types, Object[] args) throws Throwable {
    JsValue result = invokeNative(name, jthis, types, args);
    String msgPrefix = composeResultErrorMsgPrefix(name, "a boolean");
    Boolean value = JsValueGlue.get(result, getIsolatedClassLoader(),
        boolean.class, msgPrefix);
    if (value == null) {
      throw new HostedModeException(msgPrefix
          + ": return value null received, expected a boolean");
    }
    return value.booleanValue();
  }

  public byte invokeNativeByte(String name, Object jthis, Class<?>[] types,
      Object[] args) throws Throwable {
    JsValue result = invokeNative(name, jthis, types, args);
    String msgPrefix = composeResultErrorMsgPrefix(name, "a byte");
    Byte value = JsValueGlue.get(result, null, Byte.TYPE, msgPrefix);
    if (value == null) {
      throw new HostedModeException(msgPrefix
          + ": return value null received, expected a byte");
    }
    return value.byteValue();
  }

  public char invokeNativeChar(String name, Object jthis, Class<?>[] types,
      Object[] args) throws Throwable {
    JsValue result = invokeNative(name, jthis, types, args);
    String msgPrefix = composeResultErrorMsgPrefix(name, "a char");
    Character value = JsValueGlue.get(result, null, Character.TYPE, msgPrefix);
    if (value == null) {
      throw new HostedModeException(msgPrefix
          + ": return value null received, expected a char");
    }
    return value.charValue();
  }

  public double invokeNativeDouble(String name, Object jthis, Class<?>[] types,
      Object[] args) throws Throwable {
    JsValue result = invokeNative(name, jthis, types, args);
    String msgPrefix = composeResultErrorMsgPrefix(name, "a double");
    Double value = JsValueGlue.get(result, null, Double.TYPE, msgPrefix);
    if (value == null) {
      throw new HostedModeException(msgPrefix
          + ": return value null received, expected a double");
    }
    return value.doubleValue();
  }

  public float invokeNativeFloat(String name, Object jthis, Class<?>[] types,
      Object[] args) throws Throwable {
    JsValue result = invokeNative(name, jthis, types, args);
    String msgPrefix = composeResultErrorMsgPrefix(name, "a float");
    Float value = JsValueGlue.get(result, null, Float.TYPE, msgPrefix);
    if (value == null) {
      throw new HostedModeException(msgPrefix
          + ": return value null received, expected a float");
    }
    return value.floatValue();
  }

  public int invokeNativeInt(String name, Object jthis, Class<?>[] types,
      Object[] args) throws Throwable {
    JsValue result = invokeNative(name, jthis, types, args);
    String msgPrefix = composeResultErrorMsgPrefix(name, "an int");
    Integer value = JsValueGlue.get(result, null, Integer.TYPE, msgPrefix);
    if (value == null) {
      throw new HostedModeException(msgPrefix
          + ": return value null received, expected an int");
    }
    return value.intValue();
  }

  public long invokeNativeLong(String name, Object jthis, Class<?>[] types,
      Object[] args) throws Throwable {
    JsValue result = invokeNative(name, jthis, types, args);
    String msgPrefix = composeResultErrorMsgPrefix(name, "a long");
    Long value = JsValueGlue.get(result, null, Long.TYPE, msgPrefix);
    if (value == null) {
      throw new HostedModeException(msgPrefix
          + ": return value null received, expected a long");
    }
    return value.longValue();
  }

  public Object invokeNativeObject(String name, Object jthis, Class<?>[] types,
      Object[] args) throws Throwable {
    JsValue result = invokeNative(name, jthis, types, args);
    String msgPrefix = composeResultErrorMsgPrefix(name, "a Java object");
    return JsValueGlue.get(result, getIsolatedClassLoader(), Object.class,
        msgPrefix);
  }

  public short invokeNativeShort(String name, Object jthis, Class<?>[] types,
      Object[] args) throws Throwable {
    JsValue result = invokeNative(name, jthis, types, args);
    String msgPrefix = composeResultErrorMsgPrefix(name, "a short");
    Short value = JsValueGlue.get(result, null, Short.TYPE, msgPrefix);
    if (value == null) {
      throw new HostedModeException(msgPrefix
          + ": return value null received, expected a short");
    }
    return value.shortValue();
  }

  public void invokeNativeVoid(String name, Object jthis, Class<?>[] types,
      Object[] args) throws Throwable {
    JsValue result = invokeNative(name, jthis, types, args);
    if (!result.isUndefined()) {
      logger.log(
          TreeLogger.WARN,
          "JSNI method '"
              + name
              + "' returned a value of type "
              + result.getTypeString()
              + " but was declared void; it should not have returned a value at all",
          null);
    }
  }

  /**
   * Allows client-side code to log to the tree logger.
   */
  public void log(String message, Throwable e) {
    TreeLogger.Type type = TreeLogger.INFO;
    if (e != null) {
      type = TreeLogger.ERROR;
    }
    // Log at the top level for visibility.
    TreeLogger t = getLogger();
    if (t != null) {
      getLogger().log(type, message, e);
    }
  }

  /**
   * Runs the module's user startup code.
   */
  public final void onLoad(TreeLogger logger) throws UnableToCompleteException {
    Event moduleSpaceLoadEvent = SpeedTracerLogger.start(DevModeEventType.MODULE_SPACE_LOAD);

    // Tell the host we're ready for business.
    //
    host.onModuleReady(this);

    // Make sure we can resolve JSNI references to static Java names.
    //
    try {
      createStaticDispatcher(logger);
      Object staticDispatch = getStaticDispatcher();
      invokeNativeVoid("__defineStatic", null, new Class[] {Object.class},
          new Object[] {staticDispatch});
    } catch (Throwable e) {
      logger.log(TreeLogger.ERROR, "Unable to initialize static dispatcher", e);
      throw new UnableToCompleteException();
    }

    // Actually run user code.
    //
    String entryPointTypeName = null;
    try {
      // Set up GWT-entry code
      Class<?> implClass = loadClassFromSourceName("com.google.gwt.core.client.impl.Impl");
      Method registerEntry = implClass.getDeclaredMethod("registerEntry");
      registerEntry.setAccessible(true);
      registerEntry.invoke(null);

      Method enter = implClass.getDeclaredMethod("enter");
      enter.setAccessible(true);
      enter.invoke(null);

      String[] entryPoints = host.getEntryPointTypeNames();
      if (entryPoints.length > 0) {
        try {
          for (int i = 0; i < entryPoints.length; i++) {
            entryPointTypeName = entryPoints[i];
            Method onModuleLoad = null;
            Object module;

            // Try to initialize EntryPoint, else throw up glass panel
            try {
              Class<?> clazz = loadClassFromSourceName(entryPointTypeName);
              try {
                onModuleLoad = clazz.getMethod("onModuleLoad");
                if (!Modifier.isStatic(onModuleLoad.getModifiers())) {
                  // it's non-static, so we need to rebind the class
                  onModuleLoad = null;
                }
              } catch (NoSuchMethodException e) {
                // okay, try rebinding it; maybe the rebind result will have one
              }
              module = null;
              if (onModuleLoad == null) {
                module = rebindAndCreate(entryPointTypeName);
                onModuleLoad = module.getClass().getMethod("onModuleLoad");
                // Record the rebound name of the class for stats (below).
                entryPointTypeName = module.getClass().getName().replace(
                    '$', '.');
              }
            } catch (Throwable e) {
              displayErrorGlassPanel(
                  "EntryPoint initialization exception", entryPointTypeName, e);
              throw e;
            }

            // Try to invoke onModuleLoad, else throw up glass panel
            try {
              onModuleLoad.setAccessible(true);
              invokeNativeVoid("fireOnModuleLoadStart", null,
                  new Class[]{String.class}, new Object[]{entryPointTypeName});

              Event onModuleLoadEvent = SpeedTracerLogger.start(
                  DevModeEventType.ON_MODULE_LOAD);
              try {
                onModuleLoad.invoke(module);
              } finally {
                onModuleLoadEvent.end();
              }
            } catch (Throwable e) {
              displayErrorGlassPanel(
                  "onModuleLoad() threw an exception", entryPointTypeName, e);
              throw e;
            }
          }
        } finally {
          Method exit = implClass.getDeclaredMethod("exit", boolean.class);
          exit.setAccessible(true);
          exit.invoke(null, true);
        }
      } else {
        logger.log(
            TreeLogger.WARN,
            "The module has no entry points defined, so onModuleLoad() will never be called",
            null);
      }
    } catch (Throwable e) {
      Throwable caught = e;

      if (e instanceof InvocationTargetException) {
        caught = ((InvocationTargetException) e).getTargetException();
      }

      if (caught instanceof ExceptionInInitializerError) {
        caught = ((ExceptionInInitializerError) caught).getException();
      }

      String unableToLoadMessage = "Unable to load module entry point class "
          + entryPointTypeName;
      if (caught != null) {
        unableToLoadMessage += " (see associated exception for details)";
      }
      logger.log(TreeLogger.ERROR, unableToLoadMessage, caught);
      throw new UnableToCompleteException();
    } finally {
      moduleSpaceLoadEvent.end();
    }
  }

  @SuppressWarnings("unchecked")
  public <T> T rebindAndCreate(String requestedClassName)
      throws UnableToCompleteException {
    assert Name.isBinaryName(requestedClassName);
    Throwable caught = null;
    String msg = null;
    String resultName = null;
    Class<?> resolvedClass = null;

    Event moduleSpaceRebindAndCreate =
        SpeedTracerLogger.start(DevModeEventType.MODULE_SPACE_REBIND_AND_CREATE);
    try {
      // Rebind operates on source-level names.
      //
      String sourceName = BinaryName.toSourceName(requestedClassName);
      resultName = rebind(sourceName);
      moduleSpaceRebindAndCreate.addData(
          "Requested Class", requestedClassName, "Result Name", resultName);
      resolvedClass = loadClassFromSourceName(resultName);
      if (Modifier.isAbstract(resolvedClass.getModifiers())) {
        msg = "Deferred binding result type '" + resultName
            + "' should not be abstract";
      } else {
        Constructor<?> ctor = resolvedClass.getDeclaredConstructor();
        ctor.setAccessible(true);
        return (T) ctor.newInstance();
      }
    } catch (ClassNotFoundException e) {
      msg = "Could not load deferred binding result type '" + resultName + "'";
      caught = e;
    } catch (InstantiationException e) {
      caught = e;
    } catch (IllegalAccessException e) {
      caught = e;
    } catch (ExceptionInInitializerError e) {
      caught = e.getException();
    } catch (NoSuchMethodException e) { 
      // If it is a nested class and not declared as static, 
      // then it's not accessible from outside.
      //
      if (resolvedClass.getEnclosingClass() != null 
          && !Modifier.isStatic(resolvedClass.getModifiers())) {
        msg = "Rebind result '" + resultName
        + " is a non-static inner class";
      } else {
        msg = "Rebind result '" + resultName
        + "' has no default (zero argument) constructors.";
      }
      caught = e;
    } catch (InvocationTargetException e) {
      caught = e.getTargetException();
    } finally {
      moduleSpaceRebindAndCreate.end();
    }

    // Always log here because sometimes this method gets called from static
    // initializers and other unusual places, which can obscure the problem.
    //
    if (msg == null) {
      msg = "Failed to create an instance of '" + requestedClassName
          + "' via deferred binding ";
    }
    host.getLogger().log(TreeLogger.ERROR, msg, caught);
    throw new UnableToCompleteException();
  }

  protected String createNativeMethodInjector(String jsniSignature,
      String[] paramNames, String js) {
    String newScript = "window[\"" + jsniSignature + "\"] = function(";

    for (int i = 0; i < paramNames.length; ++i) {
      if (i > 0) {
        newScript += ", ";
      }

      newScript += paramNames[i];
    }

    newScript += ") { " + js + " };\n";
    return newScript;
  }

  /**
   * Create the __defineStatic method.
   * 
   * @param logger
   */
  protected abstract void createStaticDispatcher(TreeLogger logger);

  /**
   * Invokes a native JavaScript function.
   * 
   * @param name the name of the function to invoke
   * @param jthis the function's 'this' context
   * @param types the type of each argument
   * @param args the arguments to be passed
   * @return the return value as a Variant.
   */
  protected abstract JsValue doInvoke(String name, Object jthis,
      Class<?>[] types, Object[] args) throws Throwable;

  protected CompilingClassLoader getIsolatedClassLoader() {
    return host.getClassLoader();
  }

  /**
   * Injects the magic needed to resolve JSNI references from module-space.
   */
  protected abstract Object getStaticDispatcher();

  /**
   * Invokes a native JavaScript function.
   * 
   * @param name the name of the function to invoke
   * @param jthis the function's 'this' context
   * @param types the type of each argument
   * @param args the arguments to be passed
   * @return the return value as a Variant.
   */
  protected final JsValue invokeNative(String name, Object jthis,
      Class<?>[] types, Object[] args) throws Throwable {
    JsValue result = doInvoke(name, jthis, types, args);
    // Is an exception active?
    Throwable thrown = sCaughtJavaExceptionObject.get();
    if (thrown == null) {
      return result;
    }
    sCaughtJavaExceptionObject.set(null);

    scrubStackTrace(thrown);
    throw thrown;
  }

  /**
   * @param original the thrown exception
   * @param exception the caught exception
   */
  protected boolean isExceptionSame(Throwable original, Object exception) {
    // For most platforms, the null exception means we threw it.
    // IE overrides this.
    return exception == null;
  }

  protected String rebind(String sourceName) throws UnableToCompleteException {
    try {
      String result = host.rebind(logger, sourceName);
      if (result != null) {
        return result;
      } else {
        return sourceName;
      }
    } catch (UnableToCompleteException e) {
      String msg = "Deferred binding failed for '" + sourceName
          + "'; expect subsequent failures";
      host.getLogger().log(TreeLogger.ERROR, msg);
      throw new UnableToCompleteException();
    }
  }

  private String composeResultErrorMsgPrefix(String name, String typePhrase) {
    return "Something other than " + typePhrase
        + " was returned from JSNI method '" + name + "'";
  }

  private void displayErrorGlassPanel(
      String summary, String entryPointTypeName, Throwable e) throws Throwable {
    StringWriter writer = new StringWriter();
    e.printStackTrace(new PrintWriter(writer));
    String stackTrace = writer.toString().replaceFirst(
        // (?ms) for regex pattern modifiers MULTILINE and DOTALL
        "(?ms)(Caused by:.+)", "<b>$1</b>");
    String details = "<p>Exception while loading module <b>"
        + entryPointTypeName + "</b>. See Development Mode for details.</p>"
        + "<div style='overflow:visisble;white-space:pre;'>" + stackTrace
        + "</div>";

    invokeNativeVoid("__gwt_displayGlassMessage", null,
        new Class[]{String.class, String.class},
        new Object[]{summary, details});
  }

  private boolean isUserFrame(StackTraceElement element) {
    try {
      CompilingClassLoader cl = getIsolatedClassLoader();
      String className = element.getClassName();
      Class<?> clazz = Class.forName(className, false, cl);
      if (clazz.getClassLoader() == cl) {
        // Lives in user classLoader.
        return true;
      }
      // At this point, it must be a JRE class to qualify.
      if (clazz.getClassLoader() != null || !className.startsWith("java.")) {
        return false;
      }
      if (className.startsWith("java.lang.reflect.")) {
        return false;
      }
      return true;
    } catch (ClassNotFoundException e) {
      return false;
    }
  }

  /**
   * Handles loading a class that might be nested given a source type name.
   */
  private Class<?> loadClassFromSourceName(String sourceName)
      throws ClassNotFoundException {
    Event moduleSpaceClassLoad = SpeedTracerLogger.start(
        DevModeEventType.MODULE_SPACE_CLASS_LOAD, "Source Name", sourceName);
    try {
      String toTry = sourceName;
      while (true) {
        try {
          return Class.forName(toTry, true, getIsolatedClassLoader());
        } catch (ClassNotFoundException e) {
          // Assume that the last '.' should be '$' and try again.
          //
          int i = toTry.lastIndexOf('.');
          if (i == -1) {
            throw e;
          }

          toTry = toTry.substring(0, i) + "$" + toTry.substring(i + 1);
        }
      }
    } finally {
      moduleSpaceClassLoad.end();
    }
  }

  /**
   * Clean up the stack trace by removing our hosting frames. But don't do this
   * if our own frames are at the top of the stack, because we may be the real
   * cause of the exception.
   */
  private void scrubStackTrace(Throwable thrown) {
    List<StackTraceElement> trace = new ArrayList<StackTraceElement>(
        Arrays.asList(thrown.getStackTrace()));
    boolean seenUserFrame = false;
    for (ListIterator<StackTraceElement> it = trace.listIterator(); it.hasNext();) {
      StackTraceElement element = it.next();
      if (!isUserFrame(element)) {
        if (seenUserFrame) {
          it.remove();
        }
        continue;
      }
      seenUserFrame = true;

      // Remove a JavaScriptHost.invokeNative*() frame.
      if (element.getClassName().equals(JavaScriptHost.class.getName())) {
        if (element.getMethodName().equals("exceptionCaught")) {
          it.remove();
        } else if (element.getMethodName().startsWith("invokeNative")) {
          it.remove();
          // Also try to convert the next frame to a true native.
          if (it.hasNext()) {
            StackTraceElement next = it.next();
            if (next.getLineNumber() == -1) {
              next = new StackTraceElement(next.getClassName(),
                  next.getMethodName(), next.getFileName(), -2);
              it.set(next);
            }
          }
        }
      }
    }
    thrown.setStackTrace(trace.toArray(new StackTraceElement[trace.size()]));
  }
}
