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

import com.google.gwt.editor.client.IsEditor;
import com.google.gwt.editor.client.adapters.TakesValueEditor;
import com.google.gwt.event.dom.client.ChangeEvent;
import com.google.gwt.event.dom.client.ChangeHandler;
import com.google.gwt.event.logical.shared.ValueChangeEvent;
import com.google.gwt.event.logical.shared.ValueChangeHandler;
import com.google.gwt.event.shared.HandlerRegistration;
import com.google.gwt.text.shared.Renderer;
import com.google.gwt.text.shared.ToStringRenderer;
import com.google.gwt.view.client.ProvidesKey;
import com.google.gwt.view.client.SimpleKeyProvider;

import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * Implementation of {@link HasConstrainedValue} based on a
 * {@link com.google.gwt.dom.client.SelectElement}.
 * <p>
 * A {@link Renderer Renderer<T>} is used to get user-presentable strings to
 * display in the select element.
 * 
 * @param <T> the value type
 */
public class ValueListBox<T> extends Composite implements
    Focusable, HasConstrainedValue<T>, HasEnabled,
    IsEditor<TakesValueEditor<T>> {

  private final List<T> values = new ArrayList<T>();
  private final Map<Object, Integer> valueKeyToIndex = new HashMap<Object, Integer>();
  private final Renderer<? super T> renderer;
  private final ProvidesKey<T> keyProvider;

  private TakesValueEditor<T> editor;
  private T value;

  public ValueListBox() {
    this(ToStringRenderer.instance());
  }

  public ValueListBox(Renderer<? super T> renderer) {
    this(renderer, new SimpleKeyProvider<T>());
  }
  
  public ValueListBox(Renderer<? super T> renderer, ProvidesKey<T> keyProvider) {
    this.keyProvider = keyProvider;
    this.renderer = renderer;
    initWidget(new ListBox());

    getListBox().addChangeHandler(new ChangeHandler() {
      public void onChange(ChangeEvent event) {
        int selectedIndex = getListBox().getSelectedIndex();

        if (selectedIndex < 0) {
          return; // Not sure why this happens during addValue
        }
        T newValue = values.get(selectedIndex);
        setValue(newValue, true);
      }
    });
  }

  public HandlerRegistration addValueChangeHandler(ValueChangeHandler<T> handler) {
    return addHandler(handler, ValueChangeEvent.getType());
  }

  /**
   * Returns a {@link TakesValueEditor} backed by the ValueListBox.
   */
  public TakesValueEditor<T> asEditor() {
    if (editor == null) {
      editor = TakesValueEditor.of(this);
    }
    return editor;
  }

  @Override
  public int getTabIndex() {
    return getListBox().getTabIndex();
  }

  public T getValue() {
    return value;
  }

  @Override
  public boolean isEnabled() {
    return getListBox().isEnabled();
  }

  public void setAcceptableValues(Collection<T> newValues) {
    values.clear();
    valueKeyToIndex.clear();
    ListBox listBox = getListBox();
    listBox.clear();

    for (T nextNewValue : newValues) {
      addValue(nextNewValue);
    }

    updateListBox();
  }

  @Override
  public void setAccessKey(char key) {
    getListBox().setAccessKey(key);
  }

  @Override
  public void setEnabled(boolean enabled) {
    getListBox().setEnabled(enabled);
  }

  @Override
  public void setFocus(boolean focused) {
    getListBox().setFocus(focused);
  }

  @Override
  public void setTabIndex (int index) {
    getListBox().setTabIndex(index);
  }

  /**
   * Set the value and display it in the select element. Add the value to the
   * acceptable set if it is not already there.
   */
  public void setValue(T value) {
    setValue(value, false);
  }

  public void setValue(T value, boolean fireEvents) {
    if (value == this.value || (this.value != null && this.value.equals(value))) {
      return;
    }

    T before = this.value;
    this.value = value;
    updateListBox();

    if (fireEvents) {
      ValueChangeEvent.fireIfNotEqual(this, before, value);
    }
  }

  private void addValue(T value) {
    Object key = keyProvider.getKey(value);
    if (valueKeyToIndex.containsKey(key)) {
      throw new IllegalArgumentException("Duplicate value: " + value);
    }

    valueKeyToIndex.put(key, values.size());
    values.add(value);
    getListBox().addItem(renderer.render(value));
    assert values.size() == getListBox().getItemCount();
  }

  private ListBox getListBox() {
    return (ListBox) getWidget();
  }

  private void updateListBox() {
    Object key = keyProvider.getKey(value);
    Integer index = valueKeyToIndex.get(key);
    if (index == null) {
      addValue(value);
    }

    index = valueKeyToIndex.get(key);
    getListBox().setSelectedIndex(index);
  }
}
