/*
 * 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 org.jetbrains.plugins.groovy.codeInsight;

import com.intellij.codeHighlighting.Pass;
import com.intellij.codeInsight.daemon.DaemonCodeAnalyzerSettings;
import com.intellij.codeInsight.daemon.LineMarkerInfo;
import com.intellij.codeInsight.daemon.LineMarkerProvider;
import com.intellij.codeInsight.daemon.impl.JavaLineMarkerProvider;
import com.intellij.codeInsight.daemon.impl.MarkerType;
import com.intellij.icons.AllIcons;
import com.intellij.openapi.editor.Document;
import com.intellij.openapi.editor.colors.CodeInsightColors;
import com.intellij.openapi.editor.colors.EditorColorsManager;
import com.intellij.openapi.editor.colors.EditorColorsScheme;
import com.intellij.openapi.editor.markup.GutterIconRenderer;
import com.intellij.openapi.editor.markup.SeparatorPlacement;
import com.intellij.openapi.progress.ProgressManager;
import com.intellij.openapi.project.DumbAware;
import com.intellij.openapi.project.DumbService;
import com.intellij.openapi.project.IndexNotReadyException;
import com.intellij.openapi.util.Pair;
import com.intellij.openapi.util.TextRange;
import com.intellij.openapi.util.text.StringUtil;
import com.intellij.psi.*;
import com.intellij.psi.impl.PsiImplUtil;
import com.intellij.psi.search.searches.AllOverridingMethodsSearch;
import com.intellij.psi.search.searches.SuperMethodsSearch;
import com.intellij.psi.util.MethodSignatureBackedByPsiMethod;
import com.intellij.util.FunctionUtil;
import com.intellij.util.Processor;
import com.intellij.util.containers.HashSet;
import gnu.trove.THashSet;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.plugins.groovy.lang.groovydoc.psi.api.GrDocComment;
import org.jetbrains.plugins.groovy.lang.groovydoc.psi.api.GrDocCommentOwner;
import org.jetbrains.plugins.groovy.lang.psi.GrNamedElement;
import org.jetbrains.plugins.groovy.lang.psi.api.statements.GrClassInitializer;
import org.jetbrains.plugins.groovy.lang.psi.api.statements.GrField;
import org.jetbrains.plugins.groovy.lang.psi.api.statements.GrVariable;
import org.jetbrains.plugins.groovy.lang.psi.api.statements.blocks.GrClosableBlock;
import org.jetbrains.plugins.groovy.lang.psi.api.statements.typedef.GrTypeDefinition;
import org.jetbrains.plugins.groovy.lang.psi.api.statements.typedef.members.GrAccessorMethod;
import org.jetbrains.plugins.groovy.lang.psi.api.statements.typedef.members.GrMethod;
import org.jetbrains.plugins.groovy.lang.psi.api.statements.typedef.members.GrReflectedMethod;
import org.jetbrains.plugins.groovy.lang.psi.api.types.GrTypeParameter;
import org.jetbrains.plugins.groovy.lang.psi.impl.statements.GrVariableDeclarationImpl;
import org.jetbrains.plugins.groovy.lang.psi.impl.synthetic.GrTraitMethod;
import org.jetbrains.plugins.groovy.lang.psi.util.GrTraitUtil;
import org.jetbrains.plugins.groovy.lang.psi.util.GroovyPropertyUtils;

import javax.swing.*;
import java.util.Collection;
import java.util.Collections;
import java.util.List;
import java.util.Set;

/**
 * @author ilyas
 * Same logic as for Java LMP
 */
public class GroovyLineMarkerProvider implements LineMarkerProvider, DumbAware {
  protected final DaemonCodeAnalyzerSettings myDaemonSettings;
  protected final EditorColorsManager myColorsManager;

  public GroovyLineMarkerProvider(DaemonCodeAnalyzerSettings daemonSettings, EditorColorsManager colorsManager) {
    myDaemonSettings = daemonSettings;
    myColorsManager = colorsManager;
  }

