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

import com.google.gwt.cell.client.Cell;
import com.google.gwt.core.client.Scheduler;
import com.google.gwt.dom.client.Document;
import com.google.gwt.dom.client.Element;
import com.google.gwt.dom.client.EventTarget;
import com.google.gwt.event.dom.client.KeyCodes;
import com.google.gwt.event.logical.shared.ValueChangeEvent;
import com.google.gwt.event.logical.shared.ValueChangeHandler;
import com.google.gwt.event.shared.EventHandler;
import com.google.gwt.event.shared.GwtEvent.Type;
import com.google.gwt.event.shared.HandlerRegistration;
import com.google.gwt.safehtml.shared.SafeHtml;
import com.google.gwt.safehtml.shared.SafeHtmlBuilder;
import com.google.gwt.user.cellview.client.HasDataPresenter.ElementIterator;
import com.google.gwt.user.cellview.client.HasDataPresenter.LoadingState;
import com.google.gwt.user.client.DOM;
import com.google.gwt.user.client.Event;
import com.google.gwt.user.client.ui.Focusable;
import com.google.gwt.user.client.ui.Widget;
import com.google.gwt.user.client.ui.impl.FocusImpl;
import com.google.gwt.view.client.HasData;
import com.google.gwt.view.client.HasKeyProvider;
import com.google.gwt.view.client.ProvidesKey;
import com.google.gwt.view.client.Range;
import com.google.gwt.view.client.RangeChangeEvent;
import com.google.gwt.view.client.RowCountChangeEvent;
import com.google.gwt.view.client.SelectionModel;

import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Set;

/**
 * An abstract {@link Widget} that implements {@link HasData}.
 *
 * @param <T> the data type of each row
 */
