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

import com.google.gwt.aria.client.State;
import com.google.gwt.debug.client.DebugInfo;
import com.google.gwt.dom.client.Document;
import com.google.gwt.dom.client.Element;
import com.google.gwt.dom.client.SpanElement;
import com.google.gwt.dom.client.Style;
import com.google.gwt.junit.client.GWTTestCase;
import com.google.gwt.user.client.DOM;

/**
 * Tests UIObject. Currently, focuses on style name behaviors.
 */
public class UIObjectTest extends GWTTestCase {
  static class MyObject extends UIObject {
    public Element subElement;

    MyObject() {
      setElement(DOM.createDiv());
      subElement = DOM.createDiv();
    }

    @Override
    protected void onEnsureDebugId(String baseID) {
      super.onEnsureDebugId(baseID);
      ensureDebugId(subElement, baseID, "subElem");
    }
  }

  /**
   * Verify that an element has the specified debug id.
   * 
   * @param debugID the debug ID
   * @param elem the {@link Element} that should have the id
   */
  public static void assertDebugId(String debugID, Element elem) {
    debugID = UIObject.DEBUG_ID_PREFIX + debugID;
    assertEquals(debugID, elem.getPropertyString("id"));
  }

  /**
   * Verify that the contents of an element match the expected contents. This
   * method is useful to test debug IDs of private, inaccessible members of a
   * Widget. Note that this method requires that the Widget is added to the
   * {@link RootPanel} and should be called from a
   * {@link com.google.gwt.user.client.DeferredCommand} to give the browser
   * enough time to register the ID.
   * 
   * @param debugID the debug ID of the element
   * @param contents the contents expected in the inner HTML
   */
  public static void assertDebugIdContents(String debugID, String contents) {
    debugID = UIObject.DEBUG_ID_PREFIX + debugID;
    Element elem = DOM.getElementById(debugID);
    assertEquals(contents, elem.getInnerHTML());
  }

  @Override
  public String getModuleName() {
    return "com.google.gwt.user.DebugTest";
  }
  
  public void testToString() {
    UIObject u = new UIObject() {
    };
    assertEquals("(null handle)", u.toString());
    SpanElement span = Document.get().createSpanElement();
    u.setElement(span);
    assertEquals(span.getString(), u.toString());
  }

  public void testAccidentalPrimary() {
    MyObject o = new MyObject();
    o.addStyleName("accidentalPrimary");
    assertEquals("accidentalPrimary", o.getStylePrimaryName());
  }

  public void testAddAndRemoveEmptyStyleName() {
    MyObject o = new MyObject();

    o.setStylePrimaryName("primary");
    try {
      o.addStyleName("");
      fail();
    } catch (IllegalArgumentException e) {
      // This *should* throw.
    }

    try {
      o.addStyleName(" ");
      fail();
    } catch (IllegalArgumentException e) {
      // This *should* throw.
    }

    try {
      o.removeStyleName("");
      fail();
    } catch (IllegalArgumentException e) {
      // This *should* throw.
    }

    try {
      o.removeStyleName(" ");
      fail();
    } catch (IllegalArgumentException e) {
      // This *should* throw.
    }

    try {
      o.setStyleName("", true);
      fail();
    } catch (IllegalArgumentException e) {
      // This *should* throw.
    }

    try {
      o.setStyleName(" ", false);
      fail();
    } catch (IllegalArgumentException e) {
      // This *should* throw.
    }

    assertEquals("primary", o.getStylePrimaryName());
  }

  public void testDebugIdOnElement() {
    // Test basic set
    Element oElem = DOM.createDiv();
    UIObject.ensureDebugId(oElem, "test1");
    assertDebugId("test1", oElem);

    // Test override with new ID
    UIObject.ensureDebugId(oElem, "test2");
    assertDebugId("test2", oElem);

    // Test setting actual id
    oElem.setPropertyString("id", "mytest");
    assertEquals("mytest", oElem.getPropertyString("id"));

    // Test overriding with debug ID succeeds if ID present
    UIObject.ensureDebugId(oElem, "test3");
    assertDebugId("test3", oElem);
  }

