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

import com.intellij.codeInsight.CodeInsightUtilCore;
import com.intellij.openapi.diagnostic.Logger;
import com.intellij.openapi.editor.Document;
import com.intellij.openapi.editor.Editor;
import com.intellij.openapi.editor.RangeMarker;
import com.intellij.openapi.progress.ProgressManager;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.util.registry.Registry;
import com.intellij.openapi.util.text.StringUtil;
import com.intellij.psi.*;
import com.intellij.psi.impl.search.AllClassesSearchExecutor;
import com.intellij.psi.impl.source.PostprocessReformattingAspect;
import com.intellij.psi.impl.source.tree.java.PsiReferenceExpressionImpl;
import com.intellij.psi.search.GlobalSearchScope;
import com.intellij.util.Consumer;
import com.intellij.util.IncorrectOperationException;
import com.intellij.util.Processor;
import gnu.trove.THashSet;
import org.jetbrains.annotations.NotNull;

import java.util.LinkedHashSet;
import java.util.Set;

/**
 * Created by IntelliJ IDEA.
 * User: ik
 * Date: 02.12.2003
 * Time: 16:49:25
 * To change this template use Options | File Templates.
 */
public class AllClassesGetter {
  private static final Logger LOG = Logger.getInstance("#com.intellij.codeInsight.completion.AllClassesGetter");
  public static final InsertHandler<JavaPsiClassReferenceElement> TRY_SHORTENING = new InsertHandler<JavaPsiClassReferenceElement>() {

    private void _handleInsert(final InsertionContext context, final JavaPsiClassReferenceElement item) {
      final Editor editor = context.getEditor();
      final PsiClass psiClass = item.getObject();
      if (!psiClass.isValid()) return;

      int endOffset = editor.getCaretModel().getOffset();
      final String qname = psiClass.getQualifiedName();
      if (qname == null) return;

      if (endOffset == 0) return;

      final Document document = editor.getDocument();
      final PsiDocumentManager psiDocumentManager = PsiDocumentManager.getInstance(psiClass.getProject());
      final PsiFile file = context.getFile();
      if (file.findElementAt(endOffset - 1) == null) return;

      final OffsetKey key = OffsetKey.create("endOffset", false);
      context.getOffsetMap().addOffset(key, endOffset);
      PostprocessReformattingAspect.getInstance(context.getProject()).doPostponedFormatting();

      final int newOffset = context.getOffsetMap().getOffset(key);
      if (newOffset >= 0) {
        endOffset = newOffset;
      }
      else {
        LOG.error(endOffset + " became invalid: " + context.getOffsetMap() + "; inserting " + qname);
      }

      final RangeMarker toDelete = JavaCompletionUtil.insertTemporary(endOffset, document, " ");
      psiDocumentManager.commitAllDocuments();
      PsiReference psiReference = file.findReferenceAt(endOffset - 1);

      boolean insertFqn = true;
      if (psiReference != null) {
        final PsiManager psiManager = file.getManager();
        if (psiManager.areElementsEquivalent(psiClass, JavaCompletionUtil.resolveReference(psiReference))) {
          insertFqn = false;
        }
        else if (psiClass.isValid()) {
          try {
            context.setTailOffset(psiReference.getRangeInElement().getEndOffset() + psiReference.getElement().getTextRange().getStartOffset());
            final PsiElement newUnderlying = psiReference.bindToElement(psiClass);
            if (newUnderlying != null) {
              final PsiElement psiElement = CodeInsightUtilCore.forcePsiPostprocessAndRestoreElement(newUnderlying);
              if (psiElement != null) {
                for (final PsiReference reference : psiElement.getReferences()) {
                  if (psiManager.areElementsEquivalent(psiClass, JavaCompletionUtil.resolveReference(reference))) {
                    insertFqn = false;
                    break;
                  }
                }
              }
            }
          }
          catch (IncorrectOperationException e) {
            //if it's empty we just insert fqn below
          }
        }
      }
      if (toDelete.isValid()) {
        document.deleteString(toDelete.getStartOffset(), toDelete.getEndOffset());
        context.setTailOffset(toDelete.getStartOffset());
      }

      if (insertFqn) {
        INSERT_FQN.handleInsert(context, item);
      }
    }

    @Override
    public void handleInsert(final InsertionContext context, final JavaPsiClassReferenceElement item) {
      _handleInsert(context, item);
      item.getTailType().processTail(context.getEditor(), context.getEditor().getCaretModel().getOffset());
    }

  };