  @Override
  public LineMarkerInfo getLineMarkerInfo(@NotNull final PsiElement element) {
    final PsiElement parent = element.getParent();
    if (parent instanceof PsiNameIdentifierOwner) {
      if (parent instanceof GrField && element == ((GrField)parent).getNameIdentifierGroovy()) {
        for (GrAccessorMethod method : GroovyPropertyUtils.getFieldAccessors((GrField)parent)) {
          MethodSignatureBackedByPsiMethod superSignature = null;
          try {
            superSignature = SuperMethodsSearch.search(method, null, true, false).findFirst();
          }
          catch (IndexNotReadyException e) {
            //some searchers (EJB) require indices. What shall we do?
          }
          if (superSignature != null) {
            PsiMethod superMethod = superSignature.getMethod();
            boolean overrides = method.hasModifierProperty(PsiModifier.ABSTRACT) == superMethod.hasModifierProperty(PsiModifier.ABSTRACT) ||
                                superMethod.getBody() != null && GrTraitUtil.isTrait(superMethod.getContainingClass());
            final Icon icon = overrides ? AllIcons.Gutter.OverridingMethod : AllIcons.Gutter.ImplementingMethod;
            final MarkerType type = GroovyMarkerTypes.OVERRIDING_PROPERTY_TYPE;
            return new LineMarkerInfo<PsiElement>(element, element.getTextRange(), icon, Pass.UPDATE_ALL, type.getTooltip(), type.getNavigationHandler(),
                                                  GutterIconRenderer.Alignment.LEFT);
          }
        }
      }
      else if (parent instanceof GrMethod &&
               element == ((GrMethod)parent).getNameIdentifierGroovy() &&
               hasSuperMethods((GrMethod)element.getParent())) {
        final Icon icon = AllIcons.Gutter.OverridingMethod;
        final MarkerType type = GroovyMarkerTypes.OVERRIDING_METHOD;
        return new LineMarkerInfo<PsiElement>(element, element.getTextRange(), icon, Pass.UPDATE_ALL, type.getTooltip(),
                                              type.getNavigationHandler(), GutterIconRenderer.Alignment.LEFT);
      }
    }
    //need to draw method separator above docComment
    if (myDaemonSettings.SHOW_METHOD_SEPARATORS && element.getFirstChild() == null) {
      PsiElement element1 = element;
      boolean isMember = false;
      while (element1 != null && !(element1 instanceof PsiFile) && element1.getPrevSibling() == null) {
        element1 = element1.getParent();
        if (element1 instanceof PsiMember || element1 instanceof GrVariableDeclarationImpl) {
          isMember = true;
          break;
        }
      }
      if (isMember && !(element1 instanceof PsiAnonymousClass || element1.getParent() instanceof PsiAnonymousClass)) {
        PsiFile file = element1.getContainingFile();
        Document document = file == null ? null : PsiDocumentManager.getInstance(file.getProject()).getDocument(file);
        boolean drawSeparator = false;
        if (document != null) {
          CharSequence documentChars = document.getCharsSequence();

          int category = getGroovyCategory(element1, documentChars);
          for (PsiElement child = element1.getPrevSibling(); child != null; child = child.getPrevSibling()) {
            int category1 = getGroovyCategory(child, documentChars);
            if (category1 == 0) continue;
            drawSeparator = category != 1 || category1 != 1;
            break;
          }
        }

        if (drawSeparator) {
          GrDocComment comment = null;
          if (element1 instanceof GrDocCommentOwner) {
            comment = ((GrDocCommentOwner)element1).getDocComment();
          }
          LineMarkerInfo info =
            new LineMarkerInfo<PsiElement>(element, comment != null ? comment.getTextRange() : element.getTextRange(), null,
                                           Pass.UPDATE_ALL, FunctionUtil.<Object, String>nullConstant(), null,
                                           GutterIconRenderer.Alignment.RIGHT);
          EditorColorsScheme scheme = myColorsManager.getGlobalScheme();
          info.separatorColor = scheme.getColor(CodeInsightColors.METHOD_SEPARATORS_COLOR);
          info.separatorPlacement = SeparatorPlacement.TOP;
          return info;
        }
      }
    }

    return null;
  }

  private static boolean hasSuperMethods(GrMethod method) {
    final GrReflectedMethod[] reflectedMethods = method.getReflectedMethods();
    if (reflectedMethods.length > 0) {
      for (GrReflectedMethod reflectedMethod : reflectedMethods) {
        final MethodSignatureBackedByPsiMethod first = SuperMethodsSearch.search(reflectedMethod, null, true, false).findFirst();
        if (first != null) return true;
      }
      return false;
    }
    else {
      return SuperMethodsSearch.search(method, null, true, false).findFirst() != null;
    }
  }

