/*   **********************************************************************  **
 **   Copyright notice                                                       **
 **                                                                          **
 **   (c) 2003-2006 RSSOwl Development Team                                  **
 **   http://www.rssowl.org/                                                 **
 **                                                                          **
 **   All rights reserved                                                    **
 **                                                                          **
 **   This program and the accompanying materials are made available under   **
 **   the terms of the Eclipse Public License 1.0 which accompanies this     **
 **   distribution, and is available at:                                     **
 **   http://www.rssowl.org/legal/epl-v10.html                               **
 **                                                                          **
 **   A copy is found in the file epl-v10.html and important notices to the  **
 **   license from the team is found in the textfile LICENSE.txt distributed **
 **   in this package.                                                       **
 **                                                                          **
 **   This copyright notice MUST APPEAR in all copies of the file!           **
 **                                                                          **
 **   Contributors:                                                          **
 **     RSSOwl - initial API and implementation (bpasero@rssowl.org)         **
 **                                                                          **
 **  **********************************************************************  */

package net.sourceforge.rssowl.controller.properties;

import net.sourceforge.rssowl.controller.GUI;
import net.sourceforge.rssowl.controller.thread.FeedAutoUpdater;
import net.sourceforge.rssowl.util.GlobalSettings;
import net.sourceforge.rssowl.util.i18n.Dictionary;
import net.sourceforge.rssowl.util.shop.RegExShop;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Locale;
import java.util.Set;
import java.util.regex.Pattern;

/**
 * The PropertiesFilter creates and Index over all existing Property Pages. The
 * index contains the I18N keys of most preferences. For a given Filter value, a
 * list of matching Property Pages is returned.
 * 
 * @author <a href="mailto:bpasero@rssowl.org">Benjamin Pasero </a>
 * @version 1.2.3
 */
public class PropertiesFilter {
  private HashMap index;

  /**
   * Instantiate a new PropertiesFilter.
   */
  public PropertiesFilter() {
    index = new HashMap();
    createIndex();
  }

  /**
   * Filter the Index by the given Value.
   * 
   * @param str The String to Filter the Property Pages.
   * @return ArrayList Containing all matching Property Pages
   */
  public ArrayList filter(String str) {
    Pattern pattern = createPattern(str);
    ArrayList result = new ArrayList();
    Set keySet = index.keySet();

    /** For each Property Page */
    for (Iterator iter = keySet.iterator(); iter.hasNext();) {
      Object propertyKey = iter.next();
      String propertyIndex = (String) index.get(propertyKey);

      /** Check for a Match using Reg Exp */
      if (pattern.matcher(propertyIndex).matches())
        result.add(propertyKey);
    }

    return result;
  }

  /**
   * Adds a new Value to the Index.
   * 
   * @param index A single String containing all Values.
   * @param i18nKey The Value to add as I18N Key.
   */
  private void addToIndex(StringBuffer index, String i18nKey) {
    index.append(GUI.i18n.getTranslation(i18nKey)).append(" ");
  }

