/*
 * Copyright 2011 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.uibinder.test.client;

import com.google.gwt.cell.client.AbstractCell;
import com.google.gwt.dom.client.DivElement;
import com.google.gwt.dom.client.Document;
import com.google.gwt.dom.client.Element;
import com.google.gwt.dom.client.NativeEvent;
import com.google.gwt.dom.client.TableCellElement;
import com.google.gwt.event.dom.client.ClickEvent;
import com.google.gwt.event.dom.client.DomEvent;
import com.google.gwt.event.dom.client.KeyPressEvent;
import com.google.gwt.junit.client.GWTTestCase;
import com.google.gwt.safehtml.shared.SafeHtml;
import com.google.gwt.safehtml.shared.SafeHtmlBuilder;
import com.google.gwt.uibinder.client.UiHandler;
import com.google.gwt.uibinder.test.client.UiRendererUi.Bar;
import com.google.gwt.uibinder.test.client.UiRendererUi.Foo;

/**
 * Functional test of UiRenderer event handling.
 */
public class UiRendererEventsTest extends GWTTestCase {

  /**
   * Receives events containing {@link UiRendererUi.Bar} objects dispatched from
   * {@link UiRendererUi.HtmlRenderer#onBrowserEvent(MockBarReceiver, NativeEvent, Element,
   * UiRendererUi.Bar, int)}.
   */
  public class MockBarReceiver extends AbstractCell<Integer> {

    public DomEvent<?> event;
    public Bar firstExtraParam;
    public int handlerCalled = 0;
    public Element root;
    public int secondExtraParam;

    @Override
    public void render(com.google.gwt.cell.client.Cell.Context context, Integer value,
        SafeHtmlBuilder sb) {
      UiRendererUi.getRenderer().render(sb, new Foo(value.toString()), new Foo(value.toString()));
    }

    @UiHandler({"nameSpan"})
    void handler1(ClickEvent clickEvent, Element theRoot, Bar e, int f) {
      handlerCalled = 1;
      this.event = clickEvent;
      this.root = theRoot;
      this.firstExtraParam = e;
      this.secondExtraParam = f;
    }
  }

  /**
   * Implements all methods needed by {@link MockBazReceiver}.
   */
  public class MockBaseReceiver extends AbstractCell<Integer> {

    public DomEvent<?> event;
    public int handlerCalled = 0;

    @Override
    public void render(com.google.gwt.cell.client.Cell.Context context, Integer value,
        SafeHtmlBuilder sb) {
      UiRendererUi.getInheritedRenderer().render(sb, new Foo(value.toString()),
          new Foo(value.toString()));
    }

    @UiHandler({"th3"})
    void handler1(ClickEvent clickEvent) {
      handlerCalled = 1;
      this.event = clickEvent;
    }
  }

  /**
   * Receives events dispatched from
   * {@link UiRendererUi.InheritedRenderer#onBrowserEvent(MockBazReceiver, NativeEvent, Element, 
   * boolean)}.
   */
  public class MockBazReceiver extends MockBaseReceiver {
  }

  /**
   * Receives events containing {@link UiRendererUi.Foo} objects dispatched from
   * {@link UiRendererUi.HtmlRenderer#onBrowserEvent(MockFooReceiver, NativeEvent, Element,
   * UiRendererUi.Foo, String)}.
   */
  public class MockFooReceiver extends AbstractCell<String> {

    public DomEvent<?> event;
    public Foo firstExtraParam;
    public int handlerCalled = 0;
    public Element root;
    public String secondExtraParam;

    @Override
    public void render(com.google.gwt.cell.client.Cell.Context context, String value,
        SafeHtmlBuilder sb) {
      UiRendererUi.getRenderer().render(sb, new Foo(value), new Foo(value));
    }

    @UiHandler({"root", "tmElement"})
    void handler1(ClickEvent clickEvent, Element theRoot, Foo a, String b) {
      handlerCalled = 1;
      this.event = clickEvent;
      this.root = theRoot;
      this.firstExtraParam = a;
      this.secondExtraParam = b;
    }

    @UiHandler({"th1"})
    void handler2(KeyPressEvent keyEvent, Element aRoot, Foo c, String d) {
      handlerCalled = 2;
      this.event = keyEvent;
      this.root = aRoot;
      this.firstExtraParam = c;
      this.secondExtraParam = d;
    }

