/*
 * Copyright 2000-2014 JetBrains s.r.o.
 *
 * 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.intellij.ide.ui.search;

import com.intellij.application.options.SkipSelfSearchComponent;
import com.intellij.ide.actions.ShowSettingsUtilImpl;
import com.intellij.openapi.options.Configurable;
import com.intellij.openapi.options.ConfigurableGroup;
import com.intellij.openapi.options.MasterDetails;
import com.intellij.openapi.options.SearchableConfigurable;
import com.intellij.openapi.options.ex.GlassPanel;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.ui.popup.JBPopup;
import com.intellij.openapi.ui.popup.JBPopupFactory;
import com.intellij.openapi.util.Condition;
import com.intellij.openapi.util.text.StringUtil;
import com.intellij.ui.*;
import com.intellij.ui.components.JBList;
import com.intellij.util.Alarm;
import com.intellij.util.Consumer;
import com.intellij.util.containers.ContainerUtil;
import org.jetbrains.annotations.NonNls;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;

import javax.swing.*;
import javax.swing.border.Border;
import javax.swing.border.TitledBorder;
import java.awt.*;
import java.awt.event.KeyAdapter;
import java.awt.event.KeyEvent;
import java.util.*;
import java.util.List;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

/**
 * User: anna
 * Date: 07-Feb-2006
 */
public class SearchUtil {
  private static final Pattern HTML_PATTERN = Pattern.compile("<[^<>]*>");
  private static final Pattern QUOTED = Pattern.compile("\\\"([^\\\"]+)\\\"");

  public static final String HIGHLIGHT_WITH_BORDER = "searchUtil.highlightWithBorder";
  public static final String STYLE_END = "</style>";

  private SearchUtil() {
  }

  public static void processProjectConfigurables(Project project, HashMap<SearchableConfigurable, TreeSet<OptionDescription>> options) {
    processConfigurables(ShowSettingsUtilImpl.getConfigurables(project, false), options);
  }

  private static void processConfigurables(final Configurable[] configurables,
                                           final HashMap<SearchableConfigurable, TreeSet<OptionDescription>> options) {
    for (Configurable configurable : configurables) {
      if (configurable instanceof SearchableConfigurable) {
        TreeSet<OptionDescription> configurableOptions = new TreeSet<OptionDescription>();

        if (configurable instanceof Configurable.Composite) {
          final Configurable[] children = ((Configurable.Composite)configurable).getConfigurables();
          processConfigurables(children, options);
        }

        //ignore invisible root nodes
        if (configurable instanceof SearchableConfigurable.Parent && !((SearchableConfigurable.Parent)configurable).isVisible()) {
          continue;
        }

        options.put((SearchableConfigurable)configurable, configurableOptions);

        if (configurable instanceof MasterDetails) {
          final MasterDetails md = (MasterDetails)configurable;
          md.initUi();
          _processComponent(configurable, configurableOptions, md.getMaster());
          _processComponent(configurable, configurableOptions, md.getDetails().getComponent());
        }
        else {
          _processComponent(configurable, configurableOptions, configurable.createComponent());
        }
      }
    }
  }

  private static void _processComponent(final Configurable configurable, final TreeSet<OptionDescription> configurableOptions,
                                        final JComponent component) {

    if (component == null) return;

    processUILabel(configurable.getDisplayName(), configurableOptions, null);
    processComponent(component, configurableOptions, null);
  }

