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

import com.google.gwt.core.client.JavaScriptObject;
import com.google.gwt.core.client.Scheduler;
import com.google.gwt.core.client.Scheduler.ScheduledCommand;
import com.google.gwt.dom.client.Style.Position;
import com.google.gwt.dom.client.Style.Unit;
import com.google.gwt.junit.DoNotRunWith;
import com.google.gwt.junit.Platform;
import com.google.gwt.junit.client.GWTTestCase;

/**
 * Element tests (many stolen from DOMTest).
 */
public class ElementTest extends GWTTestCase {

  @Override
  public String getModuleName() {
    return "com.google.gwt.dom.DOMTest";
  }

  public void testAddRemoveReplaceClassName() {
    DivElement div = Document.get().createDivElement();

    div.setClassName("foo");
    assertEquals("foo", div.getClassName());

    assertTrue(div.addClassName("bar"));
    assertEquals("foo bar", div.getClassName());

    assertTrue(div.addClassName("baz"));
    assertEquals("foo bar baz", div.getClassName());

    assertFalse(div.addClassName("baz"));
    assertEquals("foo bar baz", div.getClassName());

    div.replaceClassName("bar", "tintin");
    assertTrue(div.getClassName().contains("tintin"));
    assertFalse(div.getClassName().contains("bar"));

    assertTrue(div.removeClassName("tintin"));
    assertEquals("foo baz", div.getClassName());

    assertFalse(div.removeClassName("bar"));
    assertEquals("foo baz", div.getClassName());

    assertTrue(div.removeClassName("baz"));
    assertEquals("foo", div.getClassName());

    assertTrue(div.removeClassName("foo"));
    assertEquals("", div.getClassName());
  }

  public void testIndexOfName() {
    assertEquals(-1, Element.indexOfName("", "foo"));

    assertEquals(-1, Element.indexOfName("foo", "fo"));
    assertEquals(-1, Element.indexOfName("foo", "fool"));

    assertEquals(-1, Element.indexOfName("bar fool", "foo"));
    assertEquals(-1, Element.indexOfName("bar fool baz", "foo"));

    assertEquals(0, Element.indexOfName("foo", "foo"));
    assertEquals(0, Element.indexOfName("foo bar", "foo"));
    assertEquals(4, Element.indexOfName("bar foo", "foo"));
    assertEquals(4, Element.indexOfName("bar foo baz", "foo"));
  }

  /**
   * firstChildElement, nextSiblingElement, previousSiblingElement.
   */
  public void testChildElements() {
    Document doc = Document.get();
    DivElement parent = doc.createDivElement();
    DivElement div0 = doc.createDivElement();
    DivElement div1 = doc.createDivElement();

    parent.appendChild(doc.createTextNode("foo"));
    parent.appendChild(div0);
    parent.appendChild(doc.createTextNode("bar"));
    parent.appendChild(div1);

    Element fc = parent.getFirstChildElement();
    Element ns = fc.getNextSiblingElement();
    Element ps = ns.getPreviousSiblingElement();
    assertEquals(div0, fc);
    assertEquals(div1, ns);
    assertEquals(div0, ps);

    assertNull(fc.getPreviousSiblingElement());
    assertNull(ns.getNextSiblingElement());
  }

  /**
   * Test round-trip of the 'disabled' property.
   */
  public void testDisabled() {
    ButtonElement button = Document.get().createPushButtonElement();
    assertFalse(button.isDisabled());
    button.setDisabled(true);
    assertTrue(button.isDisabled());

    InputElement input = Document.get().createTextInputElement();
    assertFalse(input.isDisabled());
    input.setDisabled(true);
    assertTrue(input.isDisabled());
    
    SelectElement select = Document.get().createSelectElement();
    assertFalse(select.isDisabled());
    select.setDisabled(true);
    assertTrue(select.isDisabled());
    
    OptGroupElement optgroup = Document.get().createOptGroupElement();
    assertFalse(optgroup.isDisabled());
    optgroup.setDisabled(true);
    assertTrue(optgroup.isDisabled());
  }

  /**
   * [get|set|remove]Attribute.
   */
  public void testElementAttribute() {
    DivElement div = Document.get().createDivElement();
    div.setAttribute("class", "testClass");
    String cssClass = div.getAttribute("class");
    assertEquals("testClass", cssClass);
    div.removeAttribute("class");
    cssClass = div.getAttribute("class");
    assertEquals("", cssClass);
  }

