/*
 * Copyright 2000-2009 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.codeInsight.completion.actions;

import com.intellij.codeInsight.CodeInsightActionHandler;
import com.intellij.codeInsight.FileModificationService;
import com.intellij.codeInsight.completion.impl.CamelHumpMatcher;
import com.intellij.codeInsight.highlighting.HighlightManager;
import com.intellij.codeInsight.lookup.LookupManager;
import com.intellij.openapi.editor.Editor;
import com.intellij.openapi.editor.colors.EditorColors;
import com.intellij.openapi.editor.colors.EditorColorsManager;
import com.intellij.openapi.editor.ex.EditorEx;
import com.intellij.openapi.editor.highlighter.HighlighterIterator;
import com.intellij.openapi.editor.markup.TextAttributes;
import com.intellij.openapi.fileEditor.FileEditor;
import com.intellij.openapi.fileEditor.FileEditorManager;
import com.intellij.openapi.fileEditor.TextEditor;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.util.Key;
import com.intellij.openapi.util.text.StringUtil;
import com.intellij.psi.PsiFile;
import com.intellij.util.text.CharArrayUtil;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;

import java.util.*;

/**
 * @author mike
 */
public class HippieWordCompletionHandler implements CodeInsightActionHandler {
  private static final Key<CompletionState> KEY_STATE = new Key<CompletionState>("HIPPIE_COMPLETION_STATE");
  private static final String WHITESPACE_CHARS = " \t\n";
  private final boolean myForward;

  public HippieWordCompletionHandler(boolean forward) {
    myForward = forward;
  }

  @Override
  public void invoke(@NotNull Project project, @NotNull final Editor editor, @NotNull PsiFile file) {
    if (!FileModificationService.getInstance().prepareFileForWrite(file)) return;

    LookupManager.getInstance(project).hideActiveLookup();

    final CharSequence charsSequence = editor.getDocument().getCharsSequence();

    final CompletionData data = computeData(editor, charsSequence);
    String currentPrefix = data.myPrefix;

    final CompletionState completionState = getCompletionState(editor);

    String oldPrefix = completionState.oldPrefix;
    CompletionVariant lastProposedVariant = completionState.lastProposedVariant;

    if (lastProposedVariant == null || oldPrefix == null || !new CamelHumpMatcher(oldPrefix).isStartMatch(currentPrefix) ||
        !currentPrefix.equals(lastProposedVariant.variant)) {
      //we are starting over
      oldPrefix = currentPrefix;
      completionState.oldPrefix = oldPrefix;
      lastProposedVariant = null;
    }

    CompletionVariant nextVariant = computeNextVariant(editor, oldPrefix, lastProposedVariant, data, file);
    if (nextVariant == null) return;

    int replacementEnd = data.startOffset + data.myWordUnderCursor.length();
    editor.getDocument().replaceString(data.startOffset, replacementEnd, nextVariant.variant);
    editor.getCaretModel().moveToOffset(data.startOffset + nextVariant.variant.length());
    completionState.lastProposedVariant = nextVariant;
    highlightWord(editor, nextVariant, project, data);
  }

  private static void highlightWord(final Editor editor, final CompletionVariant variant, final Project project, CompletionData data) {
    int delta = data.startOffset < variant.offset ? variant.variant.length() - data.myWordUnderCursor.length() : 0;

    HighlightManager highlightManager = HighlightManager.getInstance(project);
    EditorColorsManager colorManager = EditorColorsManager.getInstance();
    TextAttributes attributes = colorManager.getGlobalScheme().getAttributes(EditorColors.TEXT_SEARCH_RESULT_ATTRIBUTES);
    highlightManager.addOccurrenceHighlight(editor, variant.offset + delta, variant.offset + variant.variant.length() + delta, attributes,
                                            HighlightManager.HIDE_BY_ANY_KEY, null, null);
  }


  private static class CompletionData {
    public String myPrefix;
    public String myWordUnderCursor;
    public int startOffset;
  }

  @Nullable
  private CompletionVariant computeNextVariant(final Editor editor,
                                               @Nullable final String prefix,
                                               @Nullable CompletionVariant lastProposedVariant,
                                               final CompletionData data, PsiFile file) {
    final List<CompletionVariant> variants = computeVariants(editor, new CamelHumpMatcher(StringUtil.notNullize(prefix)), file);
    if (variants.isEmpty()) return null;

    for (CompletionVariant variant : variants) {
      if (lastProposedVariant != null) {
        if (variant.variant.equals(lastProposedVariant.variant)) {
          if (lastProposedVariant.offset > data.startOffset && variant.offset > data.startOffset) lastProposedVariant = variant;
          if (lastProposedVariant.offset < data.startOffset && variant.offset < data.startOffset) lastProposedVariant = variant;
        }
      }
    }


    if (lastProposedVariant == null) {
      CompletionVariant result = null;

      if (myForward) {
        for (CompletionVariant variant : variants) {
          if (variant.offset < data.startOffset) {
            result = variant;
          }
          else if (result == null) {
            result = variant;
            break;
          }
        }
      }
      else {
        for (CompletionVariant variant : variants) {
          if (variant.offset > data.startOffset) return variant;
        }

        return variants.iterator().next();
      }

      return result;
    }


    if (myForward) {
      CompletionVariant result = null;
      for (CompletionVariant variant : variants) {
        if (variant == lastProposedVariant) {
          if (result == null) return variants.get(variants.size() - 1);
          return result;
        }
        result = variant;
      }

      return variants.get(variants.size() - 1);
    }
    else {
      for (Iterator<CompletionVariant> i = variants.iterator(); i.hasNext();) {
        CompletionVariant variant = i.next();
        if (variant == lastProposedVariant) {
          if (i.hasNext()) {
            return i.next();
          }
          else {
            return variants.iterator().next();
          }
        }
      }

    }

    return null;
  }

