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

import com.intellij.featureStatistics.FeatureUsageTracker;
import com.intellij.ide.DataManager;
import com.intellij.ide.ui.UISettings;
import com.intellij.openapi.actionSystem.AnAction;
import com.intellij.openapi.actionSystem.AnActionEvent;
import com.intellij.openapi.actionSystem.CommonDataKeys;
import com.intellij.openapi.actionSystem.CustomShortcutSet;
import com.intellij.openapi.application.ApplicationManager;
import com.intellij.openapi.diagnostic.Logger;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.util.SystemInfo;
import com.intellij.openapi.util.TextRange;
import com.intellij.openapi.util.text.StringUtil;
import com.intellij.openapi.wm.ToolWindowManager;
import com.intellij.openapi.wm.ex.ToolWindowManagerAdapter;
import com.intellij.openapi.wm.ex.ToolWindowManagerEx;
import com.intellij.openapi.wm.ex.ToolWindowManagerListener;
import com.intellij.psi.codeStyle.NameUtil;
import com.intellij.ui.speedSearch.SpeedSearchSupply;
import com.intellij.util.ui.UIUtil;
import org.jetbrains.annotations.NonNls;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;

import javax.swing.*;
import javax.swing.text.AttributeSet;
import javax.swing.text.BadLocationException;
import javax.swing.text.PlainDocument;
import java.awt.*;
import java.awt.event.FocusAdapter;
import java.awt.event.FocusEvent;
import java.awt.event.KeyAdapter;
import java.awt.event.KeyEvent;
import java.beans.PropertyChangeListener;
import java.beans.PropertyChangeSupport;
import java.util.ListIterator;
import java.util.NoSuchElementException;

public abstract class SpeedSearchBase<Comp extends JComponent> extends SpeedSearchSupply {
  private static final Logger LOG = Logger.getInstance("#com.intellij.ui.SpeedSearchBase");
  private SearchPopup mySearchPopup;
  private JLayeredPane myPopupLayeredPane;
  protected final Comp myComponent;
  private final ToolWindowManagerListener myWindowManagerListener = new MyToolWindowManagerListener();
  private final PropertyChangeSupport myChangeSupport = new PropertyChangeSupport(this);
  private String myRecentEnteredPrefix;
  private SpeedSearchComparator myComparator = new SpeedSearchComparator(false);
  private boolean myClearSearchOnNavigateNoMatch = false;

  @NonNls protected static final String ENTERED_PREFIX_PROPERTY_NAME = "enteredPrefix";

  public SpeedSearchBase(Comp component) {
    myComponent = component;

    myComponent.addFocusListener(new FocusAdapter() {
      @Override
      public void focusLost(FocusEvent e) {
        manageSearchPopup(null);
      }
    });
    myComponent.addKeyListener(new KeyAdapter() {
      @Override
      public void keyTyped(KeyEvent e) {
        processKeyEvent(e);
      }

      @Override
      public void keyPressed(KeyEvent e) {
        processKeyEvent(e);
      }
    });

    new AnAction() {
      @Override
      public void actionPerformed(AnActionEvent e) {
        final String prefix = getEnteredPrefix();
        assert prefix != null;
        final String[] strings = NameUtil.splitNameIntoWords(prefix);
        final String last = strings[strings.length - 1];
        final int i = prefix.lastIndexOf(last);
        mySearchPopup.mySearchField.setText(prefix.substring(0, i).trim());
      }

      @Override
      public void update(AnActionEvent e) {
        e.getPresentation().setEnabled(isPopupActive() && !StringUtil.isEmpty(getEnteredPrefix()));
      }
    }.registerCustomShortcutSet(CustomShortcutSet.fromString(SystemInfo.isMac ? "meta BACK_SPACE" : "control BACK_SPACE"), myComponent);

    installSupplyTo(component);
  }

  public static boolean hasActiveSpeedSearch(JComponent component) {
    return getSupply(component) != null;
  }

  public void setClearSearchOnNavigateNoMatch(boolean clearSearchOnNavigateNoMatch) {
    myClearSearchOnNavigateNoMatch = clearSearchOnNavigateNoMatch;
  }

  @Override
  public boolean isPopupActive() {
    return mySearchPopup != null && mySearchPopup.isVisible();
  }


