/*
 * Copyright 2010 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.cell.client;

import com.google.gwt.cell.client.Cell.Context;
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.junit.client.GWTTestCase;
import com.google.gwt.safehtml.shared.SafeHtmlBuilder;
import com.google.gwt.user.client.DOM;
import com.google.gwt.user.client.Event;
import com.google.gwt.user.client.EventListener;

import java.util.Set;

/**
 * Base class for testing {@link Cell}.
 *
 * @param <T> the cell type
 */
public abstract class CellTestBase<T> extends GWTTestCase {

  /**
   * A mock cell used for testing.
   *
   * @param <T> the cell type
   */
  static class MockCell<T> extends AbstractCell<T> {

    private final boolean isSelectable;
    private Context lastContext;
    private T lastEventValue;
    private Element lastParentElement;
    private final T updateValue;

    public MockCell(boolean isSelectable, T updateValue,
        String... consumedEvents) {
      super(consumedEvents);
      this.isSelectable = isSelectable;
      this.updateValue = updateValue;
    }

    public void assertLastEventValue(T expected) {
      assertEquals(expected, lastEventValue);
    }

    public void assertLastParentElement(Element expected) {
      assertEquals(expected, lastParentElement);
    }

    
    @Override
    public boolean dependsOnSelection() {
      return isSelectable;
    }

    public Context getLastContext() {
      return lastContext;
    }

    @Override
    public boolean handlesSelection() {
      return isSelectable;
    }

    @Override
    public void onBrowserEvent(Context context, Element parent, T value,
        NativeEvent event, ValueUpdater<T> valueUpdater) {
      lastContext = context;
      lastParentElement = parent;
      lastEventValue = value;
      if (valueUpdater != null) {
        valueUpdater.update(updateValue);
      }
    }

    @Override
    public void render(Context context, T value, SafeHtmlBuilder sb) {
      lastContext = context;
      if (value != null) {
        sb.appendEscaped(String.valueOf(value));
      }
    }
  }

  /**
   * A mock {@link ValueUpdater} used for testing.
   */
  class MockValueUpdater implements ValueUpdater<T> {

    private T lastValue;

    public void assertLastValue(T expected) {
      assertEquals(expected, lastValue);
      lastValue = null;
    }

    public void update(T value) {
      assertNull(lastValue);
      assertNotNull(value);
      this.lastValue = value;
    }
  }

  /**
   * The default row value key used for all tests.
   */
  protected static final Object DEFAULT_KEY = new Object();

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

  public void testDependsOnSelection() {
    assertEquals(dependsOnSelection(), createCell().dependsOnSelection());
  }

  public void testGetConsumedEvents() {
    Set<String> consumedEvents = createCell().getConsumedEvents();
    String[] expected = getConsumedEvents();
    if (consumedEvents == null && expected == null) {
      return;
    }
    assertEquals(expected.length, consumedEvents.size());
    for (String typeName : expected) {
      assertTrue(consumedEvents.contains(typeName));
    }
  }

  public void testHandlesSelection() {
    // None of the provided cells handle selection.
    assertFalse(createCell().handlesSelection());
  }

  /**
   * Test rendering the cell with a valid value and no view data.
   */
  public void testRender() {
    Cell<T> cell = createCell();
    T value = createCellValue();
    SafeHtmlBuilder sb = new SafeHtmlBuilder();
    Context context = new Context(0, 0, null);
    cell.render(context, value, sb);
    assertEquals(getExpectedInnerHtml(), sb.toSafeHtml().asString());
  }

  /**
   * Test rendering the cell with a negative index is handled.
   */
  public void testRenderNegativeIndex() {
    Cell<T> cell = createCell();
    T value = createCellValue();
    SafeHtmlBuilder sb = new SafeHtmlBuilder();
    Context context = new Context(-1, -1, null);
    cell.render(context, value, sb);
    assertEquals(getExpectedInnerHtml(), sb.toSafeHtml().asString());
  }