  public static class CompletionVariant {
    public final String variant;
    public final int offset;

    public CompletionVariant(final String variant, final int offset) {
      this.variant = variant;
      this.offset = offset;
    }
  }
  
  private static boolean isWordLike(CharSequence seq, int start, int end) {
    for (int i = start; i < end; i++) {
      if (Character.isLetter(seq.charAt(i))) {
        return true;
      }
    }
    return false;
  }

  private static List<CompletionVariant> computeVariants(@NotNull final Editor editor, CamelHumpMatcher matcher, PsiFile file) {

    final CharSequence chars = editor.getDocument().getCharsSequence();

    final ArrayList<CompletionVariant> words = new ArrayList<CompletionVariant>();
    final List<CompletionVariant> afterWords = new ArrayList<CompletionVariant>();

    final int caretOffset = editor.getCaretModel().getOffset();

    addWordsForEditor((EditorEx)editor, matcher, chars, words, afterWords, caretOffset);

    for(FileEditor fileEditor: FileEditorManager.getInstance(file.getProject()).getAllEditors()) {
      if (fileEditor instanceof TextEditor) {
        Editor anotherEditor = ((TextEditor)fileEditor).getEditor();
        if (anotherEditor != editor) {
          addWordsForEditor((EditorEx)anotherEditor, matcher, anotherEditor.getDocument().getCharsSequence(), words, afterWords, 0);
        }
      }
    }

    Set<String> allWords = new HashSet<String>();
    List<CompletionVariant> result = new ArrayList<CompletionVariant>();

    Collections.reverse(words);

    for (CompletionVariant variant : words) {
      if (!allWords.contains(variant.variant)) {
        result.add(variant);
        allWords.add(variant.variant);
      }
    }

    Collections.reverse(result);

    allWords.clear();
    for (CompletionVariant variant : afterWords) {
      if (!allWords.contains(variant.variant)) {
        result.add(variant);
        allWords.add(variant.variant);
      }
    }

    return result;
  }
  
  private interface TokenProcessor {
    boolean processToken(int start, int end);
  } 

  private static void addWordsForEditor(EditorEx editor,
                                        final CamelHumpMatcher matcher,
                                        final CharSequence chars,
                                        final List<CompletionVariant> words,
                                        final List<CompletionVariant> afterWords, final int caretOffset) {
    int startOffset = 0;
    TokenProcessor processor = new TokenProcessor() {
      @Override
      public boolean processToken(int start, int end) {
        if ((start > caretOffset || end < caretOffset) &&  //skip prefix itself
            end - start > matcher.getPrefix().length() && isWordLike(chars, start, end)) {
          final String word = chars.subSequence(start, end).toString();
          if (matcher.isStartMatch(word)) {
            CompletionVariant v = new CompletionVariant(word, start);
            if (end > caretOffset) {
              afterWords.add(v);
            }
            else {
              words.add(v);
            }
          }
        }
        return true;
      }
    };
    processWords(editor, startOffset, processor);
  }

  private static void processWords(Editor editor, int startOffset, TokenProcessor processor) {
    CharSequence chars = editor.getDocument().getCharsSequence();
    HighlighterIterator iterator = ((EditorEx)editor).getHighlighter().createIterator(startOffset);
    while (!iterator.atEnd()) {
      int start = iterator.getStart();
      int end = iterator.getEnd();
      while (start < end) {
        int nextWs = StringUtil.indexOfAny(chars, WHITESPACE_CHARS, start, end);
        if (nextWs < 0) {
          if (isWordLike(chars, start, end) && !processor.processToken(start, end)) {
            return;
          }
          break;
        }
        if (isWordLike(chars, start, end) && !processor.processToken(start, nextWs)) {
          return;
        }
        start = CharArrayUtil.shiftForward(chars, nextWs, WHITESPACE_CHARS);
      }
      iterator.advance();
    }
  }

  private static CompletionData computeData(final Editor editor, final CharSequence charsSequence) {
    final int offset = editor.getCaretModel().getOffset();

    final CompletionData data = new CompletionData();
    
    processWords(editor, offset - 1, new TokenProcessor() {
      @Override
      public boolean processToken(int start, int end) {
        if (start > offset) {
          return false;
        }
        if (end >= offset) {
          data.myPrefix = charsSequence.subSequence(start, offset).toString();
          data.myWordUnderCursor = charsSequence.subSequence(start, end).toString();
          data.startOffset = start;
          return false;
        }
        return true;
      }
    });

    if (data.myPrefix == null) {
      data.myPrefix = "";
      data.myWordUnderCursor = "";
      data.startOffset = offset;
    }
    return data;
  }

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

  private static CompletionState getCompletionState(Editor editor) {
    CompletionState state = editor.getUserData(KEY_STATE);
    if (state == null) {
      state = new CompletionState();
      editor.putUserData(KEY_STATE, state);
    }

    return state;
  }

  private static class CompletionState {
    public String oldPrefix;
    public CompletionVariant lastProposedVariant;
  }
}