  /**
   * Ensure that the return type of an attribute is always a string. IE should
   * not return a numeric attribute based on the element property. See issue
   * 3238.
   */
  public void testElementAttributeNumeric() {
    DivElement div = Document.get().createDivElement();
    Document.get().getBody().appendChild(div);
    div.setInnerText("Hello World");
    div.getAttribute("offsetWidth").length();
    div.getAttribute("offsetWidth").trim().length();
    Document.get().getBody().removeChild(div);
  }

  public void testEmptyClassNameAssertion() {
    DivElement div = Document.get().createDivElement();

    if (getClass().desiredAssertionStatus()) {
      div.setClassName("primary");
      try {
        div.addClassName("");
        fail();
      } catch (AssertionError e) {
        // This *should* throw.
      }

      try {
        div.addClassName(" ");
        fail();
      } catch (AssertionError e) {
        // This *should* throw.
      }

      try {
        div.addClassName(null);
        fail();
      } catch (AssertionError e) {
        // This *should* throw.
      }

      try {
        div.removeClassName("");
        fail();
      } catch (AssertionError e) {
        // This *should* throw.
      }

      try {
        div.removeClassName(" ");
        fail();
      } catch (AssertionError e) {
        // This *should* throw.
      }

      try {
        div.removeClassName(null);
        fail();
      } catch (AssertionError e) {
        // This *should* throw.
      }

      assertEquals("primary", div.getClassName());
    }
  }

  /**
   * getAbsolute[Left|Top|Right|Bottom].
   */
  public void testGetAbsolutePosition() {
    final int border = 8;
    final int margin = 9;
    final int padding = 10;

    final int top = 15;
    final int left = 14;
    final int width = 128;
    final int height = 64;

    final Document doc = Document.get();
    final DivElement elem = doc.createDivElement();
    doc.getBody().appendChild(elem);

    elem.getStyle().setProperty("position", "absolute");
    elem.getStyle().setProperty("border", border + "px solid #000");
    elem.getStyle().setProperty("padding", padding + "px");
    elem.getStyle().setProperty("margin", margin + "px");

    elem.getStyle().setPropertyPx("top", top - doc.getBodyOffsetLeft());
    elem.getStyle().setPropertyPx("left", left - doc.getBodyOffsetTop());
    elem.getStyle().setPropertyPx("width", width);
    elem.getStyle().setPropertyPx("height", height);

    Scheduler.get().scheduleDeferred(new ScheduledCommand() {
      @Override
      public void execute() {
        int absLeft = left + margin;
        int absTop = top + margin;
        int interiorDecorations = (border * 2) + (padding * 2);

        assertEquals(absLeft, elem.getAbsoluteLeft());
        assertEquals(absTop, elem.getAbsoluteTop());

        if (isIE6or7() && !doc.isCSS1Compat()) {
          // In IE/quirk, the interior decorations are considered part of the
          // width/height, so there's no need to account for them here.
          assertEquals(absLeft + width, elem.getAbsoluteRight());
          assertEquals(absTop + height, elem.getAbsoluteBottom());
        } else {
          assertEquals(absLeft + width + interiorDecorations,
              elem.getAbsoluteRight());
          assertEquals(absTop + height + interiorDecorations,
              elem.getAbsoluteBottom());
        }
      }
    });
  }