  public void testDebugId() {
    // Test basic set
    MyObject o = new MyObject();
    Element oElem = o.getElement();
    o.ensureDebugId("test1");
    assertDebugId("test1", oElem);
    assertDebugId("test1-subElem", o.subElement);

    // Test override with new ID
    o.ensureDebugId("test2");
    assertDebugId("test2", oElem);
    assertDebugId("test2-subElem", o.subElement);

    // Test setting actual id
    oElem.setPropertyString("id", "mytest");
    assertEquals("mytest", oElem.getPropertyString("id"));
    assertDebugId("test2-subElem", o.subElement);

    // Test overriding with debug ID succeeds if ID present
    assertEquals("mytest", oElem.getPropertyString("id"));
    o.ensureDebugId("test3");
    assertDebugId("test3", oElem);
    assertDebugId("test3-subElem", o.subElement);
  }

  public void testDebugIdAsAttribute() {
    String oldAttribute = DebugInfo.getDebugIdAttribute();
    boolean asProperty = DebugInfo.isDebugIdAsProperty();
    DebugInfo.setDebugIdAttribute("debugid", false);

    MyObject o = new MyObject();
    Element oElem = o.getElement();
    o.ensureDebugId("test");
    assertEquals(DebugInfo.DEFAULT_DEBUG_ID_PREFIX + "test", oElem.getAttribute("debugid"));
    assertEquals(DebugInfo.DEFAULT_DEBUG_ID_PREFIX + "test-subElem", o.subElement
        .getAttribute("debugid"));

    // Reset the old attribute.
    DebugInfo.setDebugIdAttribute(oldAttribute, asProperty);
  }

  public void testDebugIdWithoutPrefix() {
    String oldPrefix = DebugInfo.getDebugIdPrefix();
    DebugInfo.setDebugIdPrefix("");

    MyObject o = new MyObject();
    Element oElem = o.getElement();
    o.ensureDebugId("test");
    assertEquals("test", oElem.getPropertyString("id"));
    assertEquals("test-subElem", o.subElement.getPropertyString("id"));

    // Reset the prefix.
    DebugInfo.setDebugIdPrefix(oldPrefix);
  }

  public void testIsVisible_defaultDisplay() {
    Element elem = DOM.createDiv();
    assertTrue(UIObject.isVisible(elem));
  }

  public void testIsVisible_customDisplay() {
    Element elem = DOM.createDiv();
    elem.getStyle().setDisplay(Style.Display.INLINE_BLOCK);
    assertTrue(UIObject.isVisible(elem));
  }

  public void testIsVisible_hidden() {
    Element elem = DOM.createDiv();
    elem.getStyle().setDisplay(Style.Display.NONE);
    assertFalse(UIObject.isVisible(elem));
  }

  public void testIsVisible_ignoresAria() {
    Element elem = DOM.createDiv();
    State.HIDDEN.set(elem, true);
    assertTrue(UIObject.isVisible(elem));
  }

  public void testSetVisible() {
    // Initial state: visible
    Element elem = DOM.createDiv();
    assertTrue(UIObject.isVisible(elem));

    // Hide
    UIObject.setVisible(elem, false);
    assertFalse(UIObject.isVisible(elem));
    assertEquals(Style.Display.NONE.getCssName(), elem.getStyle().getDisplay());
    assertTrue(Boolean.valueOf(State.HIDDEN.get(elem)));

    // Show again
    UIObject.setVisible(elem, true);
    assertTrue(UIObject.isVisible(elem));
    assertEquals("", elem.getStyle().getDisplay());
    assertEquals("", State.HIDDEN.get(elem));
  }

  public void testNormal() {
    // Test the basic set/get case.
    MyObject o = new MyObject();
    o.setStylePrimaryName("primaryStyle");

    // Note: getStyleName() explicitly returns the className attribute, so it
    // doesn't guarantee that there aren't leading or trailing spaces.
    assertEquals("primaryStyle", o.getStyleName());
    doDependentAndSecondaryStyleTest(o, true);
    assertEquals("primaryStyle", o.getStyleName());
    doDependentAndSecondaryStyleTest(o, false);
    assertEquals("primaryStyle", o.getStyleName());
  }

  public void testSetEmptyPrimaryStyleName() {
    MyObject o = new MyObject();
    try {
      o.setStylePrimaryName("");
      fail();
    } catch (IllegalArgumentException e) {
      // This *should* throw.
    }

    try {
      o.setStylePrimaryName(" ");
      fail();
    } catch (IllegalArgumentException e) {
      // This *should* throw.
    }
  }

  public void testSetStyleNameNormalization() {
    MyObject o = new MyObject();

    o.setStylePrimaryName(" one ");
    o.addStyleName("  two  ");
    o.addStyleName("\tthree\t");

    assertEquals("one two three", o.getStyleName());
  }