  @Override
  public Iterable<TextRange> matchingFragments(@NotNull String text) {
    if (!isPopupActive()) return null;
    final SpeedSearchComparator comparator = getComparator();
    final String recentSearchText = comparator.getRecentSearchText();
    return StringUtil.isNotEmpty(recentSearchText) ? comparator.matchingFragments(recentSearchText, text) : null;
  }

  /**
   * Returns visual (view) selection index.
   */
  protected abstract int getSelectedIndex();

  protected abstract Object[] getAllElements();

  @Nullable
  protected abstract String getElementText(Object element);

  protected int getElementCount() {
    return getAllElements().length;
  }

  /**
   * Should convert given view index to model index
   */
  protected int convertIndexToModel(final int viewIndex) {
    return viewIndex;
  }

  /**
   * @param element Element to select. Don't forget to convert model index to view index if needed (i.e. table.convertRowIndexToView(modelIndex), etc).
   * @param selectedText search text
   */
  protected abstract void selectElement(Object element, String selectedText);

  protected ListIterator<Object> getElementIterator(int startingIndex) {
    return new ViewIterator(this, startingIndex < 0 ? getElementCount() : startingIndex);
  }

  public void addChangeListener(@NotNull PropertyChangeListener listener) {
    myChangeSupport.addPropertyChangeListener(listener);
  }

  public void removeChangeListener(@NotNull PropertyChangeListener listener) {
    myChangeSupport.removePropertyChangeListener(listener);
  }

  private void fireStateChanged() {
    String enteredPrefix = getEnteredPrefix();
    myChangeSupport.firePropertyChange(ENTERED_PREFIX_PROPERTY_NAME, myRecentEnteredPrefix, enteredPrefix);
    myRecentEnteredPrefix = enteredPrefix;
  }

  protected boolean isMatchingElement(Object element, String pattern) {
    String str = getElementText(element);
    return str != null && compare(str, pattern);
  }

  protected boolean compare(String text, String pattern) {
    return myComparator.matchingFragments(pattern, text) != null;
  }

  public SpeedSearchComparator getComparator() {
    return myComparator;
  }

  public void setComparator(final SpeedSearchComparator comparator) {
    myComparator = comparator;
  }

  @Nullable
  private Object findNextElement(String s) {
    final String _s = s.trim();
    final int selectedIndex = getSelectedIndex();
    final ListIterator<?> it = getElementIterator(selectedIndex + 1);
    final Object current;
    if (it.hasPrevious()) {
      current = it.previous();
      it.next();
    }
    else current = null;
    while (it.hasNext()) {
      final Object element = it.next();
      if (isMatchingElement(element, _s)) return element;
    }

    if (UISettings.getInstance().CYCLE_SCROLLING) {
      final ListIterator<Object> i = getElementIterator(0);
      while (i.hasNext()) {
        final Object element = i.next();
        if (isMatchingElement(element, _s)) return element;
      }
    }

    return ( current != null && isMatchingElement(current, _s) ) ? current : null;
  }

  @Nullable
  private Object findPreviousElement(String s) {
    final String _s = s.trim();
    final int selectedIndex = getSelectedIndex();
    if (selectedIndex < 0) return null;
    final ListIterator<?> it = getElementIterator(selectedIndex);
    final Object current;
    if (it.hasNext()) {
      current = it.next();
      it.previous();
    }
    else current = null;
    while (it.hasPrevious()) {
      final Object element = it.previous();
      if (isMatchingElement(element, _s)) return element;
    }

    if (UISettings.getInstance().CYCLE_SCROLLING) {
      final ListIterator<Object> i = getElementIterator(getElementCount());
      while (i.hasPrevious()) {
        final Object element = i.previous();
        if (isMatchingElement(element, _s)) return element;
      }
    }

    return selectedIndex != -1 && isMatchingElement(current, _s) ? current : null;
  }

  @Nullable
  protected Object findElement(String s) {
    final String _s = s.trim();
    int selectedIndex = getSelectedIndex();
    if (selectedIndex < 0) {
      selectedIndex = 0;
    }
    final ListIterator<Object> it = getElementIterator(selectedIndex);
    while (it.hasNext()) {
      final Object element = it.next();
      if (isMatchingElement(element, _s)) return element;
    }
    if (selectedIndex > 0) {
      while (it.hasPrevious()) it.previous();
      while (it.hasNext() && it.nextIndex() != selectedIndex) {
        final Object element = it.next();
        if (isMatchingElement(element, _s)) return element;
      }
    }
    return null;
  }

