/*
 * Copyright 2007 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.safehtml.shared.SafeHtmlBuilder;
import com.google.gwt.user.client.rpc.IsSerializable;

import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Set;

/**
 * The default {@link com.google.gwt.user.client.ui.SuggestOracle}. The default
 * oracle returns potential suggestions based on breaking the query into
 * separate words and looking for matches. It also modifies the returned text to
 * show which prefix matched the query term. The matching is case insensitive.
 * All suggestions are sorted before being passed into a response.
 * <p>
 * Example Table
 * </p>
 * <p>
 * <table width = "100%" border = "1">
 * <tr>
 * <td><b> All Suggestions </b></td>
 * <td><b>Query string</b></td>
 * <td><b>Matching Suggestions</b></td>
 * </tr>
 * <tr>
 * <td>John Smith, Joe Brown, Jane Doe, Jane Smith, Bob Jones</td>
 * <td>Jo</td>
 * <td>John Smith, Joe Brown, Bob Jones</td>
 * </tr>
 * <tr>
 * <td>John Smith, Joe Brown, Jane Doe, Jane Smith, Bob Jones</td>
 * <td>Smith</td>
 * <td>John Smith, Jane Smith</td>
 * </tr>
 * <tr>
 * <td>Georgia, New York, California</td>
 * <td>g</td>
 * <td>Georgia</td>
 * </tr>
 * </table>
 * </p>
 */
public class MultiWordSuggestOracle extends SuggestOracle {

  /**
   * Suggestion class for {@link MultiWordSuggestOracle}.
   */
  public static class MultiWordSuggestion implements Suggestion, IsSerializable {
    private String displayString;
    private String replacementString;

    /**
     * Constructor used by RPC.
     */
    public MultiWordSuggestion() {
    }

    /**
     * Constructor for <code>MultiWordSuggestion</code>.
     * 
     * @param replacementString the string to enter into the SuggestBox's text
     *          box if the suggestion is chosen
     * @param displayString the display string
     */
    public MultiWordSuggestion(String replacementString, String displayString) {
      this.replacementString = replacementString;
      this.displayString = displayString;
    }

    public String getDisplayString() {
      return displayString;
    }

    public String getReplacementString() {
      return replacementString;
    }
  }

  /**
   * A class reresenting the bounds of a word within a string. 
   * 
   * The bounds are represented by a {@code startIndex} (inclusive) and
   * an {@code endIndex} (exclusive).
   */
  private static class WordBounds implements Comparable<WordBounds> {
  
    final int startIndex;
    final int endIndex;
    
    public WordBounds(int startIndex, int length) {
      this.startIndex = startIndex;
      this.endIndex = startIndex + length;
    }
    
    public int compareTo(WordBounds that) {
      int comparison = this.startIndex - that.startIndex;
      if (comparison == 0) {
        comparison = that.endIndex - this.endIndex;
      }
      return comparison;
    }
  }
  
  private static final char WHITESPACE_CHAR = ' ';
  private static final String WHITESPACE_STRING = " ";

  /**
   * Regular expression used to collapse all whitespace in a query string.
   */
  private static final String NORMALIZE_TO_SINGLE_WHITE_SPACE = "\\s+";

  /**
   * Associates substrings with words.
   */
  private final PrefixTree tree = new PrefixTree();

  /**
   * Associates individual words with candidates.
   */
  private HashMap<String, Set<String>> toCandidates = new HashMap<String, Set<String>>();

  /**
   * Associates candidates with their formatted suggestions.
   */
  private HashMap<String, String> toRealSuggestions = new HashMap<String, String>();

  /**
   * The whitespace masks used to prevent matching and replacing of the given
   * substrings.
   */
  private char[] whitespaceChars;

  private Response defaultResponse;

  /**
   * Constructor for <code>MultiWordSuggestOracle</code>. This uses a space as
   * the whitespace character.
   * 
   * @see #MultiWordSuggestOracle(String)
   */
  public MultiWordSuggestOracle() {
    this(" ");
  }

  /**
   * Constructor for <code>MultiWordSuggestOracle</code> which takes in a set of
   * whitespace chars that filter its input.
   * <p>
   * Example: If <code>".,"</code> is passed in as whitespace, then the string
   * "foo.bar" would match the queries "foo", "bar", "foo.bar", "foo...bar", and
   * "foo, bar". If the empty string is used, then all characters are used in
   * matching. For example, the query "bar" would match "bar", but not "foo
   * bar".
   * </p>
   * 
   * @param whitespaceChars the characters to treat as word separators
   */
  public MultiWordSuggestOracle(String whitespaceChars) {
    this.whitespaceChars = new char[whitespaceChars.length()];
    for (int i = 0; i < whitespaceChars.length(); i++) {
      this.whitespaceChars[i] = whitespaceChars.charAt(i);
    }
  }