    @UiHandler({"tr2"})
    void handler3(ClickEvent clickEvent, Element aRoot, Foo e, String f) {
      handlerCalled = 3;
      this.event = clickEvent;
      this.root = aRoot;
      this.firstExtraParam = e;
      this.secondExtraParam = f;
    }
  }
  private MockBarReceiver barReceiver;
  private MockBazReceiver bazReceiver;
  private MockFooReceiver fooReceiver;

  private SafeHtml renderedUi;

  private DivElement uiParent;

  private UiRendererUi uiRendererUi;

  private Element uiRoot;

  @Override
  public String getModuleName() {
    return "com.google.gwt.uibinder.test.LazyWidgetBuilderSuite";
  }

  @Override
  public void gwtSetUp() throws Exception {
    super.gwtSetUp();
    UiRendererTestApp app = UiRendererTestApp.getInstance();
    uiRendererUi = app.getUiRendererUi();
    renderedUi = uiRendererUi.render("once", "twice");

    fooReceiver = new MockFooReceiver();
    barReceiver = new MockBarReceiver();
    bazReceiver = new MockBazReceiver();

    uiParent = Document.get().createDivElement();
    uiParent.setInnerSafeHtml(renderedUi);
    Document.get().getBody().appendChild(uiParent);

    uiRoot = Element.as(uiParent.getChild(0));
  }

  public void testDispatchEventAtRoot() {

    NativeEvent eventAtRoot = createMockNativeEvent(uiRoot, "click");

    UiRendererUi.getRenderer().onBrowserEvent(fooReceiver, eventAtRoot, uiRoot, new Foo("one"), "two");

    assertEquals(1, fooReceiver.handlerCalled);
    assertEquals("click", fooReceiver.event.getAssociatedType().getName());
    assertEquals(uiRoot, fooReceiver.root);
    assertEquals("one", fooReceiver.firstExtraParam.bar);
    assertEquals("two", fooReceiver.secondExtraParam);

    // Dispatch also works when the parent is passed
    fooReceiver = new MockFooReceiver();
    UiRendererUi.getRenderer().onBrowserEvent(fooReceiver, eventAtRoot, uiParent, new Foo("three"), "four");

    assertEquals(1, fooReceiver.handlerCalled);
    assertEquals("click", fooReceiver.event.getAssociatedType().getName());
    assertEquals(uiRoot, fooReceiver.root);
    assertEquals("three", fooReceiver.firstExtraParam.bar);
    assertEquals("four", fooReceiver.secondExtraParam);
  }

  public void testDispatchWithInheritedRenderer() {

    TableCellElement th3 = UiRendererUi.getInheritedRenderer().getTh3(uiRoot);
    NativeEvent eventAtTh3 = createMockNativeEvent(th3, "click");

    UiRendererUi.getInheritedRenderer().onBrowserEvent(bazReceiver, eventAtTh3, uiRoot);

    assertEquals(1, bazReceiver.handlerCalled);
    assertEquals("click", bazReceiver.event.getAssociatedType().getName());
  }

  public void testDispatchWithinNestedElement() {
    Element th4 = UiRendererUi.getRenderer().getTh4(uiRoot);
    NativeEvent eventAtTh4 = createMockNativeEvent(th4, "click");
    UiRendererUi.getRenderer().onBrowserEvent(fooReceiver, eventAtTh4, uiRoot, new Foo("one"), "two");

    assertEquals(3, fooReceiver.handlerCalled);
    assertEquals("click", fooReceiver.event.getAssociatedType().getName());
    assertEquals(uiRoot, fooReceiver.root);
    assertEquals("one", fooReceiver.firstExtraParam.bar);
    assertEquals("two", fooReceiver.secondExtraParam);
  }

