/*
 * 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.
 *
 * @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 final 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>();
  
  /**
   * Construct an AbstractDataProvider without a key provider.
   */
  protected AbstractDataProvider() {
    this.keyProvider = null;
  }
  
  /**
   * Construct an AbstractDataProvider with a given key provider.
   */
  protected AbstractDataProvider(ProvidesKey<T> keyProvider) {
    this.keyProvider = keyProvider;
  }

  /**
   * 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;
  }

  /**
   * Remove the given data display.
   * 
   * @throws IllegalStateException if the display is not present
   */
  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();
  }

  /**
   * 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);
    }
  }
}
