/*
 * 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.core.client;

/**
 * An opaque handle to a native JavaScript object. A
 * <code>JavaScriptObject</code> cannot be created directly.
 * <code>JavaScriptObject</code> should be declared as the return type of a
 * JSNI method that returns native (non-Java) objects. A
 * <code>JavaScriptObject</code> passed back into JSNI from Java becomes the
 * original object, and can be accessed in JavaScript as expected.
 */
public class JavaScriptObject {

  /**
   * Returns a new array.
   */
  public static native JavaScriptObject createArray() /*-{
    return [];
  }-*/;

  /**
   * Returns a new array with a given size.
   *
   * <p>Consider using this method in performance critical code instead of using
   * {@link #createArray()}, since this gives more hints to the underlying
   * JavaScript VM for optimizations.
   */
  public static native JavaScriptObject createArray(int size) /*-{
    return new Array(size);
  }-*/;

  /**
   * Returns an empty function.
   */
  public static native JavaScriptObject createFunction() /*-{
    return function() {
    };
  }-*/;

  /**
   * Returns a new object.
   */
  public static native JavaScriptObject createObject() /*-{
    return {};
  }-*/;

  /**
   * Helper for {@link #toString()}, for lighter "more production" code.
   */
  private static native String toStringSimple(JavaScriptObject obj) /*-{
    return obj.toString ? obj.toString() : '[JavaScriptObject]';
  }-*/;

  /**
   * Helper for {@link #toString()}, when Development Mode or assertions are on.
   */
  private static native String toStringVerbose(JavaScriptObject obj) /*-{
    var defined = function(m) { return typeof m != 'undefined'; };
    var strip = function(s) { return s.replace(/\r\n/g, ""); };
    // Output nodes that have outerHTML
    if (defined(obj.outerHTML))
      return strip(obj.outerHTML);
    // Output nodes that have innerHTML
    if (defined(obj.innerHTML) && obj.cloneNode) {
      $doc.createElement('div').appendChild(obj.cloneNode(true)).innerHTML;
    }
    // Output text nodes
    if (defined(obj.nodeType) && obj.nodeType == 3) {
      return "'" +
        obj.data.replace(/ /g, "\u25ab").replace(/\u00A0/, "\u25aa") +
        "'";
    }
    // Output IE's TextRange (this code specific to IE7)
    if (typeof defined(obj.htmlText) && obj.collapse) {
      var html = obj.htmlText;
      if (html) {
        return 'IETextRange [' + strip(html) + ']';
      } else {
        // NOTE: using pasteHTML to place a | where the range is collapsed
        // if *very* useful when debugging. It also, however, in certain very
        // subtle circumstances change the range being toStringed! If you
        // see different behaviour in debug vs. release builds (or if logging
        // ranges changes the behaviour, comment out the 4 of the 6 lines
        // below containing dup.
        var dup = obj.duplicate();
        dup.pasteHTML('|');
        var out = 'IETextRange ' + strip(obj.parentElement().outerHTML);
        dup.moveStart('character', -1);
        dup.pasteHTML('');
        return out;
      }
    }
    return obj.toString ? obj.toString() : '[JavaScriptObject]';
  }-*/;

  /**
   * Not directly instantiable. All subclasses must also define a protected,
   * empty, no-arg constructor.
   */
  protected JavaScriptObject() {
  }

  /**
   * A helper method to enable cross-casting from any {@link JavaScriptObject}
   * type to any other {@link JavaScriptObject} type.
   *
   * @param <T> the target type
   * @return this object as a different type
   */
  @SuppressWarnings("unchecked")
  public final <T extends JavaScriptObject> T cast() {
    return (T) this;
  }

  /**
   * Calls a native JS <code>equals</code> method if any, otherwise
   * returns <code>true</code> if the objects are JavaScript identical
   * (triple-equals).
   */
  @Override
  public final boolean equals(Object other) {
    if (!GWT.isClient()) {
      return super.equals(other);
    }
    return hasEquals(this) ? callEquals(this, other) : super.equals(other);
  }

  /**
   * Calls a native JS <code>hashCode</code> method if any, otherwise
   * uses a monotonically increasing counter to assign a hash code to the
   * underlying JavaScript object. Do not call this method on non-modifiable
   * JavaScript objects.
   *
   * @return the hash code of the object
   */
  @Override
  public final int hashCode() {
    if (!GWT.isClient()) {
      return super.hashCode();
    }
    return hasHashCode(this) ? callHashCode(this) : super.hashCode();
  };

  /**
   * Call the toSource() on the JSO.
   */
  public native String toSource() /*-{
    this.toSource ? this.toSource() : "NO SOURCE";
  }-*/;

  /**
   * Makes a best-effort attempt to get a useful debugging string describing the
   * given JavaScriptObject. In Production Mode with assertions disabled, this
   * will either call and return the JSO's toString() if one exists, or just
   * return "[JavaScriptObject]". In Development Mode, or with assertions
   * enabled, some stronger effort is made to represent other types of JSOs,
   * including inspecting for document nodes' outerHTML and innerHTML, etc.
   */
  @Override
  public final String toString() {
    return JavaScriptObject.class.desiredAssertionStatus() ?
        toStringVerbose(this) : toStringSimple(this);
  }

  private static native boolean hasEquals(Object object) /*-{
    return !!object && !!object.equals;
  }-*/;

  private static native boolean hasHashCode(Object object) /*-{
    return !!object && !!object.hashCode;
  }-*/;

  private static native boolean callEquals(Object thisObject, Object thatObject) /*-{
    return thisObject.equals(thatObject);
  }-*/;

  private static native int callHashCode(Object object) /*-{
    return object.hashCode();
  }-*/;
}