  /**
   * Test rendering the cell with a null value and no view data.
   */
  public void testRenderNull() {
    Cell<T> cell = createCell();
    SafeHtmlBuilder sb = new SafeHtmlBuilder();
    Context context = new Context(0, 0, null);
    cell.render(context, null, sb);
    assertEquals(getExpectedInnerHtmlNull(), sb.toSafeHtml().asString());
  }

  /**
   * Create a new cell to test.
   *
   * @return the new cell
   */
  protected abstract Cell<T> createCell();

  /**
   * Create a value to test.
   *
   * @return the cell value
   */
  protected abstract T createCellValue();

  /**
   * Does the cell type depend on selection? Default to false.
   *
   * @return true expected value of dependsOnSelection
   */
  protected abstract boolean dependsOnSelection();

  /**
   * Get the expected events that the cell should consume.
   *
   * @return the consumed events.
   */
  protected abstract String[] getConsumedEvents();

  /**
   * Get the expected inner HTML value of the rendered cell.
   *
   * @return the expected string
   */
  protected abstract String getExpectedInnerHtml();

  /**
   * Get the expected inner HTML value of the rendered cell when null is passed
   * as the cell value.
   *
   * @return the expected string
   */
  protected abstract String getExpectedInnerHtmlNull();

  /**
   * Test
   * {@link Cell#onBrowserEvent(Element, Object, Object, NativeEvent, ValueUpdater)}
   * with the specified conditions.
   * 
   * @param startHtml the innerHTML of the cell before the test starts
   * @param event the event to fire
   * @param value the cell value
   * @param expectedValue the expected value passed to the value updater, or
   *          null if none expected
   * @return the parent element
   */
  protected Element testOnBrowserEvent(String startHtml, NativeEvent event, final T value,
      T expectedValue) {
    return testOnBrowserEvent(createCell(), startHtml, event, value, expectedValue, true);
  }

  /**
   * Test
   * {@link Cell#onBrowserEvent(Element, Object, Object, NativeEvent, ValueUpdater)}
   * with the specified conditions.
   * 
   * @param cell the cell to use
   * @param startHtml the innerHTML of the cell before the test starts
   * @param event the event to fire
   * @param value the cell value
   * @param expectedValue the expected value passed to the value updater, or
   *          null if none expected
   * @param dispatchToFirstChild true to dispatch to the first child of the
   *          rendered parent element, if one is available
   * @return the parent element
   */
  protected Element testOnBrowserEvent(final Cell<T> cell, String startHtml, NativeEvent event,
      final T value, T expectedValue, boolean dispatchToFirstChild) {
    // Setup the parent element.
    final com.google.gwt.user.client.Element parent = Document.get().createDivElement().cast();
    parent.setInnerHTML(startHtml);
    Document.get().getBody().appendChild(parent);

    // If the element has a child, use it as the event target.
    Element target = parent;
    if (dispatchToFirstChild) {
      Element child = parent.getFirstChildElement();
      target = (child == null) ? parent : child;
    }

    // Pass the event to the cell.
    final MockValueUpdater valueUpdater = new MockValueUpdater();
    Event.setEventListener(parent, new EventListener() {
      public void onBrowserEvent(Event event) {
        try {
          DOM.setEventListener(parent, null);
          Context context = new Context(0, 0, DEFAULT_KEY);
          cell.onBrowserEvent(context, parent, value, event, valueUpdater);
          parent.removeFromParent();
        } catch (Exception e) {
          // We are in an event loop, so events may not propagate out to JUnit.
          fail("An exception occured while handling the event: " + e.getMessage());
        }
      }
    });
    Event.sinkEvents(target, Event.getTypeInt(event.getType()));
    target.dispatchEvent(event);
    assertNull(DOM.getEventListener(parent));

    // Check the expected value and view data.
    valueUpdater.assertLastValue(expectedValue);
    return parent;
  }
}