  public static final InsertHandler<JavaPsiClassReferenceElement> INSERT_FQN = new InsertHandler<JavaPsiClassReferenceElement>() {
    @Override
    public void handleInsert(InsertionContext context, JavaPsiClassReferenceElement item) {
      final String qName = item.getQualifiedName();
      if (qName != null) {
        int start = context.getTailOffset() - 1;
        while (start >= 0) {
          final char ch = context.getDocument().getCharsSequence().charAt(start);
          if (!Character.isJavaIdentifierPart(ch) && ch != '.') break;
          start--;
        }
        context.getDocument().replaceString(start + 1, context.getTailOffset(), qName);
        LOG.assertTrue(context.getTailOffset() >= 0);
      }
    }
  };

  public static void processJavaClasses(@NotNull final CompletionParameters parameters,
                                        @NotNull final PrefixMatcher prefixMatcher,
                                        final boolean filterByScope,
                                        @NotNull final Consumer<PsiClass> consumer) {
    final PsiElement context = parameters.getPosition();
    final Project project = context.getProject();
    final GlobalSearchScope scope = filterByScope ? context.getContainingFile().getResolveScope() : GlobalSearchScope.allScope(project);

    Processor<PsiClass> processor = new Processor<PsiClass>() {
      final Set<String> qNames = new THashSet<String>();
      final boolean pkgContext = JavaCompletionUtil.inSomePackage(context);
      final String packagePrefix = getPackagePrefix(context, parameters.getOffset());

      @Override
      public boolean process(PsiClass psiClass) {
        if (parameters.getInvocationCount() < 2) {
          if (PsiReferenceExpressionImpl.seemsScrambled(psiClass)) {
            return true;
          }
          if (!StringUtil.isCapitalized(psiClass.getName()) && !Registry.is("ide.completion.show.lower.case.classes")) {
            return true;
          }
        }

        assert psiClass != null;
        if (isAcceptableInContext(context, psiClass, filterByScope, pkgContext)) {
          String qName = psiClass.getQualifiedName();
          if (qName != null && qName.startsWith(packagePrefix) && qNames.add(qName)) {
            consumer.consume(psiClass);
          }
        }
        return true;
      }
    };
    processJavaClasses(prefixMatcher, project, scope, processor);
  }

  public static void processJavaClasses(@NotNull final PrefixMatcher prefixMatcher,
                                        @NotNull Project project,
                                        @NotNull GlobalSearchScope scope,
                                        @NotNull Processor<PsiClass> processor) {
    final Set<String> names = new THashSet<String>(10000);
    AllClassesSearchExecutor.processClassNames(project, scope, new Consumer<String>() {
      @Override
      public void consume(String s) {
        if (prefixMatcher.prefixMatches(s)) {
          names.add(s);
        }
      }
    });
    LinkedHashSet<String> sorted = CompletionUtil.sortMatching(prefixMatcher, names);
    AllClassesSearchExecutor.processClassesByNames(project, scope, sorted, processor);
  }


  private static String getPackagePrefix(final PsiElement context, final int offset) {
    final CharSequence fileText = context.getContainingFile().getViewProvider().getContents();
    int i = offset - 1;
    while (i >= 0) {
      final char c = fileText.charAt(i);
      if (!Character.isJavaIdentifierPart(c) && c != '.') break;
      i--;
    }
    String prefix = fileText.subSequence(i + 1, offset).toString();
    final int j = prefix.lastIndexOf('.');
    return j > 0 ? prefix.substring(0, j) : "";
  }

  public static boolean isAcceptableInContext(@NotNull final PsiElement context,
                                              @NotNull final PsiClass psiClass,
                                              final boolean filterByScope, final boolean pkgContext) {
    ProgressManager.checkCanceled();

    if (!context.isValid() || !psiClass.isValid()) return false;

    if (JavaCompletionUtil.isInExcludedPackage(psiClass, false)) return false;

    final String qualifiedName = psiClass.getQualifiedName();
    if (qualifiedName == null) return false;

    if (!filterByScope && !(psiClass instanceof PsiCompiledElement)) return true;

    return JavaCompletionUtil.isSourceLevelAccessible(context, psiClass, pkgContext);
  }

  public static JavaPsiClassReferenceElement createLookupItem(@NotNull final PsiClass psiClass,
                                               final InsertHandler<JavaPsiClassReferenceElement> insertHandler) {
    final JavaPsiClassReferenceElement item = new JavaPsiClassReferenceElement(psiClass);
    item.setInsertHandler(insertHandler);
    return item;
  }

}
