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

import com.google.gwt.event.shared.HandlerRegistration;

import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;

/**
 * A base implementation of a data source for {@link HasData} implementations.
 *
 * <p>
 * Note: This class is new and its interface subject to change.
 * </p>
 *
 * @param <T> the data type of records in the list
 */
public abstract class AbstractDataProvider<T> implements ProvidesKey<T> {

  private Set<HasData<T>> displays = new HashSet<HasData<T>>();

  /**
   * The provider of keys for list items.
   */
  private ProvidesKey<T> keyProvider;

  /**
   * The last row count.
   */
  private int lastRowCount = -1;

  /**
   * Indicates whether or not the last row count is exact.
   */
  private boolean lastRowCountExact;

  /**
   * A mapping of {@link HasData}s to their handlers.
   */
  private Map<HasData<T>, HandlerRegistration> rangeChangeHandlers =
      new HashMap<HasData<T>, HandlerRegistration>();

  /**
   * Adds a data display to this adapter. The current range of interest of the
   * display will be populated with data.
   *
   * @param display a {@link HasData}.
   */
  public void addDataDisplay(final HasData<T> display) {
    if (display == null) {
      throw new IllegalArgumentException("display cannot be null");
    } else if (displays.contains(display)) {
      throw new IllegalStateException(
          "The specified display has already been added to this adapter.");
    }

    // Add the display to the set.
    displays.add(display);

    // Add a handler to the display.
    HandlerRegistration handler = display.addRangeChangeHandler(
        new RangeChangeEvent.Handler() {
          public void onRangeChange(RangeChangeEvent event) {
            AbstractDataProvider.this.onRangeChanged(display);
          }
        });
    rangeChangeHandlers.put(display, handler);

    // Update the data size in the display.
    if (lastRowCount >= 0) {
      display.setRowCount(lastRowCount, lastRowCountExact);
    }

    // Initialize the display with the current range.
    onRangeChanged(display);
  }

  /**
   * Get the set of displays currently assigned to this adapter.
   *
   * @return the set of {@link HasData}
   */
  public Set<HasData<T>> getDataDisplays() {
    return Collections.unmodifiableSet(displays);
  }

  /**
   * Get the key for a list item. The default implementation returns the item
   * itself.
   *
   * @param item the list item
   * @return the key that represents the item
   */
  public Object getKey(T item) {
    return keyProvider == null ? item : keyProvider.getKey(item);
  }

  /**
   * Get the {@link ProvidesKey} that provides keys for list items.
   *
   * @return the {@link ProvidesKey}
   */
  public ProvidesKey<T> getKeyProvider() {
    return keyProvider;
  }

  /**
   * Get the current ranges of all displays.
   *
   * @return the ranges
   */
  public Range[] getRanges() {
    Range[] ranges = new Range[displays.size()];
    int i = 0;
    for (HasData<T> display : displays) {
      ranges[i++] = display.getVisibleRange();
    }
    return ranges;
  }

  public void removeDataDisplay(HasData<T> display) {
    if (!displays.contains(display)) {
      throw new IllegalStateException("HasData not present");
    }
    displays.remove(display);

    // Remove the handler.
    HandlerRegistration handler = rangeChangeHandlers.remove(display);
    handler.removeHandler();
  }

  /**
   * Set the {@link ProvidesKey} that provides keys for list items.
   *
   * @param keyProvider the {@link ProvidesKey}
   */
  public void setKeyProvider(ProvidesKey<T> keyProvider) {
    this.keyProvider = keyProvider;
  }

  /**
   * Called when a display changes its range of interest.
   *
   * @param display the display whose range has changed
   */
  protected abstract void onRangeChanged(HasData<T> display);

  /**
   * Inform the displays of the total number of items that are available.
   *
   * @param count the new total row count
   * @param exact true if the count is exact, false if it is an estimate
   */
  protected void updateRowCount(int count, boolean exact) {
    lastRowCount = count;
    lastRowCountExact = exact;

    for (HasData<T> display : displays) {
      display.setRowCount(count, exact);
    }
  }

  /**
   * Inform the displays of the new data.
   *
   * @param start the start index
   * @param values the data values
   */
  protected void updateRowData(int start, List<T> values) {
    for (HasData<T> display : displays) {
      updateRowData(display, start, values);
    }
  }

  /**
   * Informs a single display of new data.
   *
   * @param display the display to be updated
   * @param start the start index
   * @param values the data values
   */
  protected void updateRowData(HasData<T> display, int start, List<T> values) {
    int end = start + values.size();
    Range range = display.getVisibleRange();
    int curStart = range.getStart();
    int curLength = range.getLength();
    int curEnd = curStart + curLength;
    if (start == curStart || (curStart < end && curEnd > start)) {
      // Fire the handler with the data that is in the range.
      // Allow an empty list that starts on the page start.
      int realStart = curStart < start ? start : curStart;
      int realEnd = curEnd > end ? end : curEnd;
      int realLength = realEnd - realStart;
      List<T> realValues = values.subList(
          realStart - start, realStart - start + realLength);
      display.setRowData(realStart, realValues);
    }
  }
}