  public static void processComponent(final JComponent component, final Set<OptionDescription> configurableOptions, @NonNls String path) {
    if (component instanceof SkipSelfSearchComponent) return;
    final Border border = component.getBorder();
    if (border instanceof TitledBorder) {
      final TitledBorder titledBorder = (TitledBorder)border;
      final String title = titledBorder.getTitle();
      if (title != null) {
        processUILabel(title, configurableOptions, path);
      }
    }
    if (component instanceof JLabel) {
      final String label = ((JLabel)component).getText();
      if (label != null) {
        processUILabel(label, configurableOptions, path);
      }
    }
    else if (component instanceof JCheckBox) {
      @NonNls final String checkBoxTitle = ((JCheckBox)component).getText();
      if (checkBoxTitle != null) {
        processUILabel(checkBoxTitle, configurableOptions, path);
      }
    }
    else if (component instanceof JRadioButton) {
      @NonNls final String radioButtonTitle = ((JRadioButton)component).getText();
      if (radioButtonTitle != null) {
        processUILabel(radioButtonTitle, configurableOptions, path);
      }
    }
    else if (component instanceof JButton) {
      @NonNls final String buttonTitle = ((JButton)component).getText();
      if (buttonTitle != null) {
        processUILabel(buttonTitle, configurableOptions, path);
      }
    }
    if (component instanceof JTabbedPane) {
      final JTabbedPane tabbedPane = (JTabbedPane)component;
      final int tabCount = tabbedPane.getTabCount();
      for (int i = 0; i < tabCount; i++) {
        final String title = path != null ? path + '.' + tabbedPane.getTitleAt(i) : tabbedPane.getTitleAt(i);
        processUILabel(title, configurableOptions, title);
        final Component tabComponent = tabbedPane.getComponentAt(i);
        if (tabComponent instanceof JComponent) {
          processComponent((JComponent)tabComponent, configurableOptions, title);
        }
      }
    }
    else {
      final Component[] components = component.getComponents();
      if (components != null) {
        for (Component child : components) {
          if (child instanceof JComponent) {
            processComponent((JComponent)child, configurableOptions, path);
          }
        }
      }
    }
  }

  private static void processUILabel(@NonNls final String title, final Set<OptionDescription> configurableOptions, String path) {
    final Set<String> words = SearchableOptionsRegistrar.getInstance().getProcessedWordsWithoutStemming(title);
    @NonNls final String regex = "[\\W&&[^\\p{Punct}\\p{Blank}]]";
    for (String option : words) {
      configurableOptions.add(new OptionDescription(option, HTML_PATTERN.matcher(title).replaceAll(" ").replaceAll(regex, " "), path));
    }
  }

  public static Runnable lightOptions(final SearchableConfigurable configurable,
                                      final JComponent component,
                                      final String option,
                                      final GlassPanel glassPanel) {
    return new Runnable() {
      public void run() {
        if (!traverseComponentsTree(configurable, glassPanel, component, option, true)) {
          traverseComponentsTree(configurable, glassPanel, component, option, false);
        }
      }
    };
  }

  private static int getSelection(String tabIdx, final JTabbedPane tabbedPane) {
    SearchableOptionsRegistrar searchableOptionsRegistrar = SearchableOptionsRegistrar.getInstance();
    for (int i = 0; i < tabbedPane.getTabCount(); i++) {
      final Set<String> pathWords = searchableOptionsRegistrar.getProcessedWords(tabIdx);
      final String title = tabbedPane.getTitleAt(i);
      if (!pathWords.isEmpty()) {
        final Set<String> titleWords = searchableOptionsRegistrar.getProcessedWords(title);
        pathWords.removeAll(titleWords);
        if (pathWords.isEmpty()) return i;
      } else if (tabIdx.equalsIgnoreCase(title)) { //e.g. only stop words
        return i;
      }
    }
    return -1;
  }

  public static int getSelection(String tabIdx, final TabbedPaneWrapper tabbedPane) {
    SearchableOptionsRegistrar searchableOptionsRegistrar = SearchableOptionsRegistrar.getInstance();
    for (int i = 0; i < tabbedPane.getTabCount(); i++) {
      final Set<String> pathWords = searchableOptionsRegistrar.getProcessedWords(tabIdx);
      final String title = tabbedPane.getTitleAt(i);
      final Set<String> titleWords = searchableOptionsRegistrar.getProcessedWords(title);
      pathWords.removeAll(titleWords);
      if (pathWords.isEmpty()) return i;
    }
    return -1;
  }

