/*
 * Copyright 2000-2013 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.jetbrains.python.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.icons.AllIcons;
import com.intellij.lang.ASTNode;
import com.intellij.psi.PsiElement;
import com.intellij.psi.util.PsiTreeUtil;
import com.intellij.util.CollectionQuery;
import com.intellij.util.Function;
import com.intellij.util.Processor;
import com.intellij.util.Query;
import com.intellij.util.containers.HashSet;
import com.intellij.util.containers.MultiMap;
import com.jetbrains.python.PyNames;
import com.jetbrains.python.PyTokenTypes;
import com.jetbrains.python.psi.PyClass;
import com.jetbrains.python.psi.PyFunction;
import com.jetbrains.python.psi.PyTargetExpression;
import com.jetbrains.python.psi.PyUtil;
import com.jetbrains.python.psi.search.PyClassInheritorsSearch;
import com.jetbrains.python.psi.search.PyOverridingMethodsSearch;
import com.jetbrains.python.psi.search.PySuperMethodsSearch;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;

import java.util.*;
import java.util.concurrent.atomic.AtomicInteger;

/**
 * @author yole
 */
public class PyLineMarkerProvider implements LineMarkerProvider, PyLineSeparatorUtil.Provider {

  private static class TooltipProvider implements Function<PsiElement, String> {
    private final String myText;

    private TooltipProvider(String text) {
      myText = text;
    }

    public String fun(PsiElement psiElement) {
      return myText;
    }
  }

  private static final Function<PyClass, String> ourSubclassTooltipProvider = new Function<PyClass, String>() {
    public String fun(PyClass pyClass) {
      final StringBuilder builder = new StringBuilder("<html>Is subclassed by:");
      final AtomicInteger count = new AtomicInteger();
      PyClassInheritorsSearch.search(pyClass, true).forEach(new Processor<PyClass>() {
        public boolean process(PyClass pyClass) {
          if (count.incrementAndGet() >= 10) {
            builder.setLength(0);
            builder.append("Has subclasses");
            return false;
          }
          builder.append("<br>&nbsp;&nbsp;").append(pyClass.getName());
          return true;
        }
      });
      return builder.toString();
    }
  };

  private static final Function<PyFunction, String> ourOverridingMethodTooltipProvider = new Function<PyFunction, String>() {
    public String fun(final PyFunction pyFunction) {
      final StringBuilder builder = new StringBuilder("<html>Is overridden in:");
      final AtomicInteger count = new AtomicInteger();
      PyClassInheritorsSearch.search(pyFunction.getContainingClass(), true).forEach(new Processor<PyClass>() {
        public boolean process(PyClass pyClass) {
          if (count.incrementAndGet() >= 10) {
            builder.setLength(0);
            builder.append("Has overridden methods");
            return false;
          }
          if (pyClass.findMethodByName(pyFunction.getName(), false) != null) {
            builder.append("<br>&nbsp;&nbsp;").append(pyClass.getName());
          }
          return true;
        }
      });
      return builder.toString();
    }
  };

  private static final PyLineMarkerNavigator<PsiElement> ourSuperMethodNavigator = new PyLineMarkerNavigator<PsiElement>() {
    protected String getTitle(final PsiElement elt) {
      return "Choose Super Method of " + ((PyFunction)elt.getParent()).getName();
    }

    @Nullable
    protected Query<PsiElement> search(final PsiElement elt) {
      if (!(elt.getParent() instanceof PyFunction)) return null;
      return PySuperMethodsSearch.search((PyFunction)elt.getParent());
    }
  };

  private static final PyLineMarkerNavigator<PsiElement> ourSuperAttributeNavigator = new PyLineMarkerNavigator<PsiElement>() {
    protected String getTitle(final PsiElement elt) {
      return "Choose Super Attribute of " + ((PyTargetExpression)elt).getName();
    }

    @Nullable
    protected Query<PsiElement> search(final PsiElement elt) {
      List<PsiElement> result = new ArrayList<PsiElement>();
      PyClass containingClass = PsiTreeUtil.getParentOfType(elt, PyClass.class);
      if (containingClass != null && elt instanceof PyTargetExpression) {
        for (PyClass ancestor : containingClass.getAncestorClasses()) {
          final PyTargetExpression attribute = ancestor.findClassAttribute(((PyTargetExpression)elt).getReferencedName(), false);
          if (attribute != null) {
            result.add(attribute);
          }
        }
      }
      return new CollectionQuery<PsiElement>(result);
    }
  };

  private static final PyLineMarkerNavigator<PyClass> ourSubclassNavigator = new PyLineMarkerNavigator<PyClass>() {
    protected String getTitle(final PyClass elt) {
      return "Choose Subclass of "+ elt.getName();
    }

    protected Query<PyClass> search(final PyClass elt) {
      return PyClassInheritorsSearch.search(elt, true);
    }
  };

  private static final PyLineMarkerNavigator<PyFunction> ourOverridingMethodNavigator = new PyLineMarkerNavigator<PyFunction>() {
    protected String getTitle(final PyFunction elt) {
      return "Choose Overriding Method of " + elt.getName();
    }

    protected Query<PyFunction> search(final PyFunction elt) {
      return PyOverridingMethodsSearch.search(elt, true);
    }
  };

