package com.google.gwt.user.client.ui;

import java.util.ArrayList;
import java.util.Collection;

import com.google.gwt.user.client.rpc.IsSerializable;

public abstract class ValueSuggestOracle<T> {
  private final ValueResponse<T> emptyResponse = new ValueResponse<T>(
      new ArrayList<ValueSuggestion<T>>());

  public interface ValueCallback<T> {
    void onSuggestionsReady(ValueRequest request, ValueResponse<T> response);
  }

  public static class ValueRequest implements IsSerializable {
    private int limit = 20;
    private String query;

    public ValueRequest() {
    }

    public ValueRequest(final String query) {
      setQuery(query);
    }

    public ValueRequest(final String query, final int limit) {
      setQuery(query);
      setLimit(limit);
    }

    public int getLimit() {
      return limit;
    }

    public String getQuery() {
      return query;
    }

    public void setLimit(final int limit) {
      this.limit = limit;
    }

    public void setQuery(final String query) {
      this.query = query;
    }
  }

  public static class ValueResponse<T> implements IsSerializable {
    private Collection<? extends ValueSuggestion<T>> suggestions;

    private boolean moreSuggestions = false;

    private int numMoreSuggestions = 0;

    public ValueResponse() {
    }

    public ValueResponse(final Collection<? extends ValueSuggestion<T>> suggestions) {
      setSuggestions(suggestions);
    }

    public int getMoreSuggestionsCount() {
      return this.numMoreSuggestions;
    }

    public Collection<? extends ValueSuggestion<T>> getSuggestions() {
      return this.suggestions;
    }

    public boolean hasMoreSuggestions() {
      return this.moreSuggestions;
    }

    public void setMoreSuggestions(final boolean moreSuggestions) {
      this.moreSuggestions = moreSuggestions;
    }

    public void setMoreSuggestionsCount(final int count) {
      this.numMoreSuggestions = count;
      this.moreSuggestions = (count > 0);
    }

    public void setSuggestions(final Collection<? extends ValueSuggestion<T>> suggestions) {
      this.suggestions = suggestions;
    }
  }
  public interface ValueSuggestion<T> {

    String getDisplayString();

    T getReplacementValue();
  }

  public ValueSuggestOracle() {

  }

  public boolean isDisplayStringHTML() {
    return false;
  }

  public void requestDefaultSuggestions(final ValueRequest request, final ValueCallback<T> callback) {
    assert (request.query == null);
    callback.onSuggestionsReady(request, emptyResponse);
  }

  public abstract void requestSuggestions(ValueRequest request, ValueCallback<T> callback);
}