  @Nullable
  private Object findFirstElement(String s) {
    final String _s = s.trim();
    for (ListIterator<?> it = getElementIterator(0); it.hasNext();) {
      final Object element = it.next();
      if (isMatchingElement(element, _s)) return element;
    }
    return null;
  }

  @Nullable
  private Object findLastElement(String s) {
    final String _s = s.trim();
    for (ListIterator<?> it = getElementIterator(-1); it.hasPrevious();) {
      final Object element = it.previous();
      if (isMatchingElement(element, _s)) return element;
    }
    return null;
  }

  public void showPopup() {
    manageSearchPopup(new SearchPopup(""));
  }

  public void hidePopup() {
    manageSearchPopup(null);
  }

  protected void processKeyEvent(KeyEvent e) {
    if (e.isAltDown()) return;
    if (e.isShiftDown() && isNavigationKey(e.getKeyCode())) return;
    if (mySearchPopup != null) {
      mySearchPopup.processKeyEvent(e);
      return;
    }
    if (!isSpeedSearchEnabled()) return;
    if (e.getID() == KeyEvent.KEY_TYPED) {
      if (!UIUtil.isReallyTypedEvent(e)) return;

      char c = e.getKeyChar();
      if (Character.isLetterOrDigit(c) || c == '_' || c == '*' || c == '/' || c == ':' || c == '.' || c == '#') {
        manageSearchPopup(new SearchPopup(String.valueOf(c)));
        e.consume();
      }
    }
  }


  public Comp getComponent() {
    return myComponent;
  }

  protected boolean isSpeedSearchEnabled() {
    return true;
  }

  @Override
  @Nullable
  public String getEnteredPrefix() {
    return mySearchPopup != null ? mySearchPopup.mySearchField.getText() : null;
  }

  @Override
  public void refreshSelection() {
    if ( mySearchPopup != null ) mySearchPopup.refreshSelection();
  }

  private class SearchPopup extends JPanel {
    private final SearchField mySearchField;

    public SearchPopup(String initialString) {
      final Color foregroundColor = UIUtil.getToolTipForeground();
      Color color1 = new JBColor(UIUtil.getToolTipBackground().brighter(), Gray._111);
      mySearchField = new SearchField();
      final JLabel searchLabel = new JLabel(" " + UIBundle.message("search.popup.search.for.label") + " ");
      searchLabel.setFont(searchLabel.getFont().deriveFont(Font.BOLD));
      searchLabel.setForeground(foregroundColor);
      mySearchField.setBorder(null);
      mySearchField.setBackground(color1);
      mySearchField.setForeground(foregroundColor);

      mySearchField.setDocument(new PlainDocument() {
        @Override
        public void insertString(int offs, String str, AttributeSet a) throws BadLocationException {
          String oldText;
          try {
            oldText = getText(0, getLength());
          }
          catch (BadLocationException e1) {
            oldText = "";
          }

          String newText = oldText.substring(0, offs) + str + oldText.substring(offs);
          super.insertString(offs, str, a);
          if (findElement(newText) == null) {
            mySearchField.setForeground(JBColor.RED);
          }
          else {
            mySearchField.setForeground(foregroundColor);
          }
        }
      });
      mySearchField.setText(initialString);

      setBorder(BorderFactory.createLineBorder(Color.gray, 1));
      setBackground(color1);
      setLayout(new BorderLayout());
      add(searchLabel, BorderLayout.WEST);
      add(mySearchField, BorderLayout.EAST);
      Object element = findElement(mySearchField.getText());
      onSearchFieldUpdated(initialString);
      updateSelection(element);
    }

    @Override
    public void processKeyEvent(KeyEvent e) {
      mySearchField.processKeyEvent(e);
      if (e.isConsumed()) {
        String s = mySearchField.getText();
        onSearchFieldUpdated(s);
        int keyCode = e.getKeyCode();
        Object element;
        if (isUpDownHomeEnd(keyCode)) {
          element = findTargetElement(keyCode, s);
          if (myClearSearchOnNavigateNoMatch && element == null) {
            manageSearchPopup(null);
            element = findTargetElement(keyCode, "");
          }
        }
        else {
          element = findElement(s);
        }
        updateSelection(element);
      }
    }