  public LineMarkerInfo getLineMarkerInfo(@NotNull final PsiElement element) {
    final ASTNode node = element.getNode();
    if (node != null && node.getElementType() == PyTokenTypes.IDENTIFIER && element.getParent() instanceof PyFunction) {
      final PyFunction function = (PyFunction)element.getParent();
      return getMethodMarker(element, function);
    }
    if (element instanceof PyTargetExpression && PyUtil.isClassAttribute(element)) {
      return getAttributeMarker((PyTargetExpression) element);
    }
    if (DaemonCodeAnalyzerSettings.getInstance().SHOW_METHOD_SEPARATORS && isSeparatorAllowed(element)) {
      return PyLineSeparatorUtil.addLineSeparatorIfNeeded(this, element);
    }
    return null;
  }

  public boolean isSeparatorAllowed(PsiElement element) {
    return element instanceof PyFunction || element instanceof PyClass;
  }

  @Nullable
  private static LineMarkerInfo<PsiElement> getMethodMarker(final PsiElement element, final PyFunction function) {
    if (PyNames.INIT.equals(function.getName())) {
      return null;      
    }
    final PsiElement superMethod = PySuperMethodsSearch.search(function).findFirst();
    if (superMethod != null) {
      PyClass superClass = null;
      if (superMethod instanceof PyFunction) {
        superClass = ((PyFunction)superMethod).getContainingClass();
      }
      // TODO: show "implementing" instead of "overriding" icon for Python implementations of Java interface methods
      return new LineMarkerInfo<PsiElement>(element, element.getTextRange().getStartOffset(), AllIcons.Gutter.OverridingMethod, Pass.UPDATE_ALL,
                                            superClass == null ? null : new TooltipProvider("Overrides method in " + superClass.getName()),
                                            ourSuperMethodNavigator);
    }
    return null;
  }

  @Nullable
  private static LineMarkerInfo<PsiElement> getAttributeMarker(PyTargetExpression element) {
    final String name = element.getReferencedName();
    if (name == null) {
      return null;
    }
    PyClass containingClass = PsiTreeUtil.getParentOfType(element, PyClass.class);
    if (containingClass == null) return null;
    for (PyClass ancestor : containingClass.getAncestorClasses()) {
      final PyTargetExpression ancestorAttr = ancestor.findClassAttribute(name, false);
      if (ancestorAttr != null) {
        return new LineMarkerInfo<PsiElement>(element, element.getTextRange().getStartOffset(),
                                              AllIcons.Gutter.OverridingMethod, Pass.UPDATE_ALL,
                                              new TooltipProvider("Overrides attribute in " + ancestor.getName()),
                                              ourSuperAttributeNavigator);
      }
    }
    return null;
  }

  public void collectSlowLineMarkers(@NotNull final List<PsiElement> elements, @NotNull final Collection<LineMarkerInfo> result) {
    Set<PyFunction> functions = new HashSet<PyFunction>();
    for(PsiElement element: elements) {
      if (element instanceof PyClass) {
        collectInheritingClasses((PyClass) element, result);
      }
      else if (element instanceof PyFunction) {
        functions.add((PyFunction)element);
      }
    }
    collectOverridingMethods(functions, result);
  }

  private static void collectInheritingClasses(final PyClass element, final Collection<LineMarkerInfo> result) {
    if (PyClassInheritorsSearch.search(element, false).findFirst() != null) {
      result.add(new LineMarkerInfo<PyClass>(element, element.getTextOffset(), AllIcons.Gutter.OverridenMethod, Pass.UPDATE_OVERRIDEN_MARKERS,
                                             ourSubclassTooltipProvider, ourSubclassNavigator));
    }
  }

  private static void collectOverridingMethods(final Set<PyFunction> functions, final Collection<LineMarkerInfo> result) {
    Set<PyClass> classes = new HashSet<PyClass>();
    final MultiMap<PyClass, PyFunction> candidates = new MultiMap<PyClass, PyFunction>();
    for(PyFunction function: functions) {
      PyClass pyClass = function.getContainingClass();
      if (pyClass != null && function.getName() != null) {
        classes.add(pyClass);
        candidates.putValue(pyClass, function);
      }
    }
    final Set<PyFunction> overridden = new HashSet<PyFunction>();
    for(final PyClass pyClass: classes) {
      PyClassInheritorsSearch.search(pyClass, true).forEach(new Processor<PyClass>() {
        public boolean process(final PyClass inheritor) {
          for (Iterator<PyFunction> it = candidates.get(pyClass).iterator(); it.hasNext();) {
            PyFunction func = it.next();
            if (inheritor.findMethodByName(func.getName(), false) != null) {
              overridden.add(func);
              it.remove();
            }
          }
          return !candidates.isEmpty();
        }
      });
      if (candidates.isEmpty()) break;
    }
    for(PyFunction func: overridden) {
      result.add(new LineMarkerInfo<PyFunction>(func, func.getTextOffset(), AllIcons.Gutter.OverridenMethod, Pass.UPDATE_OVERRIDEN_MARKERS,
                                                ourOverridingMethodTooltipProvider,
                                                ourOverridingMethodNavigator));
    }
  }
}