public abstract class AbstractHasData<T> extends Widget implements HasData<T>,
    HasKeyProvider<T>, Focusable, HasKeyboardPagingPolicy {

  /**
   * Implementation of {@link HasDataPresenter.View} used by this widget.
   *
   * @param <T> the data type of the view
   */
  private static class View<T> implements HasDataPresenter.View<T> {

    private final AbstractHasData<T> hasData;
    private boolean wasFocused;

    public View(AbstractHasData<T> hasData) {
      this.hasData = hasData;
    }

    public <H extends EventHandler> HandlerRegistration addHandler(H handler,
        Type<H> type) {
      return hasData.addHandler(handler, type);
    }

    public boolean dependsOnSelection() {
      return hasData.dependsOnSelection();
    }

    public int getChildCount() {
      return hasData.getChildCount();
    }

    public ElementIterator getChildIterator() {
      return new HasDataPresenter.DefaultElementIterator(this,
          hasData.getChildContainer().getFirstChildElement());
    }

    public void onUpdateSelection() {
      hasData.onUpdateSelection();
    }

    public void render(SafeHtmlBuilder sb, List<T> values, int start,
        SelectionModel<? super T> selectionModel) {
      hasData.renderRowValues(sb, values, start, selectionModel);
    }

    public void replaceAllChildren(List<T> values, SafeHtml html) {
      // Removing elements can fire a blur event, which we ignore.
      wasFocused = hasData.isFocused;
      hasData.isRefreshing = true;
      hasData.replaceAllChildren(values, html);
      hasData.isRefreshing = false;
      fireValueChangeEvent();
    }

    public void replaceChildren(List<T> values, int start, SafeHtml html) {
      // Removing elements can fire a blur event, which we ignore.
      wasFocused = hasData.isFocused;
      hasData.isRefreshing = true;
      hasData.replaceChildren(values, start, html);
      hasData.isRefreshing = false;
      fireValueChangeEvent();
    }

    public void resetFocus() {
      if (wasFocused) {
        CellBasedWidgetImpl.get().resetFocus(new Scheduler.ScheduledCommand() {
          public void execute() {
            if (!hasData.resetFocusOnCell()) {
              Element elem = hasData.getKeyboardSelectedElement();
              if (elem != null) {
                elem.focus();
              }
            }
          }
        });
      }
    }

    public void setKeyboardSelected(int index, boolean seleted,
        boolean stealFocus) {
      hasData.setKeyboardSelected(index, seleted, stealFocus);
    }

    public void setLoadingState(LoadingState state) {
      hasData.isRefreshing = true;
      hasData.setLoadingState(state);
      hasData.isRefreshing = false;
    }

    public void setSelected(Element elem, boolean selected) {
      hasData.setSelected(elem, selected);
    }

    /**
     * Fire a value change event.
     */
    private void fireValueChangeEvent() {
      // Use an anonymous class to override ValueChangeEvents's protected
      // constructor. We can't call ValueChangeEvent.fire() because this class
      // doesn't implement HasValueChangeHandlers.
      hasData.fireEvent(new ValueChangeEvent<List<T>>(
          hasData.getDisplayedItems()) {
      });
    }
  }

  /**
   * The temporary element use to convert HTML to DOM.
   */
  private static com.google.gwt.user.client.Element tmpElem;

  /**
   * Convenience method to convert the specified HTML into DOM elements and
   * return the parent of the DOM elements.
   *
   * @param html the HTML to convert
   * @param tmpElem a temporary element
   * @return the parent element
   */
  static Element convertToElements(Widget widget,
      com.google.gwt.user.client.Element tmpElem, SafeHtml html) {
    // Attach an event listener so we can catch synchronous load events from
    // cached images.
    DOM.setEventListener(tmpElem, widget);

    tmpElem.setInnerHTML(html.asString());

    // Detach the event listener.
    DOM.setEventListener(tmpElem, null);

    return tmpElem;
  }

  /**
   * Convenience method to replace all children of a Widget.
   *
   * @param widget the widget who's contents will be replaced
   * @param childContainer the container that holds the contents
   * @param html the html to set
   */
  static void replaceAllChildren(Widget widget, Element childContainer,
      SafeHtml html) {
    // If the widget is not attached, attach an event listener so we can catch
    // synchronous load events from cached images.
    if (!widget.isAttached()) {
      DOM.setEventListener(widget.getElement(), widget);
    }

    // Render the HTML.
    childContainer.setInnerHTML(CellBasedWidgetImpl.get().processHtml(html).asString());

    // Detach the event listener.
    if (!widget.isAttached()) {
      DOM.setEventListener(widget.getElement(), null);
    }
  }

  /**
   * Convenience method to convert the specified HTML into DOM elements and
   * replace the existing elements starting at the specified index. If the
   * number of children specified exceeds the existing number of children, the
   * remaining children should be appended.
   *
   * @param widget the widget who's contents will be replaced
   * @param childContainer the container that holds the contents
   * @param newChildren an element containing the new children
   * @param start the start index to replace
   * @param html the HTML to convert
   */
  static void replaceChildren(Widget widget, Element childContainer,
      Element newChildren, int start, SafeHtml html) {
    // Get the first element to be replaced.
    int childCount = childContainer.getChildCount();
    Element toReplace = null;
    if (start < childCount) {
      toReplace = childContainer.getChild(start).cast();
    }

    // Replace the elements.
    int count = newChildren.getChildCount();
    for (int i = 0; i < count; i++) {
      if (toReplace == null) {
        // The child will be removed from tmpElem, so always use index 0.
        childContainer.appendChild(newChildren.getChild(0));
      } else {
        Element nextSibling = toReplace.getNextSiblingElement();
        childContainer.replaceChild(newChildren.getChild(0), toReplace);
        toReplace = nextSibling;
      }
    }
  }

  /**
   * Return the temporary element used to create elements.
   */
  private static com.google.gwt.user.client.Element getTmpElem() {
    if (tmpElem == null) {
      tmpElem = Document.get().createDivElement().cast();
    }
    return tmpElem;
  }

  /**
   * A boolean indicating that the widget has focus.
   */
  boolean isFocused;

  private char accessKey = 0;

  /**
   * A boolean indicating that the widget is refreshing, so all events should be
   * ignored.
   */
  private boolean isRefreshing;

  private final HasDataPresenter<T> presenter;
  private int tabIndex;

  /**
   * Constructs an {@link AbstractHasData} with the given page size.
   *
   * @param pageSize the page size
   */
  public AbstractHasData(Element elem, final int pageSize,
      final ProvidesKey<T> keyProvider) {
    setElement(elem);
    this.presenter = new HasDataPresenter<T>(this, new View<T>(this), pageSize,
        keyProvider);

    // Sink events.
    Set<String> eventTypes = new HashSet<String>();
    eventTypes.add("focus");
    eventTypes.add("blur");
    eventTypes.add("keydown");
    eventTypes.add("mousedown"); // Used by subclasses to steal focus.
    CellBasedWidgetImpl.get().sinkEvents(this, eventTypes);
  }

  public HandlerRegistration addRangeChangeHandler(
      RangeChangeEvent.Handler handler) {
    return presenter.addRangeChangeHandler(handler);
  }

  public HandlerRegistration addRowCountChangeHandler(
      RowCountChangeEvent.Handler handler) {
    return presenter.addRowCountChangeHandler(handler);
  }

  /**
   * Get the access key.
   *
   * @return the access key, or -1 if not set
   */
  public char getAccessKey() {
    return accessKey;
  }

  /**
   * Get the row value at the specified visible index. Index 0 corresponds to
   * the first item on the page.
   *
   * @param indexOnPage the index on the page
   * @return the row value
   */
  public T getDisplayedItem(int indexOnPage) {
    checkRowBounds(indexOnPage);
    return presenter.getRowData().get(indexOnPage);
  }

  /**
   * Get the row values that the widget is currently displaying.
   */
  public List<T> getDisplayedItems() {
    return new ArrayList<T>(presenter.getRowData());
  }

  public KeyboardPagingPolicy getKeyboardPagingPolicy() {
    return presenter.getKeyboardPagingPolicy();
  }

  public KeyboardSelectionPolicy getKeyboardSelectionPolicy() {
    return presenter.getKeyboardSelectionPolicy();
  }

  public ProvidesKey<T> getKeyProvider() {
    return presenter.getKeyProvider();
  }

  /**
   * Return the range size.
   * @see #getVisibleRange()
   */
  public final int getPageSize() {
    return getVisibleRange().getLength();
  }

  /**
   * Return the range start.
   * @see #getVisibleRange()
   */
  public final int getPageStart() {
    return getVisibleRange().getStart();
  }

  public int getRowCount() {
    return presenter.getRowCount();
  }

  public SelectionModel<? super T> getSelectionModel() {
    return presenter.getSelectionModel();
  }

  public int getTabIndex() {
    return tabIndex;
  }

  public Range getVisibleRange() {
    return presenter.getVisibleRange();
  }

  public boolean isRowCountExact() {
    return presenter.isRowCountExact();
  }

  /**
   * Handle browser events. Subclasses should override
   * {@link #onBrowserEvent2(Event)} if they want to extend browser event
   * handling.
   *
   * @see #onBrowserEvent2(Event)
   */
  @Override
  public final void onBrowserEvent(Event event) {
    CellBasedWidgetImpl.get().onBrowserEvent(this, event);

    // Ignore spurious events (such as onblur) while we refresh the table.
    if (isRefreshing) {
      return;
    }

    // Verify that the target is still a child of this widget. IE fires focus
    // events even after the element has been removed from the DOM.
    EventTarget eventTarget = event.getEventTarget();
    if (!Element.is(eventTarget)
        || !getElement().isOrHasChild(Element.as(eventTarget))) {
      return;
    }
    super.onBrowserEvent(event);

    String eventType = event.getType();
    if ("focus".equals(eventType)) {
      // Remember the focus state.
      isFocused = true;
      onFocus();
    } else if ("blur".equals(eventType)) {
      // Remember the blur state.
      isFocused = false;
      onBlur();
    } else if ("keydown".equals(eventType) && !isKeyboardNavigationSuppressed()) {
      // A key event indicates that we have focus.
      isFocused = true;

      // Handle keyboard navigation. Prevent default on navigation events to
      // prevent default scrollbar behavior.
      int keyCode = event.getKeyCode();
      switch (keyCode) {
        case KeyCodes.KEY_DOWN:
          presenter.keyboardNext();
          event.preventDefault();
          return;
        case KeyCodes.KEY_UP:
          presenter.keyboardPrev();
          event.preventDefault();
          return;
        case KeyCodes.KEY_PAGEDOWN:
          presenter.keyboardNextPage();
          event.preventDefault();
          return;
        case KeyCodes.KEY_PAGEUP:
          presenter.keyboardPrevPage();
          event.preventDefault();
          return;
        case KeyCodes.KEY_HOME:
          presenter.keyboardHome();
          event.preventDefault();
          return;
        case KeyCodes.KEY_END:
          presenter.keyboardEnd();
          event.preventDefault();
          return;
        case 32:
          // Select the node on space.
          presenter.keyboardToggleSelect();
          event.preventDefault();
          return;
      }
    }

    // Let subclasses handle the event now.
    onBrowserEvent2(event);
  }

  /**
   * Redraw the widget using the existing data.
   */
  public void redraw() {
    presenter.redraw();
  }

  public void setAccessKey(char key) {
    this.accessKey = key;
    setKeyboardSelected(getKeyboardSelectedRow(), true, false);
  }

  public void setFocus(boolean focused) {
    Element elem = getKeyboardSelectedElement();
    if (elem != null) {
      if (focused) {
        elem.focus();
      } else {
        elem.blur();
      }
    }
  }

  public void setKeyboardPagingPolicy(KeyboardPagingPolicy policy) {
    presenter.setKeyboardPagingPolicy(policy);
  }

  public void setKeyboardSelectionPolicy(KeyboardSelectionPolicy policy) {
    presenter.setKeyboardSelectionPolicy(policy);
  }

  /**
   * Set the number of rows per page and refresh the view.
   *
   * @param pageSize the page size
   * @see #setVisibleRange(Range)
   */
  public final void setPageSize(int pageSize) {
    setVisibleRange(getPageStart(), pageSize);
  }

  /**
   * Set the starting index of the current visible page. The actual page start
   * will be clamped in the range [0, getSize() - 1].
   *
   * @param pageStart the index of the row that should appear at the start of
   *          the page
   * @see #setVisibleRange(Range)
   */
  public final void setPageStart(int pageStart) {
    setVisibleRange(pageStart, getPageSize());
  }

  public final void setRowCount(int count) {
    setRowCount(count, true);
  }

  public void setRowCount(int size, boolean isExact) {
    presenter.setRowCount(size, isExact);
  }

  public void setRowData(int start, List<T> values) {
    presenter.setRowData(start, values);
  }

  public void setSelectionModel(SelectionModel<? super T> selectionModel) {
    presenter.setSelectionModel(selectionModel);
  }

  public void setTabIndex(int index) {
    this.tabIndex = index;
    setKeyboardSelected(getKeyboardSelectedRow(), true, false);
  }

  public final void setVisibleRange(int start, int length) {
    setVisibleRange(new Range(start, length));
  }

  public void setVisibleRange(Range range) {
    presenter.setVisibleRange(range);
  }

  public void setVisibleRangeAndClearData(Range range,
      boolean forceRangeChangeEvent) {
    presenter.setVisibleRangeAndClearData(range, forceRangeChangeEvent);
  }

  /**
   * Check if a cell consumes the specified event type.
   *
   * @param cell the cell
   * @param eventType the event type to check
   * @return true if consumed, false if not
   */
  protected boolean cellConsumesEventType(Cell<?> cell, String eventType) {
    Set<String> consumedEvents = cell.getConsumedEvents();
    return consumedEvents != null && consumedEvents.contains(eventType);
  }

  /**
   * Check that the row is within the correct bounds.
   *
   * @param row row index to check
   * @throws IndexOutOfBoundsException
   */
  protected void checkRowBounds(int row) {
    if (!isRowWithinBounds(row)) {
      throw new IndexOutOfBoundsException("Row index: " + row + ", Row size: "
          + getRowCount());
    }
  }

  /**
   * Convert the specified HTML into DOM elements and return the parent of the
   * DOM elements.
   *
   * @param html the HTML to convert
   * @return the parent element
   */
  protected Element convertToElements(SafeHtml html) {
    return convertToElements(this, getTmpElem(), html);
  }

  /**
   * Check whether or not the cells in the view depend on the selection state.
   *
   * @return true if cells depend on selection, false if not
   */
  protected abstract boolean dependsOnSelection();

  /**
   * Return the element that holds the rendered cells.
   */
  protected abstract Element getChildContainer();

  /**
   * Get the element that has keyboard selection.
   *
   * @return the keyboard selected element
   */
  protected abstract Element getKeyboardSelectedElement();

  /**
   * Get the row index of the keyboard selected row.
   *
   * @return the row index
   */
  protected int getKeyboardSelectedRow() {
    return presenter.getKeyboardSelectedRow();
  }

  /**
   * Get the key for the specified value.
   *
   * @param value the value
   * @return the key
   */
  protected Object getValueKey(T value) {
    ProvidesKey<T> keyProvider = getKeyProvider();
    return keyProvider == null ? value : keyProvider.getKey(value);
  }

  /**
   * Check if keyboard navigation is being suppressed, such as when the user is
   * editing a cell.
   *
   * @return true if suppressed, false if not
   */
  protected abstract boolean isKeyboardNavigationSuppressed();

  /**
   * Checks that the row is within the correct bounds.
   *
   * @param row row index to check
   * @return true if within bounds, false if not
   */
  protected boolean isRowWithinBounds(int row) {
    return row >= 0 && row < getChildCount()
        && row < presenter.getRowData().size();
  }

  /**
   * Called when the widget is blurred.
   */
  protected void onBlur() {
  }

  /**
   * Called after {@link #onBrowserEvent(Event)} completes.
   *
   * @param event the event that was fired
   */
  protected void onBrowserEvent2(Event event) {
  }

  /**
   * Called when the widget is focused.
   */
  protected void onFocus() {
  }

  @Override
  protected void onUnload() {
    isFocused = false;
    super.onUnload();
  }

  /**
   * Called when selection changes.
   */
  protected void onUpdateSelection() {
  }

  /**
   * Render all row values into the specified {@link SafeHtmlBuilder}.
   *
   * @param sb the {@link SafeHtmlBuilder} to render into
   * @param values the row values
   * @param start the start index of the values
   * @param selectionModel the {@link SelectionModel}
   */
  protected abstract void renderRowValues(SafeHtmlBuilder sb, List<T> values,
      int start, SelectionModel<? super T> selectionModel);

  /**
   * Replace all children with the specified html.
   *
   * @param values the values of the new children
   * @param html the html to render in the child
   */
  protected void replaceAllChildren(List<T> values, SafeHtml html) {
    replaceAllChildren(this, getChildContainer(), html);
  }

  /**
   * Convert the specified HTML into DOM elements and replace the existing
   * elements starting at the specified index. If the number of children
   * specified exceeds the existing number of children, the remaining children
   * should be appended.
   *
   * @param values the values of the new children
   * @param start the start index to be replaced
   * @param html the HTML to convert
   */
  protected void replaceChildren(List<T> values, int start, SafeHtml html) {
    Element newChildren = convertToElements(html);
    replaceChildren(this, getChildContainer(), newChildren, start, html);
  }

  /**
   * Reset focus on the currently focused cell.
   *
   * @return true if focus is taken, false if not
   */
  protected abstract boolean resetFocusOnCell();

  /**
   * Make an element focusable or not.
   *
   * @param elem the element
   * @param focusable true to make focusable, false to make unfocusable
   */
  protected void setFocusable(Element elem, boolean focusable) {
    if (focusable) {
      FocusImpl focusImpl = FocusImpl.getFocusImplForWidget();
      com.google.gwt.user.client.Element rowElem = elem.cast();
      focusImpl.setTabIndex(rowElem, getTabIndex());
      if (accessKey != 0) {
        focusImpl.setAccessKey(rowElem, accessKey);
      }
    } else {
      // Chrome: Elements remain focusable after removing the tabIndex, so set
      // it to -1 first.
      elem.setTabIndex(-1);
      elem.removeAttribute("tabIndex");
      elem.removeAttribute("accessKey");
    }
  }

  /**
   * Update an element to reflect its keyboard selected state.
   *
   * @param index the index of the element
   * @param selected true if selected, false if not
   * @param stealFocus true if the row should steal focus, false if not
   */
  protected abstract void setKeyboardSelected(int index, boolean selected,
      boolean stealFocus);

  /**
   * Update an element to reflect its selected state.
   *
   * @param elem the element to update
   * @param selected true if selected, false if not
   */
  protected abstract void setSelected(Element elem, boolean selected);

  /**
   * Add a {@link ValueChangeHandler} that is called when the display values
   * change. Used by {@link CellBrowser} to detect when the displayed data
   * changes.
   *
   * @param handler the handler
   * @return a {@link HandlerRegistration} to remove the handler
   */
  final HandlerRegistration addValueChangeHandler(
      ValueChangeHandler<List<T>> handler) {
    return addHandler(handler, ValueChangeEvent.getType());
  }

  /**
   * Return the number of child elements.
   */
  int getChildCount() {
    return getChildContainer().getChildCount();
  }

  HasDataPresenter<T> getPresenter() {
    return presenter;
  }

  /**
   * Get the first index of a displayed item according to its key.
   *
   * @param value the value
   * @return the index of the item, or -1 of not found
   */
  int indexOf(T value) {
    ProvidesKey<T> keyProvider = getKeyProvider();
    List<T> items = getDisplayedItems();

    // If no key provider is present, just compare the objets.
    if (keyProvider == null) {
      return items.indexOf(value);
    }

    // Compare the keys of each object.
    Object key = keyProvider.getKey(value);
    if (key == null) {
      return -1;
    }
    int itemCount = items.size();
    for (int i = 0; i < itemCount; i++) {
      if (key.equals(keyProvider.getKey(items.get(i)))) {
        return i;
      }
    }
    return -1;
  }

  /**
   * Set the current loading state of the data.
   *
   * @param state the loading state
   */
  void setLoadingState(LoadingState state) {
  }
}