  /**
   * scroll[Left|Top], getAbsolute[Left|Top].
   */
  @DoNotRunWith(Platform.HtmlUnitLayout)
  public void testGetAbsolutePositionWhenBodyScrolled() {
    Document doc = Document.get();
    BodyElement body = doc.getBody();

    DivElement div = doc.createDivElement();
    body.appendChild(div);

    div.setInnerText("foo");
    div.getStyle().setPosition(Position.ABSOLUTE);
    div.getStyle().setLeft(1000, Unit.PX);
    div.getStyle().setTop(1000, Unit.PX);

    DivElement fixedDiv = doc.createDivElement();
    body.appendChild(fixedDiv);
    fixedDiv.setInnerText("foo");
    fixedDiv.getStyle().setPosition(Position.FIXED);

    // Get the absolute position of the element when the body is unscrolled.
    int absLeft = div.getAbsoluteLeft();
    int absTop = div.getAbsoluteTop();

    // Scroll the body as far down and to the right as possible.
    body.setScrollLeft(10000);
    body.setScrollTop(10000);

    // Make sure the absolute position hasn't changed (this has turned out to
    // be a common error in getAbsoluteLeft/Top() implementations).
    //
    // HACK: Firefox 2 has a bug that causes its getBoxObjectFor() to become
    // off-by-one at times when scrolling. It's not clear how to make this go
    // away, and doesn't seem to be worth the trouble to implement
    // getAbsoluteLeft/Top() yet again for FF2.
    assertTrue(Math.abs(absLeft - div.getAbsoluteLeft()) <= 1);
    assertTrue(Math.abs(absTop - div.getAbsoluteTop()) <= 1);

    // Ensure that the 'position:fixed' div's absolute position includes the
    // body's scroll position.
    //
    // Don't do this on IE6/7, which doesn't support position:fixed.
    if (!isIE6or7()) {
      assertTrue(fixedDiv.getAbsoluteLeft() >= body.getScrollLeft());
      assertTrue(fixedDiv.getAbsoluteTop() >= body.getScrollTop());
    }
  }

  /**
   * getElementsByTagName.
   */
  public void testGetElementsByTagName() {
    DivElement div = Document.get().createDivElement();
    div.setInnerHTML("<span><button>foo</button><span><button>bar</button></span></span>");

    NodeList<Element> nodes = div.getElementsByTagName("button");
    assertEquals(2, nodes.getLength());
    assertEquals("foo", nodes.getItem(0).getInnerText());
    assertEquals("bar", nodes.getItem(1).getInnerText());
  }

  public void testHasAttribute() {
    DivElement div = Document.get().createDivElement();

    // Assert that a raw element doesn't incorrectly report that it has any
    // unspecified built-in attributes (this is a problem on IE<8 if you're not
    // careful in implementing hasAttribute()).
    assertFalse(div.hasAttribute("class"));
    assertFalse(div.hasAttribute("style"));
    assertFalse(div.hasAttribute("title"));
    assertFalse(div.hasAttribute("id"));

    // Ensure that setting HTML-defined attributes is properly reported by
    // hasAttribute().
    div.setId("foo");
    assertTrue(div.hasAttribute("id"));

    // Ensure that setting *custom* attributes is properly reported by
    // hasAttribute().
    assertFalse(div.hasAttribute("foo"));
    div.setAttribute("foo", "bar");
    assertTrue(div.hasAttribute("foo"));

    // Ensure that a null attribute argument always returns null.
    assertFalse(div.hasAttribute(null));
  }

  /**
   * Tests HeadingElement.as() (it has slightly more complex assertion logic
   * than most).
   */
  public void testHeadingElementAs() {
    DivElement placeHolder = Document.get().createDivElement();

    for (int i = 0; i < 6; ++i) {
      placeHolder.setInnerHTML("<H" + (i + 1) + "/>");
      assertNotNull(HeadingElement.as(placeHolder.getFirstChildElement()));
    }

    if (getClass().desiredAssertionStatus()) {
      Element notHeading = Document.get().createDivElement();
      try {
        HeadingElement.as(notHeading);
        fail("Expected assertion failure");
      } catch (AssertionError e) {
        // this *should* happen.
      }
    }
  }

  /**
   * Tests Element.is() and Element.as().
   */
  public void testIsAndAs() {
    assertFalse(Element.is(Document.get()));

    Node div = Document.get().createDivElement();
    assertTrue(Element.is(div));
    assertEquals("div", Element.as(div).getTagName().toLowerCase());

    // Element.is(null) is allowed and should return false.
    assertFalse(Element.is(null));
  }

  /**
   * Document.createElement('ns:tag'), getTagName().
   */
  public void testNamespaces() {
    Element elem = Document.get().createElement("myns:elem");
    assertEquals("myns:elem", elem.getTagName().toLowerCase());
  }

  /**
   * className, id, tagName, title, dir, lang.
   */
  public void testNativeProperties() {
    DivElement div = Document.get().createDivElement();

    assertEquals("div", div.getTagName().toLowerCase());

    div.setClassName("myClass");
    assertEquals(div.getClassName(), "myClass");

    div.setId("myId");
    assertEquals(div.getId(), "myId");

    div.setTitle("myTitle");
    assertEquals(div.getTitle(), "myTitle");

    div.setDir("rtl");
    assertEquals(div.getDir(), "rtl");

    div.setLang("fr-FR");
    assertEquals(div.getLang(), "fr-FR");
  }