  /**
   * Adds a suggestion to the oracle. Each suggestion must be plain text.
   * 
   * @param suggestion the suggestion
   */
  public void add(String suggestion) {
    String candidate = normalizeSuggestion(suggestion);
    // candidates --> real suggestions.
    toRealSuggestions.put(candidate, suggestion);

    // word fragments --> candidates.
    String[] words = candidate.split(WHITESPACE_STRING);
    for (int i = 0; i < words.length; i++) {
      String word = words[i];
      tree.add(word);
      Set<String> l = toCandidates.get(word);
      if (l == null) {
        l = new HashSet<String>();
        toCandidates.put(word, l);
      }
      l.add(candidate);
    }
  }

  /**
   * Adds all suggestions specified. Each suggestion must be plain text.
   * 
   * @param collection the collection
   */
  public final void addAll(Collection<String> collection) {
    for (String suggestion : collection) {
      add(suggestion);
    }
  }

  /**
   * Removes all of the suggestions from the oracle.
   */
  public void clear() {
    tree.clear();
    toCandidates.clear();
    toRealSuggestions.clear();
  }

  @Override
  public boolean isDisplayStringHTML() {
    return true;
  }

  @Override
  public void requestDefaultSuggestions(Request request, Callback callback) {
    if (defaultResponse != null) {
      callback.onSuggestionsReady(request, defaultResponse);
    } else {
      super.requestDefaultSuggestions(request, callback);
    }
  }

  @Override
  public void requestSuggestions(Request request, Callback callback) {
    String query = normalizeSearch(request.getQuery());
    int limit = request.getLimit();

    // Get candidates from search words.
    List<String> candidates = createCandidatesFromSearch(query);

    // Respect limit for number of choices.
    int numberTruncated = Math.max(0, candidates.size() - limit);
    for (int i = candidates.size() - 1; i > limit; i--) {
      candidates.remove(i);
    }

    // Convert candidates to suggestions.
    List<MultiWordSuggestion> suggestions = 
        convertToFormattedSuggestions(query, candidates);

    Response response = new Response(suggestions);
    response.setMoreSuggestionsCount(numberTruncated);

    callback.onSuggestionsReady(request, response);
  }

  /**
   * Sets the default suggestion collection.
   * 
   * @param suggestionList the default list of suggestions
   */
  public void setDefaultSuggestions(Collection<Suggestion> suggestionList) {
    this.defaultResponse = new Response(suggestionList);
  }

  /**
   * A convenience method to set default suggestions using plain text strings.
   * 
   * Note to use this method each default suggestion must be plain text.
   * 
   * @param suggestionList the default list of suggestions
   */
  public final void setDefaultSuggestionsFromText(
      Collection<String> suggestionList) {
    Collection<Suggestion> accum = new ArrayList<Suggestion>();
    for (String candidate : suggestionList) {
      accum.add(createSuggestion(candidate, candidate));
    }
    setDefaultSuggestions(accum);
  }

  /**
   * Creates the suggestion based on the given replacement and display strings.
   * 
   * @param replacementString the string to enter into the SuggestBox's text box
   *          if the suggestion is chosen
   * @param displayString the display string
   * 
   * @return the suggestion created
   */
  protected MultiWordSuggestion createSuggestion(String replacementString,
      String displayString) {
    return new MultiWordSuggestion(replacementString, displayString);
  }

  /**
   * Returns real suggestions with the given query in <code>strong</code> html
   * font.
   * 
   * @param query query string
   * @param candidates candidates
   * @return real suggestions
   */
  private List<MultiWordSuggestion> convertToFormattedSuggestions(String query,
      List<String> candidates) {
    List<MultiWordSuggestion> suggestions = new ArrayList<MultiWordSuggestion>();

    for (int i = 0; i < candidates.size(); i++) {
      String candidate = candidates.get(i);
      int cursor = 0;
      int index = 0;
      // Use real suggestion for assembly.
      String formattedSuggestion = toRealSuggestions.get(candidate);

      // Create strong search string.
      SafeHtmlBuilder accum = new SafeHtmlBuilder();
      
      String[] searchWords = query.split(WHITESPACE_STRING);
      while (true) {
        WordBounds wordBounds = findNextWord(candidate, searchWords, index);
        if (wordBounds == null) {
          break;
        }
        if (wordBounds.startIndex == 0 || 
            WHITESPACE_CHAR == candidate.charAt(wordBounds.startIndex - 1)) {
          String part1 = formattedSuggestion.substring(cursor, wordBounds.startIndex);
          String part2 = formattedSuggestion.substring(wordBounds.startIndex,
              wordBounds.endIndex);
          cursor = wordBounds.endIndex;
          accum.appendEscaped(part1);
          accum.appendHtmlConstant("<strong>");
          accum.appendEscaped(part2);
          accum.appendHtmlConstant("</strong>");
        }
        index = wordBounds.endIndex;
      }
      
      // Check to make sure the search was found in the string.
      if (cursor == 0) {
        continue;
      }
      
      accum.appendEscaped(formattedSuggestion.substring(cursor));
      MultiWordSuggestion suggestion = createSuggestion(formattedSuggestion,
          accum.toSafeHtml().asString());
      suggestions.add(suggestion);
    }
    return suggestions;
  }

