/*
 * 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.util.TypeInfo;

import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;

/**
 * Glue layer that performs GWT-specific operations on JsValues. Used to isolate
 * HostedModeExceptions/etc from JsValue code
 */
public final class JsValueGlue {
  public static final String HOSTED_MODE_REFERENCE = "hostedModeReference";
  public static final String JSO_CLASS = "com.google.gwt.core.client.JavaScriptObject";
  public static final String JSO_IMPL_CLASS = "com.google.gwt.core.client.JavaScriptObject$";

  /**
   * Create a JavaScriptObject instance referring to this JavaScript object.
   * 
   * @param classLoader the classLoader to create from
   * @return the constructed JavaScriptObject
   */
  public static Object createJavaScriptObject(JsValue value,
      CompilingClassLoader classLoader) {
    Throwable caught;
    try {
      // See if there's already a wrapper object (assures identity comparison).
      Object jso = classLoader.getCachedJso(value.getJavaScriptObjectPointer());
      if (jso != null) {
        return jso;
      }

      // Instantiate the JSO class.
      Class<?> jsoType = Class.forName(JSO_IMPL_CLASS, true, classLoader);
      Constructor<?> ctor = jsoType.getDeclaredConstructor();
      ctor.setAccessible(true);
      jso = ctor.newInstance();

      // Set the reference field to this JsValue using reflection.
      Field referenceField = jsoType.getField(HOSTED_MODE_REFERENCE);
      referenceField.set(jso, value);

      classLoader.putCachedJso(value.getJavaScriptObjectPointer(), jso);
      return jso;
    } catch (InstantiationException e) {
      caught = e;
    } catch (IllegalAccessException e) {
      caught = e;
    } catch (SecurityException e) {
      caught = e;
    } catch (NoSuchMethodException e) {
      caught = e;
    } catch (IllegalArgumentException e) {
      caught = e;
    } catch (InvocationTargetException e) {
      caught = e;
    } catch (ClassNotFoundException e) {
      caught = e;
    } catch (NoSuchFieldException e) {
      caught = e;
    }
    throw new RuntimeException("Error creating JavaScript object", caught);
  }

  /**
   * Return an object containing the value JavaScript object as a specified
   * type.
   * 
   * @param value the JavaScript value
   * @param type expected type of the returned object
   * @param msgPrefix a prefix for error/warning messages
   * @return the object reference
   * @throws com.google.gwt.dev.shell.HostedModeException if the JavaScript
   *     object is not assignable to the supplied type.
   */
  @SuppressWarnings("unchecked")
  public static <T> T get(JsValue value, CompilingClassLoader cl,
      Class<T> type, String msgPrefix) {

    if (type.isPrimitive()) {
      if (type == Boolean.TYPE) {
        if (!value.isBoolean()) {
          throw new HostedModeException(msgPrefix + ": JS value of type "
              + value.getTypeString() + ", expected boolean");
        }
        return (T) Boolean.valueOf(value.getBoolean());
      } else if (type == Byte.TYPE) {
        return (T) Byte.valueOf((byte) getIntRange(value, Byte.MIN_VALUE,
            Byte.MAX_VALUE, "byte", msgPrefix));
      } else if (type == Character.TYPE) {
        return (T) Character.valueOf((char) getIntRange(value,
            Character.MIN_VALUE, Character.MAX_VALUE, "char", msgPrefix));
      } else if (type == Double.TYPE) {
        if (!value.isNumber()) {
          throw new HostedModeException(msgPrefix + ": JS value of type "
              + value.getTypeString() + ", expected double");
        }
        return (T) Double.valueOf(value.getNumber());
      } else if (type == Float.TYPE) {
        if (!value.isNumber()) {
          throw new HostedModeException(msgPrefix + ": JS value of type "
              + value.getTypeString() + ", expected float");
        }
        double doubleVal = value.getNumber();

        // Check for small changes near MIN_VALUE and replace with the
        // actual end point value, in case it is being used as a sentinel
        // value. This test works by the subtraction result rounding off to
        // zero if the delta is not representable in a float.
        // TODO(jat): add similar test for MAX_VALUE if we have a JS
        // platform that alters the value while converting to/from strings.
        if ((float) (doubleVal - Float.MIN_VALUE) == 0.0f) {
          doubleVal = Float.MIN_VALUE;
        }

        float floatVal = (float) doubleVal;
        if (Float.isInfinite(floatVal) && !Double.isInfinite(doubleVal)) {
          // in this case we had overflow from the double value which was
          // outside the range of supported float values, and the cast
          // converted it to infinity. Since this lost data, we treat this
          // as an error in hosted mode.
          throw new HostedModeException(msgPrefix + ": JS value " + doubleVal
              + " out of range for a float");
        }
        return (T) Float.valueOf(floatVal);
      } else if (type == Integer.TYPE) {
        return (T) Integer.valueOf(getIntRange(value, Integer.MIN_VALUE,
            Integer.MAX_VALUE, "int", msgPrefix));
      } else if (type == Long.TYPE) {
        if (!value.isWrappedJavaObject()) {
          throw new HostedModeException(msgPrefix + ": JS value of type "
              + value.getTypeString() + ", expected Java long");
        }
        JavaLong javaLong = (JavaLong) value.getWrappedJavaObject();
        return (T) Long.valueOf(javaLong.longValue());
      } else if (type == Short.TYPE) {
        return (T) Short.valueOf((short) getIntRange(value, Short.MIN_VALUE,
            Short.MAX_VALUE, "short", msgPrefix));
      }
    }

    if (value.isNull() || value.isUndefined()) {
      return null;
    }
    if (value.isWrappedJavaObject()) {
      return type.cast(value.getWrappedJavaObject());
    }
    if (value.isString()) {
      return type.cast(value.getString());
    }
    if (value.isJavaScriptObject()) {
      return type.cast(createJavaScriptObject(value, cl));
    }

    // Just don't know what do to with this.
    /*
     * TODO (amitmanjhi): does throwing a HostedModeException here and catching
     * a RuntimeException in user test
     * com.google.gwt.dev.jjs.test.HostedTest::testObjectReturns() make sense
     */
    throw new IllegalArgumentException(msgPrefix + ": JS value of type "
        + value.getTypeString() + ", expected "
        + TypeInfo.getSourceRepresentation(type));
  }