  private static int getGroovyCategory(PsiElement element, CharSequence documentChars) {
    if (element instanceof GrVariableDeclarationImpl) {
      GrVariable[] variables = ((GrVariableDeclarationImpl)element).getVariables();
      if (variables.length == 1 && variables[0] instanceof GrField && variables[0].getInitializerGroovy() instanceof GrClosableBlock) {
        return 2;
      }
    }

    if (element instanceof GrField || element instanceof GrTypeParameter) return 1;
    if (element instanceof GrTypeDefinition || element instanceof GrClassInitializer) return 2;
    if (element instanceof GrMethod) {
      if (((GrMethod)element).hasModifierProperty(PsiModifier.ABSTRACT) && !(((GrMethod)element).getBlock() != null &&
                                                                             GrTraitUtil.isTrait(((GrMethod)element).getContainingClass()))) {
        return 1;
      }
      TextRange textRange = element.getTextRange();
      int start = textRange.getStartOffset();
      int end = Math.min(documentChars.length(), textRange.getEndOffset());
      int crlf = StringUtil.getLineBreakCount(documentChars.subSequence(start, end));
      return crlf == 0 ? 1 : 2;
    }
    return 0;
  }

  @Override
  public void collectSlowLineMarkers(@NotNull final List<PsiElement> elements, @NotNull final Collection<LineMarkerInfo> result) {
    if (elements.isEmpty() || DumbService.getInstance(elements.get(0).getProject()).isDumb()) {
      return;
    }

    Set<PsiMethod> methods = new HashSet<PsiMethod>();
    for (PsiElement element : elements) {
      ProgressManager.checkCanceled();
      if (element instanceof GrField) {
        methods.addAll(GroovyPropertyUtils.getFieldAccessors((GrField)element));
      }
      else if (element instanceof GrMethod) {
        GrReflectedMethod[] reflected = ((GrMethod)element).getReflectedMethods();
        if (reflected.length != 0) {
          Collections.addAll(methods, reflected);
        }
        else {
          methods.add((PsiMethod)element);
        }
      }
      else if (element instanceof PsiClass && !(element instanceof PsiTypeParameter)) {
        JavaLineMarkerProvider.collectInheritingClasses((PsiClass)element, result);
      }
    }
    collectOverridingMethods(methods, result);
  }

  private static void collectOverridingMethods(final Set<PsiMethod> methods, Collection<LineMarkerInfo> result) {
    final Set<PsiElement> overridden = new HashSet<PsiElement>();

    Set<PsiClass> classes = new THashSet<PsiClass>();
    for (PsiMethod method : methods) {
      ProgressManager.checkCanceled();
      final PsiClass parentClass = method.getContainingClass();
      if (parentClass != null && !CommonClassNames.JAVA_LANG_OBJECT.equals(parentClass.getQualifiedName())) {
        classes.add(parentClass);
      }
    }

    for (final PsiClass aClass : classes) {
      try {
        AllOverridingMethodsSearch.search(aClass).forEach(new Processor<Pair<PsiMethod, PsiMethod>>() {
          @Override
          public boolean process(final Pair<PsiMethod, PsiMethod> pair) {
            ProgressManager.checkCanceled();

            final PsiMethod superMethod = pair.getFirst();
            if (isCorrectTarget(superMethod) && isCorrectTarget(pair.getSecond())) {
              if (methods.remove(superMethod)) {
                overridden.add(PsiImplUtil.handleMirror(superMethod));
              }
            }
            return !methods.isEmpty();
          }
        });
      }
      catch (IndexNotReadyException ignored) {
      }
    }

    for (PsiElement element : overridden) {
      final Icon icon = AllIcons.Gutter.OverridenMethod;

      element = PsiImplUtil.handleMirror(element);

      PsiElement range;
      if (element instanceof GrNamedElement) {
        range = ((GrNamedElement)element).getNameIdentifierGroovy();
      }
      else {
        range = element;
      }

      final MarkerType type = element instanceof GrField ? GroovyMarkerTypes.OVERRIDEN_PROPERTY_TYPE
                                                         : GroovyMarkerTypes.OVERRIDEN_METHOD;
      LineMarkerInfo info = new LineMarkerInfo<PsiElement>(range, range.getTextRange(), icon, Pass.UPDATE_OVERRIDEN_MARKERS, type.getTooltip(),
                                                           type.getNavigationHandler(), GutterIconRenderer.Alignment.RIGHT);
      result.add(info);
    }
  }

  private static boolean isCorrectTarget(PsiMethod method) {
    if (method instanceof GrTraitMethod) return false;

    final PsiElement navigationElement = method.getNavigationElement();
    return method.isPhysical() || navigationElement.isPhysical() && !(navigationElement instanceof PsiClass);
  }
}