  /**
   * Find the sorted list of candidates that are matches for the given query.
   */
  private List<String> createCandidatesFromSearch(String query) {
    ArrayList<String> candidates = new ArrayList<String>();

    if (query.length() == 0) {
      return candidates;
    }

    // Find all words to search for.
    String[] searchWords = query.split(WHITESPACE_STRING);
    HashSet<String> candidateSet = null;
    for (int i = 0; i < searchWords.length; i++) {
      String word = searchWords[i];

      // Eliminate bogus word choices.
      if (word.length() == 0 || word.matches(WHITESPACE_STRING)) {
        continue;
      }

      // Find the set of candidates that are associated with all the
      // searchWords.
      HashSet<String> thisWordChoices = createCandidatesFromWord(word);
      if (candidateSet == null) {
        candidateSet = thisWordChoices;
      } else {
        candidateSet.retainAll(thisWordChoices);

        if (candidateSet.size() < 2) {
          // If there is only one candidate, on average it is cheaper to
          // check if that candidate contains our search string than to
          // continue intersecting suggestion sets.
          break;
        }
      }
    }
    if (candidateSet != null) {
      candidates.addAll(candidateSet);
      Collections.sort(candidates);
    }
    return candidates;
  }

  /**
   * Creates a set of potential candidates that match the given query.
   * 
   * @param query query string
   * @return possible candidates
   */
  private HashSet<String> createCandidatesFromWord(String query) {
    HashSet<String> candidateSet = new HashSet<String>();
    List<String> words = tree.getSuggestions(query, Integer.MAX_VALUE);
    if (words != null) {
      // Find all candidates that contain the given word the search is a
      // subset of.
      for (int i = 0; i < words.size(); i++) {
        Collection<String> belongsTo = toCandidates.get(words.get(i));
        if (belongsTo != null) {
          candidateSet.addAll(belongsTo);
        }
      }
    }
    return candidateSet;
  }
  
  /**
   * @return a {@link WordBounds} representing the first word in 
   *     {@code searchWords} that is found in candidate starting at 
   *     {@code indexToStartAt} or {@code null} if no words could be found.
   */
  private WordBounds findNextWord(String candidate, String[] searchWords, int indexToStartAt) {
    WordBounds firstWord = null;
    for (String word : searchWords) {
      int index = candidate.indexOf(word, indexToStartAt);
      if (index != -1) {
        WordBounds newWord = new WordBounds(index, word.length());
        if (firstWord == null || newWord.compareTo(firstWord) < 0) {
          firstWord = newWord;
        }
      }
    }
    return firstWord;
  }
  
  /**
   * Normalize the search key by making it lower case, removing multiple spaces,
   * apply whitespace masks, and make it lower case.
   */
  private String normalizeSearch(String search) {
    // Use the same whitespace masks and case normalization for the search
    // string as was used with the candidate values.
    search = normalizeSuggestion(search);

    // Remove all excess whitespace from the search string.
    search = search.replaceAll(NORMALIZE_TO_SINGLE_WHITE_SPACE,
        WHITESPACE_STRING);

    return search.trim();
  }

  /**
   * Takes the formatted suggestion, makes it lower case and blanks out any
   * existing whitespace for searching.
   */
  private String normalizeSuggestion(String formattedSuggestion) {
    // Formatted suggestions should already have normalized whitespace. So we
    // can skip that step.

    // Lower case suggestion.
    formattedSuggestion = formattedSuggestion.toLowerCase();

    // Apply whitespace.
    if (whitespaceChars != null) {
      for (int i = 0; i < whitespaceChars.length; i++) {
        char ignore = whitespaceChars[i];
        formattedSuggestion = formattedSuggestion.replace(ignore,
            WHITESPACE_CHAR);
      }
    }
    return formattedSuggestion;
  }
}