    @Nullable
    private Object findTargetElement(int keyCode, String searchPrefix) {
      if (keyCode == KeyEvent.VK_UP) {
        return findPreviousElement(searchPrefix);
      }
      else if (keyCode == KeyEvent.VK_DOWN) {
        return findNextElement(searchPrefix);
      }
      else if (keyCode == KeyEvent.VK_HOME) {
        return findFirstElement(searchPrefix);
      }
      else {
        assert keyCode == KeyEvent.VK_END;
        return findLastElement(searchPrefix);
      }
    }

    public void refreshSelection () {
      updateSelection(findElement(mySearchField.getText()));
    }

    private void updateSelection(Object element) {
      if (element != null) {
        selectElement(element, mySearchField.getText());
        mySearchField.setForeground(UIUtil.getLabelForeground());
      }
      else {
        mySearchField.setForeground(JBColor.red);
      }
      if (mySearchPopup != null) {
        mySearchPopup.setSize(mySearchPopup.getPreferredSize());
        mySearchPopup.validate();
      }

      fireStateChanged();
    }
  }

  protected void onSearchFieldUpdated(String pattern) {
  }

  private class SearchField extends JTextField {
    SearchField() {
      setFocusable(false);
    }

    @Override
    public Dimension getPreferredSize() {
      Dimension dim = super.getPreferredSize();
      dim.width = getFontMetrics(getFont()).stringWidth(getText()) + 10;
      return dim;
    }

    /**
     * I made this method public in order to be able to call it from the outside.
     * This is needed for delegating calls.
     */
    @Override
    public void processKeyEvent(KeyEvent e) {
      int i = e.getKeyCode();
      if (i == KeyEvent.VK_BACK_SPACE && getDocument().getLength() == 0) {
        e.consume();
        return;
      }
      if (
        i == KeyEvent.VK_ENTER ||
        i == KeyEvent.VK_ESCAPE ||
        i == KeyEvent.VK_PAGE_UP ||
        i == KeyEvent.VK_PAGE_DOWN ||
        i == KeyEvent.VK_LEFT ||
        i == KeyEvent.VK_RIGHT
        ) {
        manageSearchPopup(null);
        if (i == KeyEvent.VK_ESCAPE) {
          e.consume();
        }
        return;
      }
      
      if (isUpDownHomeEnd(i)) {
        e.consume();
        return;
      }

      super.processKeyEvent(e);
      if (i == KeyEvent.VK_BACK_SPACE) {
        e.consume();
      }
    }

  }

  private static boolean isUpDownHomeEnd(int keyCode) {
    return keyCode == KeyEvent.VK_HOME || keyCode == KeyEvent.VK_END || keyCode == KeyEvent.VK_UP || keyCode == KeyEvent.VK_DOWN;
  }

  private static boolean isPgUpPgDown(int keyCode) {
    return keyCode == KeyEvent.VK_PAGE_UP || keyCode == KeyEvent.VK_PAGE_DOWN;
  }

  private static boolean isNavigationKey(int keyCode) {
    return isPgUpPgDown(keyCode) || isUpDownHomeEnd(keyCode);
  }
  