  /**
   * Create the Index over all Property Pages.
   */
  private void createIndex() {

    /** General */
    String propertyKey = "MENU_WORKBENCH";

    StringBuffer propertyIndex = new StringBuffer();
    addToIndex(propertyIndex, "MENU_WORKBENCH");
    addToIndex(propertyIndex, "GROUP_OPEN_MODE");
    addToIndex(propertyIndex, "LABEL_SINGLE_CLICK");
    addToIndex(propertyIndex, "LABEL_DOUBLE_CLICK");
    addToIndex(propertyIndex, "GROUP_CONFIRM_DIALOG");
    addToIndex(propertyIndex, "BUTTON_DELETE_FAVORITE");
    addToIndex(propertyIndex, "BUTTON_DELETE_CATEGORY");
    addToIndex(propertyIndex, "BUTTON_DELETE_SUBSCRIPTION");
    addToIndex(propertyIndex, "LABEL_REOPEN_DISPLAYED_FEEDS");
    addToIndex(propertyIndex, "BUTTON_CACHE_FEEDS");
    addToIndex(propertyIndex, "BUTTON_READ_ON_CLOSE");
    addToIndex(propertyIndex, "BUTTON_READ_ON_MINIMIZE");
    addToIndex(propertyIndex, "MENU_DIRECTOPEN");
    addToIndex(propertyIndex, "MENU_DIRECTOPENEACH");
    addToIndex(propertyIndex, "MENU_CHECK_UPDATE");

    index.put(propertyKey, propertyIndex.toString());

    /** Colors */
    propertyKey = "MENU_COLORS";

    propertyIndex = new StringBuffer();
    addToIndex(propertyIndex, "MENU_COLORS");
    addToIndex(propertyIndex, "GROUP_LINK_COLOR");
    addToIndex(propertyIndex, "GROUP_SYNTAXHIGHLIGHT_COLOR");
    addToIndex(propertyIndex, "LABEL_CURRENT_COLOR");

    index.put(propertyKey, propertyIndex.toString());

    /** Font */
    propertyKey = "MENU_FONT";

    propertyIndex = new StringBuffer();
    addToIndex(propertyIndex, "MENU_FONT");
    addToIndex(propertyIndex, "FONT_AREA_TEXT");
    addToIndex(propertyIndex, "FONT_AREA_DIALOG");
    addToIndex(propertyIndex, "FONT_AREA_TREE");
    addToIndex(propertyIndex, "FONT_AREA_TABLE");
    addToIndex(propertyIndex, "FONT_AREA_HEADER");
    addToIndex(propertyIndex, "GROUP_SELECTED_FONT");
    addToIndex(propertyIndex, "LABEL_SIZE");
    addToIndex(propertyIndex, "LABEL_STYLE");
    addToIndex(propertyIndex, "LABEL_USE_SYSTEM_FONT");
    addToIndex(propertyIndex, "MENU_ENCODING");

    index.put(propertyKey, propertyIndex.toString());

    /** Hotkeys */
    propertyKey = "MENU_HOTKEYS";

    propertyIndex = new StringBuffer();
    addToIndex(propertyIndex, "MENU_HOTKEYS");
    addToIndex(propertyIndex, "GROUP_COMMAND");
    addToIndex(propertyIndex, "LABEL_KEY_SEQUENCE");
    addToIndex(propertyIndex, "BUTTON_ASSIGN");

    index.put(propertyKey, propertyIndex.toString());

    /** Language */
    propertyKey = "MENU_LANGUAGE";

    propertyIndex = new StringBuffer();
    addToIndex(propertyIndex, "MENU_LANGUAGE");

    /* Add all supported Languages */
    for (int a = 0; a < Dictionary.languages.size(); a++) {
      Locale locale = (Locale) Dictionary.locales.get(Dictionary.languages.get(a));
      addToIndex(propertyIndex, locale.getLanguage());
    }

    index.put(propertyKey, propertyIndex.toString());

    /** News Sorting */
    propertyKey = "LABEL_SORT_ORDER";

    propertyIndex = new StringBuffer();
    addToIndex(propertyIndex, "LABEL_SORT_ORDER");
    addToIndex(propertyIndex, "LABEL_SORT_EXPLANATION");
    addToIndex(propertyIndex, "BUTTON_NO_SORT");

    /* Add all Sort Fields */
    for (int a = 0; a < GlobalSettings.sortOrder.size(); a++)
      addToIndex(propertyIndex, (String) GlobalSettings.sortOrder.get(a));

    index.put(propertyKey, propertyIndex.toString());

    /** View */
    propertyKey = "MENU_WINDOW";

    propertyIndex = new StringBuffer();
    addToIndex(propertyIndex, "MENU_WINDOW");
    addToIndex(propertyIndex, "GROUP_WINDOW_LAYOUT");
    addToIndex(propertyIndex, "GROUP_TAB_LAYOUT");
    addToIndex(propertyIndex, "LABEL_TRADITIONAL_TABS");
    addToIndex(propertyIndex, "LABEL_CURVED_TABS");
    addToIndex(propertyIndex, "BUTTON_DISPLAY_TABS");
    addToIndex(propertyIndex, "BUTTON_FOCUS_TABS");
    addToIndex(propertyIndex, "BUTTON_SHOW_TAB_CLOSE");
    addToIndex(propertyIndex, "MENU_CHANNELINFO");
    addToIndex(propertyIndex, "BUTTON_SHOW_ERRORS");

    if (GlobalSettings.useInternalBrowser())
      addToIndex(propertyIndex, "MENU_BROWSER_FOR_NEWSTEXT");

    index.put(propertyKey, propertyIndex.toString());

    /** System Tray */
    if (GlobalSettings.useSystemTray()) {
      propertyKey = "GROUP_TRAY";

      propertyIndex = new StringBuffer();
      addToIndex(propertyIndex, "GROUP_TRAY");
      addToIndex(propertyIndex, "MENU_SYSTRAY");
      addToIndex(propertyIndex, "BUTTON_TRAY_STARTUP");
      addToIndex(propertyIndex, "BUTTON_TRAY_EXIT");
      addToIndex(propertyIndex, "GROUP_NEWS_POPUP");
      addToIndex(propertyIndex, "BUTTON_TRAY_POPUP");
      addToIndex(propertyIndex, "BUTTON_ANIMATE_POPUP");
      addToIndex(propertyIndex, "BUTTON_AUTOCLOSE_POPUP");

      index.put(propertyKey, propertyIndex.toString());
    }

    /** AmphetaRate */
    /*
     * propertyKey = "AmphetaRate"; propertyIndex = new StringBuffer();
     * addToIndex(propertyIndex, "AmphetaRate"); addToIndex(propertyIndex,
     * "GROUP_EXISTING_ACCOUNT"); addToIndex(propertyIndex,
     * "GROUP_NEW_ACCOUNT"); addToIndex(propertyIndex, "LABEL_USERNAME");
     * addToIndex(propertyIndex, "LABEL_PASSWORD"); addToIndex(propertyIndex,
     * "LABEL_OLD_ID"); addToIndex(propertyIndex, "BUTTON_CREATE_ACCOUNT");
     * index.put(propertyKey, propertyIndex.toString());
     */

    /** Blogger */
    propertyKey = "MENU_BLOGGER";

    propertyIndex = new StringBuffer();
    addToIndex(propertyIndex, "MENU_BLOGGER");
    addToIndex(propertyIndex, "LABEL_SELECT_BLOGGER");
    addToIndex(propertyIndex, "DIALOG_SELECT_EXTERNAL_BROWSER");
    addToIndex(propertyIndex, "GROUP_ARGUMENTS");

    index.put(propertyKey, propertyIndex.toString());

    /** Browser */
    propertyKey = "MENU_BROWSER";

    propertyIndex = new StringBuffer();
    addToIndex(propertyIndex, "MENU_BROWSER");
    addToIndex(propertyIndex, "MENU_SELECT_EXTERNAL_BROWSER");
    addToIndex(propertyIndex, "DIALOG_SELECT_EXTERNAL_BROWSER");
    addToIndex(propertyIndex, "GROUP_ARGUMENTS");
    addToIndex(propertyIndex, "MENU_OPENNEW_BROWSER");
    addToIndex(propertyIndex, "MENU_BROWSER_EXTERN");

    if (!GlobalSettings.isLinux())
      addToIndex(propertyIndex, "BUTTON_BLOCK_POPUPS");

    index.put(propertyKey, propertyIndex.toString());

    /** Favorites */
    propertyKey = "HEADER_RSS_FAVORITES";

    propertyIndex = new StringBuffer();
    addToIndex(propertyIndex, "HEADER_RSS_FAVORITES");
    addToIndex(propertyIndex, "LABEL_TEMPLATE_EXPLANATION");
    addToIndex(propertyIndex, "POP_AUTO_UPDATE");
    addToIndex(propertyIndex, "POP_UPDATE_ONSTARTUP");
    addToIndex(propertyIndex, "POP_OPEN_STARTUP");

    /* Add all supported Update Intervals */
    for (int a = 0; a < FeedAutoUpdater.updateIntervalNames.length; a++)
      addToIndex(propertyIndex, FeedAutoUpdater.updateIntervalNames[a]);

    index.put(propertyKey, propertyIndex.toString());

    /** Format NewsTip */
    propertyKey = "MENU_NEWSTIP_MAIL";

    propertyIndex = new StringBuffer();
    addToIndex(propertyIndex, "MENU_NEWSTIP_MAIL");
    addToIndex(propertyIndex, "LABEL_MAIL_SUBJECT");
    addToIndex(propertyIndex, "LABEL_MAIL_BODY");
    addToIndex(propertyIndex, "LABEL_HTML_FORMAT_MAIL");

    index.put(propertyKey, propertyIndex.toString());

    /** Connection */
    propertyKey = "MENU_CONNECTION";

    propertyIndex = new StringBuffer();
    addToIndex(propertyIndex, "MENU_CONNECTION");
    addToIndex(propertyIndex, "MENU_PROXY");
    addToIndex(propertyIndex, "LABEL_USE_PROXY");
    addToIndex(propertyIndex, "LABEL_PROXY_HOST");
    addToIndex(propertyIndex, "LABEL_PROXY_PORT");
    addToIndex(propertyIndex, "LABEL_PROXY_AUTHENTIFICATION");
    addToIndex(propertyIndex, "LABEL_USERNAME");
    addToIndex(propertyIndex, "LABEL_PASSWORD");
    addToIndex(propertyIndex, "LABEL_DOMAIN");
    addToIndex(propertyIndex, "LABEL_USE_PROXY_FOR_ALL");
    addToIndex(propertyIndex, "LABEL_MAX_CONNECTIONS");
    addToIndex(propertyIndex, "LABEL_CON_TIMEOUT");

    index.put(propertyKey, propertyIndex.toString());
  }

  /**
   * Creates a regular Expression Pattern from the given Value. The Pattern will
   * use ".*" as wrapper to ensure a Match.
   * 
   * @param str The Value to create a Pattern from.
   * @return Pattern The regular Expression Pattern from the given Value
   */
  private Pattern createPattern(String str) {
    StringBuffer pattern = new StringBuffer();
    pattern.append(".*");
    pattern.append(RegExShop.escapeRegEx(str));
    pattern.append(".*");
    return Pattern.compile(pattern.toString(), Pattern.CASE_INSENSITIVE);
  }
}