  /**
   * Set the underlying value.
   * 
   * @param value JsValue to set
   * @param type static type of the object
   * @param obj the object to store in the JS value
   */
  public static void set(JsValue value, CompilingClassLoader cl, Class<?> type,
      Object obj) {
    if (type.isPrimitive()) {
      if (type == Boolean.TYPE) {
        value.setBoolean(((Boolean) obj).booleanValue());
      } else if (type == Byte.TYPE) {
        value.setInt(((Byte) obj).byteValue());
      } else if (type == Character.TYPE) {
        value.setInt(((Character) obj).charValue());
      } else if (type == Double.TYPE) {
        value.setDouble(((Double) obj).doubleValue());
      } else if (type == Float.TYPE) {
        value.setDouble(((Float) obj).floatValue());
      } else if (type == Integer.TYPE) {
        value.setInt(((Integer) obj).intValue());
      } else if (type == Long.TYPE) {
        long longVal = ((Long) obj).longValue();
        value.setWrappedJavaObject(cl, new JavaLong(longVal));
      } else if (type == Short.TYPE) {
        value.setInt(((Short) obj).shortValue());
      } else if (type == Void.TYPE) {
        value.setUndefined();
      } else {
        throw new HostedModeException("Cannot marshal primitive type " + type);
      }
    } else if (obj == null) {
      value.setNull();
    } else {
      // not a boxed primitive
      try {
        Class<?> jsoType = Class.forName(JSO_IMPL_CLASS, false, cl);
        if (jsoType == obj.getClass()) {
          JsValue jsObject = getUnderlyingObject(obj);
          value.setValue(jsObject);
          return;
        }
      } catch (ClassNotFoundException e) {
        // Ignore the exception, if we can't find the class then obviously we
        // don't have to worry about o being one
      }

      // Fall through case: Object.
      if (!type.isInstance(obj)) {
        throw new HostedModeException("object is of type "
            + obj.getClass().getName() + ", expected " + type.getName());
      }
      if (obj instanceof String) {
        value.setString((String) obj);
      } else {
        value.setWrappedJavaObject(cl, obj);
      }
    }
  }

  private static int getIntRange(JsValue value, int low, int high,
      String typeName, String msgPrefix) {
    int intVal;
    if (value.isInt()) {
      intVal = value.getInt();
      if (intVal < low || intVal > high) {
        throw new HostedModeException(msgPrefix + ": JS int value " + intVal
            + " out of range for a " + typeName);
      }
    } else if (value.isNumber()) {
      double doubleVal = value.getNumber();
      if (doubleVal < low || doubleVal > high) {
        throw new HostedModeException(msgPrefix + ": JS double value "
            + doubleVal + " out of range for a " + typeName);
      }
      intVal = (int) doubleVal;
      if (intVal != doubleVal) {
        ModuleSpace.getLogger().log(TreeLogger.WARN,
            msgPrefix + ": Rounding double (" + doubleVal + ") to int for "
            + typeName, null);
      }
    } else {
      throw new HostedModeException(msgPrefix + ": JS value of type "
          + value.getTypeString() + ", expected " + typeName);
    }
    return intVal;
  }

  /**
   * Returns the underlying JsValue from a JavaScriptObject instance.
   * 
   * The tricky part is that it is in a different ClassLoader so therefore can't
   * be specified directly. The type is specified as Object, and reflection is
   * used to retrieve the reference field.
   * 
   * @param jso the instance of JavaScriptObject to retrieve the JsValue from.
   * @return the JsValue representing the JavaScript object
   */
  private static JsValue getUnderlyingObject(Object jso) {
    Throwable caught;
    try {
      Field referenceField = jso.getClass().getField(HOSTED_MODE_REFERENCE);
      referenceField.setAccessible(true);
      return (JsValue) referenceField.get(jso);
    } catch (IllegalAccessException e) {
      caught = e;
    } catch (SecurityException e) {
      caught = e;
    } catch (NoSuchFieldException e) {
      caught = e;
    }
    throw new RuntimeException("Error reading " + HOSTED_MODE_REFERENCE, caught);
  }

  private JsValueGlue() {
  }
}