  public void testDispatchWithinRoot() {
    Element tmElement = UiRendererUi.getRenderer().getTmElement(uiRoot);
    NativeEvent eventAtTm = createMockNativeEvent(tmElement, "click");
    UiRendererUi.getRenderer().onBrowserEvent(fooReceiver, eventAtTm, uiRoot, new Foo("one"), "two");

    assertEquals(1, fooReceiver.handlerCalled);
    assertEquals("click", fooReceiver.event.getAssociatedType().getName());
    assertEquals(uiRoot, fooReceiver.root);
    assertEquals("one", fooReceiver.firstExtraParam.bar);
    assertEquals("two", fooReceiver.secondExtraParam);

    Element th1 = UiRendererUi.getRenderer().getTh1(uiRoot);
    NativeEvent eventAtTh1 = createMockNativeEvent(th1, "keypress");
    fooReceiver = new MockFooReceiver();
    UiRendererUi.getRenderer().onBrowserEvent(fooReceiver, eventAtTh1, uiRoot, new Foo("three"), "four");

    assertEquals(2, fooReceiver.handlerCalled);
    assertEquals("keypress", fooReceiver.event.getAssociatedType().getName());
    assertEquals(uiRoot, fooReceiver.root);
    assertEquals("three", fooReceiver.firstExtraParam.bar);
    assertEquals("four", fooReceiver.secondExtraParam);

    Element nameSpan = UiRendererUi.getRenderer().getNameSpan(uiRoot);
    NativeEvent eventAtNameSpan = createMockNativeEvent(nameSpan, "click");
    fooReceiver = new MockFooReceiver();
    UiRendererUi.getRenderer().onBrowserEvent(barReceiver, eventAtNameSpan, uiRoot, new Bar(5), 6);

    assertEquals(1, barReceiver.handlerCalled);
    assertEquals("click", barReceiver.event.getAssociatedType().getName());
    assertEquals(uiRoot, barReceiver.root);
    assertEquals(5, barReceiver.firstExtraParam.baz.intValue());
    assertEquals(6, barReceiver.secondExtraParam);
  }

  public void testNoDispatchOnNullRoot() {
    NativeEvent eventAtBody = createMockNativeEvent(Document.get().getBody(), "click");
    try {
      UiRendererUi.getRenderer().onBrowserEvent(fooReceiver, eventAtBody, null, new Foo("one"), "two");
      fail("NPE expected");
    } catch (NullPointerException e) {
      // Expected case
      assertEquals(0, fooReceiver.handlerCalled);
    }
  }

  public void testNoDispatchOnNullEvent() {
    try {
      UiRendererUi.getRenderer().onBrowserEvent(fooReceiver, null, uiRoot, new Foo("one"), "two");
      fail("NPE expected");
    } catch (NullPointerException e) {
      // Expected case
      assertEquals(0, fooReceiver.handlerCalled);
    }
  }

  public void testNoDispatchOnNullReceiver() {
    NativeEvent eventAtBody = createMockNativeEvent(Document.get().getBody(), "click");
    try {
      UiRendererUi.getRenderer().onBrowserEvent(null, eventAtBody, uiRoot, new Foo("one"), "two");
      fail("NPE expected");
    } catch (NullPointerException e) {
      // Expected case
      assertEquals(0, fooReceiver.handlerCalled);
    }
  }

  public void testNoDispatchOutsideRendered() {
    // An event at the body is not dispatched
    NativeEvent eventAtBody = createMockNativeEvent(Document.get().getBody(), "click");
    UiRendererUi.getRenderer().onBrowserEvent(fooReceiver, eventAtBody, uiRoot, new Foo("one"), "two");
    assertEquals(0, fooReceiver.handlerCalled);

    // An event at the parent is not dispatched
    NativeEvent eventAtParent = createMockNativeEvent(uiParent, "click");
    fooReceiver = new MockFooReceiver();
    UiRendererUi.getRenderer().onBrowserEvent(fooReceiver, eventAtParent, uiRoot, new Foo("one"), "two");
    assertEquals(0, fooReceiver.handlerCalled);

    // At an element besides the parent does not fire either
    DivElement externalDiv = Document.get().createDivElement();
    Document.get().getBody().appendChild(externalDiv);
    NativeEvent eventAtDiv = createMockNativeEvent(externalDiv, "click");
    fooReceiver = new MockFooReceiver();
    UiRendererUi.getRenderer().onBrowserEvent(fooReceiver, eventAtDiv, uiRoot, new Foo("one"), "two");
    assertEquals(0, fooReceiver.handlerCalled);
  }

  @Override
  protected void gwtTearDown() {
    uiParent.removeFromParent();
    uiParent = null;
  }

  private native NativeEvent createMockNativeEvent(Element target, String type) /*-{
    var event = {};

    event.target = target;
    // For IE < 9
    event.srcElement = target;

    event.type = type;
    return event;
  }-*/;
}
