/*
 * 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.openapi.editor.actions;

import com.intellij.codeInsight.editorActions.SelectWordUtil;
import com.intellij.codeInsight.hint.HintManager;
import com.intellij.codeInsight.hint.HintManagerImpl;
import com.intellij.codeInsight.hint.HintUtil;
import com.intellij.find.EditorSearchComponent;
import com.intellij.find.FindBundle;
import com.intellij.find.FindModel;
import com.intellij.find.editorHeaderActions.EditorHeaderAction;
import com.intellij.openapi.actionSystem.*;
import com.intellij.openapi.editor.Caret;
import com.intellij.openapi.editor.Editor;
import com.intellij.openapi.editor.EditorLastActionTracker;
import com.intellij.openapi.editor.actionSystem.EditorActionHandler;
import com.intellij.openapi.util.Key;
import com.intellij.openapi.util.TextRange;
import com.intellij.ui.LightweightHint;
import com.intellij.util.containers.HashSet;
import org.jetbrains.annotations.Nullable;

import java.util.Arrays;
import java.util.Set;

abstract public class SelectOccurrencesActionHandler extends EditorActionHandler {

  private static final Key<Boolean> NOT_FOUND = Key.create("select.next.occurence.not.found");
  private static final Key<Boolean> WHOLE_WORDS = Key.create("select.next.occurence.whole.words");

  private static final Set<String> SELECT_ACTIONS = new HashSet<String>(Arrays.asList(
    IdeActions.ACTION_SELECT_NEXT_OCCURENCE,
    IdeActions.ACTION_UNSELECT_PREVIOUS_OCCURENCE,
    IdeActions.ACTION_FIND_NEXT,
    IdeActions.ACTION_FIND_PREVIOUS
  ));

  protected static void setSelection(Editor editor, Caret caret, TextRange selectionRange) {
    EditorActionUtil.makePositionVisible(editor, selectionRange.getStartOffset());
    EditorActionUtil.makePositionVisible(editor, selectionRange.getEndOffset());
    caret.setSelection(selectionRange.getStartOffset(), selectionRange.getEndOffset());
  }

  protected static void showHint(final Editor editor) {
    String message = FindBundle.message("select.next.occurence.not.found.message");
    final LightweightHint hint = new LightweightHint(HintUtil.createInformationLabel(message));
    HintManagerImpl.getInstanceImpl().showEditorHint(hint,
                                                     editor,
                                                     HintManager.UNDER,
                                                     HintManager.HIDE_BY_TEXT_CHANGE | HintManager.HIDE_BY_SCROLLING,
                                                     0,
                                                     false);
  }

  protected static boolean getAndResetNotFoundStatus(Editor editor) {
    boolean status = editor.getUserData(NOT_FOUND) != null;
    editor.putUserData(NOT_FOUND, null);
    return status && isRepeatedActionInvocation();
  }

  protected static void setNotFoundStatus(Editor editor) {
    editor.putUserData(NOT_FOUND, Boolean.TRUE);
  }

  protected static boolean isWholeWordSearch(Editor editor) {
    if (!isRepeatedActionInvocation()) {
      editor.putUserData(WHOLE_WORDS, null);
    }
    Boolean value = editor.getUserData(WHOLE_WORDS);
    return value != null;
  }

  @Nullable
  protected static TextRange getSelectionRange(Editor editor, Caret caret) {
    return SelectWordUtil.getWordSelectionRange(editor.getDocument().getCharsSequence(),
                                                caret.getOffset(),
                                                SelectWordUtil.JAVA_IDENTIFIER_PART_CONDITION);
  }

  protected static void setWholeWordSearch(Editor editor, boolean isWholeWordSearch) {
    editor.putUserData(WHOLE_WORDS, isWholeWordSearch);
  }

  protected static boolean isRepeatedActionInvocation() {
    String lastActionId = EditorLastActionTracker.getInstance().getLastActionId();
    return SELECT_ACTIONS.contains(lastActionId);
  }

  protected static FindModel getFindModel(String text, boolean wholeWords) {
    FindModel model = new FindModel();
    model.setStringToFind(text);
    model.setCaseSensitive(true);
    model.setWholeWordsOnly(wholeWords);
    return model;
  }
}