  private static boolean traverseComponentsTree(final SearchableConfigurable configurable,
                                                GlassPanel glassPanel,
                                                JComponent rootComponent,
                                                String option,
                                                boolean force) {

    rootComponent.putClientProperty(HIGHLIGHT_WITH_BORDER, null);

    if (option == null || option.trim().length() == 0) return false;
    boolean highlight = false;
    if (rootComponent instanceof JCheckBox) {
      final JCheckBox checkBox = ((JCheckBox)rootComponent);
      if (isComponentHighlighted(checkBox.getText(), option, force, configurable)) {
        highlight = true;
        glassPanel.addSpotlight(checkBox);
      }
    }
    else if (rootComponent instanceof JRadioButton) {
      final JRadioButton radioButton = ((JRadioButton)rootComponent);
      if (isComponentHighlighted(radioButton.getText(), option, force, configurable)) {
        highlight = true;
        glassPanel.addSpotlight(radioButton);
      }
    }
    else if (rootComponent instanceof JLabel) {
      final JLabel label = ((JLabel)rootComponent);
      if (isComponentHighlighted(label.getText(), option, force, configurable)) {
        highlight = true;
        glassPanel.addSpotlight(label);
      }
    }
    else if (rootComponent instanceof JButton) {
      final JButton button = ((JButton)rootComponent);
      if (isComponentHighlighted(button.getText(), option, force, configurable)) {
        highlight = true;
        glassPanel.addSpotlight(button);
      }
    }
    else if (rootComponent instanceof JTabbedPane) {
      final JTabbedPane tabbedPane = (JTabbedPane)rootComponent;
      final String path = SearchableOptionsRegistrar.getInstance().getInnerPath(configurable, option);
      if (path != null) {
        final int index = getSelection(path, tabbedPane);
        if (index > -1 && index < tabbedPane.getTabCount()) {
          if (tabbedPane.getTabComponentAt(index) instanceof JComponent) {
            glassPanel.addSpotlight((JComponent)tabbedPane.getTabComponentAt(index));
          }
        }
      }
    }


    final Component[] components = rootComponent.getComponents();
    for (Component component : components) {
      if (component instanceof JComponent) {
        final boolean innerHighlight = traverseComponentsTree(configurable, glassPanel, (JComponent)component, option, force);

        if (!highlight && !innerHighlight) {
          final Border border = rootComponent.getBorder();
          if (border instanceof TitledBorder) {
            final String title = ((TitledBorder)border).getTitle();
            if (isComponentHighlighted(title, option, force, configurable)) {
              highlight = true;
              glassPanel.addSpotlight(rootComponent);
              rootComponent.putClientProperty(HIGHLIGHT_WITH_BORDER, Boolean.TRUE);
            }
          }
        }


        if (innerHighlight) {
          highlight = true;
        }
      }
    }
    return highlight;
  }

  public static boolean isComponentHighlighted(String text, String option, final boolean force, final SearchableConfigurable configurable) {
    if (text == null || option == null || option.length() == 0) return false;
    final SearchableOptionsRegistrar searchableOptionsRegistrar = SearchableOptionsRegistrar.getInstance();
    final Set<String> words = searchableOptionsRegistrar.getProcessedWords(option);
    final Set<String> options =
      configurable != null ? searchableOptionsRegistrar.replaceSynonyms(words, configurable) : words;
    if (options == null || options.isEmpty()) {
      return text.toLowerCase().indexOf(option.toLowerCase()) != -1;
    }
    final Set<String> tokens = searchableOptionsRegistrar.getProcessedWords(text);
    if (!force) {
      options.retainAll(tokens);
      final boolean highlight = !options.isEmpty();
      return highlight || text.toLowerCase().indexOf(option.toLowerCase()) != -1;
    }
    else {
      options.removeAll(tokens);
      return options.isEmpty();
    }
  }