  /**
   * offset[Left|Top|Width|Height], offsetParent.
   */
  public void testOffsets() {
    DivElement outer = Document.get().createDivElement();
    DivElement middle = Document.get().createDivElement();
    DivElement inner = Document.get().createDivElement();

    Document.get().getBody().appendChild(outer);
    outer.appendChild(middle);
    middle.appendChild(inner);

    outer.getStyle().setProperty("position", "absolute");
    inner.getStyle().setProperty("position", "relative");
    inner.getStyle().setPropertyPx("left", 19);
    inner.getStyle().setPropertyPx("top", 23);
    inner.getStyle().setPropertyPx("width", 29);
    inner.getStyle().setPropertyPx("height", 31);

    assertEquals(outer, inner.getOffsetParent());
    assertEquals(19, inner.getOffsetLeft());
    assertEquals(23, inner.getOffsetTop());
    assertEquals(29, inner.getOffsetWidth());
    assertEquals(31, inner.getOffsetHeight());
  }

  /**
   * setProperty*, getProperty*.
   */
  public void testProperties() {
    DivElement div = Document.get().createDivElement();

    div.setPropertyString("foo", "bar");
    assertEquals("bar", div.getPropertyString("foo"));

    div.setPropertyInt("foo", 42);
    assertEquals(42, div.getPropertyInt("foo"));

    div.setPropertyBoolean("foo", true);
    div.setPropertyBoolean("bar", false);
    assertEquals(true, div.getPropertyBoolean("foo"));
    assertEquals(false, div.getPropertyBoolean("bar"));

    Object obj = new Object();
    div.setPropertyObject("baz", obj);
    assertEquals(obj, div.getPropertyObject("baz"));

    JavaScriptObject jso = createTrivialJSO();
    div.setPropertyJSO("tintin", jso);
    assertEquals(jso, div.getPropertyJSO("tintin"));
  }

  /**
   * scroll[Left|Top], scrollIntoView.
   */
  @DoNotRunWith({Platform.HtmlUnitLayout})
  public void testScrollIntoView() {
    final DivElement outer = Document.get().createDivElement();
    final DivElement inner = Document.get().createDivElement();

    outer.getStyle().setProperty("position", "absolute");
    outer.getStyle().setProperty("top", "0px");
    outer.getStyle().setProperty("left", "0px");
    outer.getStyle().setProperty("overflow", "auto");
    outer.getStyle().setProperty("width", "200px");
    outer.getStyle().setProperty("height", "200px");

    inner.getStyle().setProperty("marginTop", "800px");
    inner.getStyle().setProperty("marginLeft", "800px");

    outer.appendChild(inner);
    Document.get().getBody().appendChild(outer);
    inner.setInnerText(":-)");
    inner.scrollIntoView();

    // Ensure that we are scrolled.
    assertTrue(outer.getScrollTop() > 0);
    assertTrue(outer.getScrollLeft() > 0);

    outer.setScrollLeft(0);
    outer.setScrollTop(0);

    // Ensure that we are no longer scrolled.
    assertEquals(outer.getScrollTop(), 0);
    assertEquals(outer.getScrollLeft(), 0);
  }

