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

import java.util.HashMap;
import java.util.Map;

/**
 * A convenience {@link SelectionModel} that allows records to be selected
 * according to a subclass-defined rule, plus a list of positive or negative
 * exceptions.
 *
 * @param <T> the data type of records in the list
 */
public abstract class DefaultSelectionModel<T> extends AbstractSelectionModel<T> {

  private final Map<Object, Boolean> exceptions = new HashMap<Object, Boolean>();

  // Changes to be propagated into exceptions map
  private final HashMap<T, Boolean> selectionChanges = new HashMap<T, Boolean>();

  /**
   * Constructs a DefaultSelectionModel without a key provider.
   */
  public DefaultSelectionModel() {
    super(null);
  }
  
  /**
   * Constructs a DefaultSelectionModel with the given key provider.
   *
   * @param keyProvider an instance of ProvidesKey<T>, or null if the record
   *        object should act as its own key
   */
  public DefaultSelectionModel(ProvidesKey<T> keyProvider) {
    super(keyProvider);
  }
  
  /**
   * Removes all exceptions.
   */
  public void clearExceptions() {
    exceptions.clear();
    selectionChanges.clear();
    scheduleSelectionChangeEvent();
  }

  /**
   * Returns true if the given object should be selected by default. Subclasses
   * implement this method in order to define the default selection behavior.
   * 
   * @param object an object of this {@link SelectionModel}'s type
   * @return true if the object should be selected by default
   */
  public abstract boolean isDefaultSelected(T object);

  /**
   * If the given object is marked as an exception, return the exception value.
   * Otherwise, return the value of isDefaultSelected for the given object.
   */
  public boolean isSelected(T object) {
    resolveChanges();

    // Check exceptions first
    Object key = getKey(object);
    Boolean exception = exceptions.get(key);
    if (exception != null) {
      return exception.booleanValue();
    }
    // If not in exceptions, return the default
    return isDefaultSelected(object);
  }

  /**
   * Sets an object's selection state. If the object is currently marked as an
   * exception, and the new selected state differs from the previous selected
   * state, the object is removed from the list of exceptions. Otherwise, the
   * object is added to the list of exceptions with the given selected state.
   */
  public void setSelected(T object, boolean selected) {
    selectionChanges.put(object, selected);
    scheduleSelectionChangeEvent();
  }

  @Override
  protected void fireSelectionChangeEvent() {
    if (isEventScheduled()) {
      setEventCancelled(true);
    }
    resolveChanges();
  }

  /**
   * Copies the exceptions map into a user-supplied map.
   *
   * @param output the user supplied map
   * @return the user supplied map
   */
  protected Map<Object, Boolean> getExceptions(Map<Object, Boolean> output) {
    output.clear();
    output.putAll(exceptions);
    return output;
  }

  private void resolveChanges() {
    boolean changed = false;
    for (Map.Entry<T, Boolean> entry : selectionChanges.entrySet()) {
      T object = entry.getKey();
      boolean selected = entry.getValue();
      boolean defaultSelected = isDefaultSelected(object);
      Object key = getKey(object);
      Boolean previousException = exceptions.get(key);

      if (defaultSelected == selected) {
        // Not an exception, remove from exceptions table if present
        if (previousException != null) {
          exceptions.remove(key);
          changed = true;
        }
      } else {
        // Add as an exception if not already there
        if (previousException != Boolean.valueOf(selected)) {
          exceptions.put(key, selected);
          changed = true;
        }
      }
    }

    selectionChanges.clear();

    // Fire a selection change event.
    if (changed) {
      SelectionChangeEvent.fire(this);
    }
  }
}