  public static String markup(@NonNls @NotNull String textToMarkup, @Nullable String filter) {
    if (filter == null || filter.length() == 0) {
      return textToMarkup;
    }
    int bodyStart = textToMarkup.indexOf("<body>");
    final int bodyEnd = textToMarkup.indexOf("</body>");
    final String head;
    final String foot;
    if (bodyStart >= 0) {
      bodyStart += "<body>".length();
      head = textToMarkup.substring(0, bodyStart);
      if (bodyEnd >= 0) {
        foot = textToMarkup.substring(bodyEnd);
      } else {
        foot = "";
      }
      textToMarkup = textToMarkup.substring(bodyStart, bodyEnd);
    } else {
      foot = "";
      head = "";
    }
    final Pattern insideHtmlTagPattern = Pattern.compile("[<[^<>]*>]*<[^<>]*");
    final SearchableOptionsRegistrar registrar = SearchableOptionsRegistrar.getInstance();
    final HashSet<String> quoted = new HashSet<String>();
    filter = processFilter(quoteStrictOccurrences(textToMarkup, filter), quoted);
    final Set<String> options = registrar.getProcessedWords(filter);
    final Set<String> words = registrar.getProcessedWords(textToMarkup);
    for (String option : options) {
      if (words.contains(option)) {
        textToMarkup = markup(textToMarkup, insideHtmlTagPattern, option);
      }
    }
    for (String stripped : quoted) {
      textToMarkup = markup(textToMarkup, insideHtmlTagPattern, stripped);
    }
    return head + textToMarkup + foot;
  }

  private static String quoteStrictOccurrences(final String textToMarkup, final String filter) {
    String cur = "";
    final String s = textToMarkup.toLowerCase();
    for (String part : filter.split(" ")) {
      if (s.contains(part)) {
        cur += "\"" + part + "\" ";
      }
      else {
        cur += part + " ";
      }
    }
    return cur;
  }

  private static String markup(@NonNls String textToMarkup, final Pattern insideHtmlTagPattern, final String option) {
    @NonNls String result = "";
    final int styleIdx = textToMarkup.indexOf("<style");
    final int styleEndIdx = textToMarkup.indexOf("</style>");
    if (styleIdx < 0 || styleEndIdx < 0) {
      result = markupInText(textToMarkup, insideHtmlTagPattern, option);
    } else {
      result = markup(textToMarkup.substring(0, styleIdx), insideHtmlTagPattern, option) + markup(textToMarkup.substring(styleEndIdx + STYLE_END.length()), insideHtmlTagPattern, option);
    }
    return result;
  }

  private static String markupInText(String textToMarkup, Pattern insideHtmlTagPattern, String option) {
    String result = "";
    int beg = 0;
    int idx;
    while ((idx = StringUtil.indexOfIgnoreCase(textToMarkup, option, beg)) != -1) {
      final String prefix = textToMarkup.substring(beg, idx);
      final String toMark = textToMarkup.substring(idx, idx + option.length());
      if (insideHtmlTagPattern.matcher(prefix).matches()) {
        final int lastIdx = textToMarkup.indexOf(">", idx);
        result += prefix + textToMarkup.substring(idx, lastIdx + 1);
        beg = lastIdx + 1;
      }
      else {
        result += prefix + "<font color='#ffffff' bgColor='#1d5da7'>" + toMark + "</font>";
        beg = idx + option.length();
      }
    }
    result += textToMarkup.substring(beg);
    return result;
  }

  public static void appendFragments(String filter,
                                     @NonNls String text,
                                     @SimpleTextAttributes.StyleAttributeConstant int style,
                                     final Color foreground,
                                     final Color background,
                                     final SimpleColoredComponent textRenderer) {
    if (text == null) return;
    if (filter == null || filter.length() == 0) {
      textRenderer.append(text, new SimpleTextAttributes(background, foreground, JBColor.RED, style));
    }
    else { //markup
      final HashSet<String> quoted = new HashSet<String>();
      filter = processFilter(quoteStrictOccurrences(text, filter), quoted);
      final TreeMap<Integer, String> indx = new TreeMap<Integer, String>();
      for (String stripped : quoted) {
        int beg = 0;
        int idx;
        while ((idx = StringUtil.indexOfIgnoreCase(text, stripped, beg)) != -1) {
          indx.put(idx, text.substring(idx, idx + stripped.length()));
          beg = idx + stripped.length();
        }
      }

      final List<String> selectedWords = new ArrayList<String>();
      int pos = 0;
      for (Integer index : indx.keySet()) {
        final String stripped = indx.get(index);
        final int start = index.intValue();
        if (pos > start) {
          final String highlighted = selectedWords.get(selectedWords.size() - 1);
          if (highlighted.length() < stripped.length()){
            selectedWords.remove(highlighted);
          } else {
            continue;
          }
        }
        appendSelectedWords(text, selectedWords, pos, start, filter);
        selectedWords.add(stripped);
        pos = start + stripped.length();
      }
      appendSelectedWords(text, selectedWords, pos, text.length(), filter);

      int idx = 0;
      for (String word : selectedWords) {
        text = text.substring(idx);
        final String before = text.substring(0, text.indexOf(word));
        if (before.length() > 0) textRenderer.append(before, new SimpleTextAttributes(background, foreground, null, style));
        idx = text.indexOf(word) + word.length();
        textRenderer.append(text.substring(idx - word.length(), idx), new SimpleTextAttributes(background,
                                                                                               foreground, null,
                                                                                               style |
                                                                                               SimpleTextAttributes.STYLE_SEARCH_MATCH));
      }
      final String after = text.substring(idx, text.length());
      if (after.length() > 0) textRenderer.append(after, new SimpleTextAttributes(background, foreground, null, style));
    }
  }