  /**
   * Tests that scrollLeft behaves as expected in RTL mode.
   * Failed in all modes due to HtmlUnit bug:
   * https://sourceforge.net/tracker/?func=detail&aid=2941255&group_id=47038&atid=448266
   */
  @DoNotRunWith({Platform.HtmlUnitLayout})
  public void testScrollLeftInRtl() {
    final DivElement outer = Document.get().createDivElement();
    final DivElement inner = Document.get().createDivElement();

    outer.getStyle().setProperty("position", "absolute");
    outer.getStyle().setProperty("top", "0px");
    outer.getStyle().setProperty("left", "0px");
    outer.getStyle().setProperty("overflow", "auto");
    outer.getStyle().setProperty("width", "200px");
    outer.getStyle().setProperty("height", "200px");

    // Force scrolling on the outer div, because WebKit doesn't do this
    // correctly in RTL mode.
    outer.getStyle().setProperty("overflow", "scroll");

    inner.getStyle().setProperty("position", "absolute");
    inner.getStyle().setProperty("top", "0px");
    inner.getStyle().setProperty("left", "0px");
    inner.getStyle().setProperty("right", "0px");
    inner.getStyle().setProperty("marginTop", "800px");
    inner.getStyle().setProperty("marginRight", "800px");

    outer.appendChild(inner);
    Document.get().getBody().appendChild(outer);
    outer.setDir("rtl");

    // FF2 does not render scroll bars reliably in RTL, so we set a large
    // content to force the scroll bars.
    String content = "ssssssssssssssssssssssssssssssssssssssssssssssssssss"
        + "sssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssss"
        + "sssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssss";
    inner.setInnerText(content);

    // The important thing is that setting and retrieving scrollLeft values in
    // RTL mode works only for negative numbers, and that they round-trip
    // correctly.
    outer.setScrollLeft(-32);
    assertEquals(-32, outer.getScrollLeft());

    outer.setScrollLeft(32);
    assertEquals(0, outer.getScrollLeft());
  }

  /**
   * innerHTML.
   */
  public void testSetInnerHTML() {
    DivElement div = Document.get().createDivElement();
    div.setInnerHTML("<button><img src='foo.gif'></button>");

    Element button = div.getFirstChildElement();
    Element img = button.getFirstChildElement();

    assertEquals("button", button.getTagName().toLowerCase());
    assertEquals("img", img.getTagName().toLowerCase());
    assertTrue(((ImageElement) img).getSrc().endsWith("foo.gif"));
  }

  /**
   * innerText.
   */
  public void testSetInnerText() {
    Document doc = Document.get();

    TableElement tableElem = doc.createTableElement();
    TableRowElement trElem = doc.createTRElement();
    TableCellElement tdElem = doc.createTDElement();
    tdElem.setInnerText("Some Table Heading Data");

    // Add a <em> element as a child to the td element
    Element emElem = doc.createElement("em");
    emElem.setInnerText("Some emphasized text");
    tdElem.appendChild(emElem);

    trElem.appendChild(tdElem);
    tableElem.appendChild(trElem);
    doc.getBody().appendChild(tableElem);
    tdElem.setInnerText(null);

    // Once we set the inner text on an element to null, all of the element's
    // child nodes should be deleted, including any text nodes, for all
    // supported browsers.
    assertTrue(tdElem.getChildNodes().getLength() == 0);
  }

  /**
   * style.
   */
  public void testStyle() {
    DivElement div = Document.get().createDivElement();

    div.getStyle().setProperty("color", "black");
    assertEquals("black", div.getStyle().getProperty("color"));

    div.getStyle().setPropertyPx("width", 42);
    assertEquals("42px", div.getStyle().getProperty("width"));
  }

  /**
   * Test that styles only allow camelCase.
   */
  public void testStyleCamelCase() {
    DivElement div = Document.get().createDivElement();

    // Use a camelCase property
    div.getStyle().setProperty("backgroundColor", "black");
    assertEquals("black", div.getStyle().getProperty("backgroundColor"));
    div.getStyle().setPropertyPx("marginLeft", 10);
    assertEquals("10px", div.getStyle().getProperty("marginLeft"));

    // Use a hyphenated style
    if (Style.class.desiredAssertionStatus()) {
      try {
        div.getStyle().setProperty("background-color", "red");
        fail("Expected assertion error: background-color should be in camelCase");
      } catch (AssertionError e) {
        // expected
      }
      try {
        div.getStyle().setPropertyPx("margin-left", 20);
        fail("Expected assertion error: margin-left should be in camelCase");
      } catch (AssertionError e) {
        // expected
      }
      try {
        div.getStyle().getProperty("margin-right");
        fail("Expected assertion error: margin-right should be in camelCase");
      } catch (AssertionError e) {
        // expected
      }
    }
  }

  private native JavaScriptObject createTrivialJSO() /*-{
    return {};
  }-*/;

  // Stolen from UserAgentPropertyGenerator
  private native boolean isIE6or7() /*-{
    var ua = navigator.userAgent.toLowerCase();
    if (ua.indexOf("msie") != -1) {
      if ($doc.documentMode >= 8) {
        return false;
      }
      return true;
    }
    return false;
  }-*/;
}