  private void manageSearchPopup(@Nullable SearchPopup searchPopup) {
    Project project = null;
    if (ApplicationManager.getApplication() != null && !ApplicationManager.getApplication().isDisposed()) {
      project = CommonDataKeys.PROJECT.getData(DataManager.getInstance().getDataContext(myComponent));
    }
    if (project != null && project.isDefault()) {
      project = null;
    }
    if (mySearchPopup != null) {
      myPopupLayeredPane.remove(mySearchPopup);
      myPopupLayeredPane.validate();
      myPopupLayeredPane.repaint();
      myPopupLayeredPane = null;

      if (project != null) {
        ((ToolWindowManagerEx)ToolWindowManager.getInstance(project)).removeToolWindowManagerListener(myWindowManagerListener);
      }
    }
    else if (searchPopup != null) {
      FeatureUsageTracker.getInstance().triggerFeatureUsed("ui.tree.speedsearch");
    }

    if (!myComponent.isShowing()) {
      mySearchPopup = null;
    }
    else {
      mySearchPopup = searchPopup;
    }

    fireStateChanged();

    if (mySearchPopup == null || !myComponent.isDisplayable()) return;

    if (project != null) {
      ((ToolWindowManagerEx)ToolWindowManager.getInstance(project)).addToolWindowManagerListener(myWindowManagerListener);
    }
    JRootPane rootPane = myComponent.getRootPane();
    if (rootPane != null) {
      myPopupLayeredPane = rootPane.getLayeredPane();
    }
    else {
      myPopupLayeredPane = null;
    }
    if (myPopupLayeredPane == null) {
      LOG.error(toString() + " in " + myComponent);
      return;
    }
    myPopupLayeredPane.add(mySearchPopup, JLayeredPane.POPUP_LAYER);
    if (myPopupLayeredPane == null) return; // See # 27482. Somewho it does happen...
    Point lPaneP = myPopupLayeredPane.getLocationOnScreen();
    Point componentP = getComponentLocationOnScreen();
    Rectangle r = getComponentVisibleRect();
    Dimension prefSize = mySearchPopup.getPreferredSize();
    Window window = (Window)SwingUtilities.getAncestorOfClass(Window.class, myComponent);
    Point windowP;
    if (window instanceof JDialog) {
      windowP = ((JDialog)window).getContentPane().getLocationOnScreen();
    }
    else if (window instanceof JFrame) {
      windowP = ((JFrame)window).getContentPane().getLocationOnScreen();
    }
    else {
      windowP = window.getLocationOnScreen();
    }
    int y = r.y + componentP.y - lPaneP.y - prefSize.height;
    y = Math.max(y, windowP.y - lPaneP.y);
    mySearchPopup.setLocation(componentP.x - lPaneP.x + r.x, y);
    mySearchPopup.setSize(prefSize);
    mySearchPopup.setVisible(true);
    mySearchPopup.validate();
  }

  protected Rectangle getComponentVisibleRect() {
    return myComponent.getVisibleRect();
  }

  protected Point getComponentLocationOnScreen() {
    return myComponent.getLocationOnScreen();
  }

  private class MyToolWindowManagerListener extends ToolWindowManagerAdapter {
    @Override
    public void stateChanged() {
      manageSearchPopup(null);
    }
  }

  protected class ViewIterator implements ListIterator<Object> {
    private final SpeedSearchBase mySpeedSearch;
    private int myCurrentIndex;
    private final Object[] myElements;

    public ViewIterator(@NotNull final SpeedSearchBase speedSearch, final int startIndex) {
      mySpeedSearch = speedSearch;
      myCurrentIndex = startIndex;
      myElements = speedSearch.getAllElements();

      if (startIndex < 0 || startIndex > myElements.length) {
        throw new IndexOutOfBoundsException("Index: " + startIndex + " in: " + SpeedSearchBase.this.getClass());
      }
    }

    @Override
    public boolean hasPrevious() {
      return myCurrentIndex != 0;
    }

    @Override
    public Object previous() {
      final int i = myCurrentIndex - 1;
      if (i < 0) throw new NoSuchElementException();
      final Object previous = myElements[mySpeedSearch.convertIndexToModel(i)];
      myCurrentIndex = i;
      return previous;
    }

    @Override
    public int nextIndex() {
      return myCurrentIndex;
    }

    @Override
    public int previousIndex() {
      return myCurrentIndex - 1;
    }

    @Override
    public boolean hasNext() {
      return myCurrentIndex != myElements.length;
    }

    @Override
    public Object next() {
      if (myCurrentIndex + 1 > myElements.length) throw new NoSuchElementException();
      return myElements[mySpeedSearch.convertIndexToModel(myCurrentIndex++)];
    }

    @Override
    public void remove() {
      throw new UnsupportedOperationException("Not implemented in: " + getClass().getCanonicalName());
    }

    @Override
    public void set(Object o) {
      throw new UnsupportedOperationException("Not implemented in: " + getClass().getCanonicalName());
    }

    @Override
    public void add(Object o) {
      throw new UnsupportedOperationException("Not implemented in: " + getClass().getCanonicalName());
    }
  }
}