  private static void appendSelectedWords(final String text,
                                          final List<String> selectedWords,
                                          final int pos,
                                          int end,
                                          final String filter) {
    if (pos < end) {
      final Set<String> filters = SearchableOptionsRegistrar.getInstance().getProcessedWords(filter);
      final String[] words = text.substring(pos, end).split("[\\W&&[^-]]+");
      for (String word : words) {
        if (filters.contains(PorterStemmerUtil.stem(word.toLowerCase()))) {
          selectedWords.add(word);
        }
      }
    }
  }

  @Nullable
  private static JBPopup createPopup(final ConfigurableSearchTextField searchField,
                                     final JBPopup[] activePopup,
                                     final Alarm showHintAlarm,
                                     final Consumer<String> selectConfigurable,
                                     final Project project,
                                     final int down) {

    final String filter = searchField.getText();
    if (filter == null || filter.length() == 0) return null;
    final Map<String, Set<String>> hints = SearchableOptionsRegistrar.getInstance().findPossibleExtension(filter, project);
    final DefaultListModel model = new DefaultListModel();
    final JList list = new JBList(model);
    for (String groupName : hints.keySet()) {
      model.addElement(groupName);
      final Set<String> descriptions = hints.get(groupName);
      if (descriptions != null) {
        for (String hit : descriptions) {
          if (hit == null) continue;
          model.addElement(new OptionDescription(null, groupName, hit, null));
        }
      }
    }
    list.setCellRenderer(new DefaultListCellRenderer() {
      public Component getListCellRendererComponent(JList list, Object value, int index, boolean isSelected, boolean cellHasFocus) {
        final Component rendererComponent = super.getListCellRendererComponent(list, value, index, isSelected, cellHasFocus);
        if (value instanceof String) {
          setText("------ " + value + " ------");
        }
        else if (value instanceof OptionDescription) {
          setText(((OptionDescription)value).getHit());
        }
        return rendererComponent;
      }
    });


    if (model.size() > 0) {
      final Runnable onChosen = new Runnable() {
        public void run() {
          final Object selectedValue = list.getSelectedValue();
          if (selectedValue instanceof OptionDescription) {
            final OptionDescription description = ((OptionDescription)selectedValue);
            searchField.setText(description.getHit());
            searchField.addCurrentTextToHistory();
            SwingUtilities.invokeLater(new Runnable() {
              public void run() {     //do not show look up again
                showHintAlarm.cancelAllRequests();
                selectConfigurable.consume(description.getConfigurableId());
              }
            });
          }
        }
      };
      final JBPopup popup = JBPopupFactory.getInstance()
        .createListPopupBuilder(list)
        .setItemChoosenCallback(onChosen)
        .setRequestFocus(down != 0)
        .createPopup();
      list.addKeyListener(new KeyAdapter() {
        public void keyPressed(final KeyEvent e) {
          if (e.getKeyCode() != KeyEvent.VK_ENTER && e.getKeyCode() != KeyEvent.VK_UP && e.getKeyCode() != KeyEvent.VK_DOWN &&
              e.getKeyCode() != KeyEvent.VK_PAGE_UP && e.getKeyCode() != KeyEvent.VK_PAGE_DOWN) {
            searchField.requestFocusInWindow();
            if (cancelPopups(activePopup) && e.getKeyCode() == KeyEvent.VK_ESCAPE) {
              return;
            }
            if (e.getKeyChar() != KeyEvent.CHAR_UNDEFINED) {
              searchField.process(
                new KeyEvent(searchField, KeyEvent.KEY_TYPED, e.getWhen(), e.getModifiers(), KeyEvent.VK_UNDEFINED, e.getKeyChar()));
            }
          }
        }

      });
      if (down > 0) {
        if (list.getSelectedIndex() < list.getModel().getSize() - 1) {
          list.setSelectedIndex(list.getSelectedIndex() + 1);
        }
      }
      else if (down < 0) {
        if (list.getSelectedIndex() > 0) {
          list.setSelectedIndex(list.getSelectedIndex() - 1);
        }
      }
      return popup;
    }
    return null;
  }