  public void testSetStylePrimaryName() {
    MyObject o = new MyObject();
    o.setStylePrimaryName("gwt");
    o.addStyleDependentName("dependent");
    o.addStyleName("i-heart-gwt");
    o.addStyleName("i-gwt-heart");

    assertTrue(containsClass(o, "gwt"));
    assertTrue(containsClass(o, "gwt-dependent"));
    assertTrue(containsClass(o, "i-heart-gwt"));
    assertTrue(containsClass(o, "i-gwt-heart"));

    o.setStylePrimaryName("awt");

    assertPrimaryStyleNameEquals(o, "awt");
    assertTrue(containsClass(o, "awt-dependent"));
    assertFalse(containsClass(o, "gwt-dependent"));
    assertTrue(containsClass(o, "i-heart-gwt"));
    assertTrue(containsClass(o, "i-gwt-heart"));
    assertFalse(containsClass(o, "i-heart-awt"));
    assertFalse(containsClass(o, "i-awt-heart"));
  }

  public void testMissingElementAssertion() {
    try {
      Widget w = new Widget() {
      };

      w.getElement();
      if (UIObjectTest.class.desiredAssertionStatus()) {
        fail("Expected assertion failure");
      }
    } catch (AssertionError e) {
      assertEquals(UIObject.MISSING_ELEMENT_ERROR, e.getMessage());
    }

    try {
      Composite c = new Composite() {
      };

      c.getElement();
      if (UIObjectTest.class.desiredAssertionStatus()) {
        fail("Expected assertion failure");
      }
    } catch (AssertionError e) {
      assertEquals(UIObject.MISSING_ELEMENT_ERROR, e.getMessage());
    }
  }

  public void testSetElementTwiceFails() {
    UIObject o = new UIObject() {
      {
        setElement(DOM.createDiv());
      }
    };

    try {
      o.setElement(DOM.createSpan());
      if (UIObjectTest.class.desiredAssertionStatus()) {
        fail("Expected assertion failure");
      }
    } catch (AssertionError e) {
      assertEquals(UIObject.SETELEMENT_TWICE_ERROR, e.getMessage());
    }
  }

  private void assertPrimaryStyleNameEquals(UIObject o, String className) {
    String attr = o.getElement().getPropertyString("className");
    assertTrue(attr.indexOf(className) == 0);
    assertTrue(attr.length() == className.length()
        || attr.charAt(className.length()) == ' ');
  }

  private boolean containsClass(UIObject o, String className) {
    String[] classes = o.getElement().getPropertyString("className").split(
        "\\s+");
    for (int i = 0; i < classes.length; i++) {
      if (className.equals(classes[i])) {
        return true;
      }
    }
    return false;
  }

  // doStuff() should leave MyObject's style in the same state it started in.
  private void doDependentAndSecondaryStyleTest(MyObject o, boolean usingSet) {
    // Test that the primary style remains the first class, and that the
    // dependent style shows up.
    if (usingSet) {
      o.setStyleDependentName("dependent", true);
    } else {
      o.addStyleDependentName("dependent");
    }
    assertTrue(containsClass(o, o.getStylePrimaryName() + "-dependent"));

    String oldPrimaryStyle = o.getStylePrimaryName();

    // Test that replacing the primary style name works (and doesn't munge up
    // the secondary style).
    if (usingSet) {
      o.setStyleName("secondaryStyle", true);
    } else {
      o.addStyleName("secondaryStyle");
    }
    o.setStylePrimaryName("newPrimaryStyle");

    assertEquals("newPrimaryStyle", o.getStylePrimaryName());
    assertPrimaryStyleNameEquals(o, "newPrimaryStyle");
    assertTrue(containsClass(o, "newPrimaryStyle-dependent"));
    assertTrue(containsClass(o, "secondaryStyle"));
    assertFalse(containsClass(o, oldPrimaryStyle));
    assertFalse(containsClass(o, oldPrimaryStyle + "-dependent"));

    // Clean up & return.
    o.setStylePrimaryName(oldPrimaryStyle);
    if (usingSet) {
      o.setStyleDependentName("dependent", false);
      o.setStyleName("secondaryStyle", false);
    } else {
      o.removeStyleDependentName("dependent");
      o.removeStyleName("secondaryStyle");
    }
    assertFalse(containsClass(o, o.getStylePrimaryName() + "-dependent"));
    assertFalse(containsClass(o, "secondaryStyle"));
  }
}