  private static boolean cancelPopups(final JBPopup[] activePopup) {
    for (JBPopup popup : activePopup) {
      if (popup != null && popup.isVisible()) {
        popup.cancel();
        return true;
      }
    }
    return false;
  }

  public static List<Set<String>> findKeys(String filter, Set<String> quoted) {
    filter = processFilter(filter.toLowerCase(), quoted);
    final List<Set<String>> keySetList = new ArrayList<Set<String>>();
    final SearchableOptionsRegistrar optionsRegistrar = SearchableOptionsRegistrar.getInstance();
    final Set<String> words = optionsRegistrar.getProcessedWords(filter);
    for (String word : words) {
      final Set<OptionDescription> descriptions = ((SearchableOptionsRegistrarImpl)optionsRegistrar).getAcceptableDescriptions(word);
      Set<String> keySet = new HashSet<String>();
      if (descriptions != null) {
        for (OptionDescription description : descriptions) {
          keySet.add(description.getPath());
        }
      }
      keySetList.add(keySet);
    }
    if (keySetList.isEmpty() && !StringUtil.isEmptyOrSpaces(filter)) {
      keySetList.add(Collections.singleton(filter));
    }
    return keySetList;
  }

  public static String processFilter(String filter, Set<String> quoted) {
    String withoutQuoted = "";
    int beg = 0;
    final Matcher matcher = QUOTED.matcher(filter);
    while (matcher.find()) {
      final int start = matcher.start(1);
      withoutQuoted += " " + filter.substring(beg, start);
      beg = matcher.end(1);
      final String trimmed = filter.substring(start, beg).trim();
      if (trimmed.length() > 0) {
        quoted.add(trimmed);
      }
    }
    return withoutQuoted + " " + filter.substring(beg);
  }

  //to process event
  public static class ConfigurableSearchTextField extends SearchTextFieldWithStoredHistory {
    public ConfigurableSearchTextField() {
      super("ALL_CONFIGURABLES_PANEL_SEARCH_HISTORY");
    }

    public void process(final KeyEvent e) {
      ((TextFieldWithProcessing)getTextEditor()).processKeyEvent(e);
    }
  }

  public static List<Configurable> expand(ConfigurableGroup[] groups) {
    final ArrayList<Configurable> result = new ArrayList<Configurable>();
    for (ConfigurableGroup eachGroup : groups) {
      result.addAll(expandGroup(eachGroup));
    }
    return result;
  }

  public static List<Configurable> expandGroup(final ConfigurableGroup group) {
    final Configurable[] configurables = group.getConfigurables();
    List<Configurable> result = new ArrayList<Configurable>();
    ContainerUtil.addAll(result, configurables);
    for (Configurable each : configurables) {
      addChildren(each, result);
    }
    
    result = ContainerUtil.filter(result, new Condition<Configurable>() {
      @Override
      public boolean value(Configurable configurable) {
        return !(configurable instanceof SearchableConfigurable.Parent) || ((SearchableConfigurable.Parent)configurable).isVisible();
      }
    });
   
    return result;
  }

  private static void addChildren(Configurable configurable, List<Configurable> list) {
    if (configurable instanceof Configurable.Composite) {
      final Configurable[] kids = ((Configurable.Composite)configurable).getConfigurables();
      for (Configurable eachKid : kids) {
        list.add(eachKid);
        addChildren(eachKid, list);
      }
    }
  }

}
