/*
 * Copyright 2013-2014 must-be.org
 *
 * 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.mustbe.consulo.csharp.ide.lineMarkerProvider;

import java.awt.event.MouseEvent;
import java.util.Collection;

import org.jetbrains.annotations.NotNull;
import org.mustbe.consulo.csharp.lang.psi.CSharpModifier;
import org.mustbe.consulo.csharp.lang.psi.CSharpTokens;
import org.mustbe.consulo.csharp.lang.psi.CSharpTypeDeclaration;
import org.mustbe.consulo.csharp.lang.psi.impl.resolve.CSharpPsiSearcher;
import org.mustbe.consulo.dotnet.psi.DotNetTypeDeclaration;
import com.intellij.codeHighlighting.Pass;
import com.intellij.codeInsight.daemon.GutterIconNavigationHandler;
import com.intellij.codeInsight.daemon.LineMarkerInfo;
import com.intellij.codeInsight.navigation.NavigationUtil;
import com.intellij.icons.AllIcons;
import com.intellij.openapi.editor.markup.GutterIconRenderer;
import com.intellij.openapi.ui.popup.JBPopup;
import com.intellij.psi.PsiElement;
import com.intellij.ui.awt.RelativePoint;
import com.intellij.util.ArrayUtil;
import com.intellij.util.Function;
import lombok.val;

/**
 * @author VISTALL
 * @since 25.03.14
 */
public class PartialTypeCollector implements LineMarkerCollector
{
	@Override
	public void collect(PsiElement psiElement, @NotNull Collection<LineMarkerInfo> lineMarkerInfos)
	{
		if(psiElement.getParent() instanceof CSharpTypeDeclaration && psiElement.getNode().getElementType() == CSharpTokens.IDENTIFIER)
		{
			CSharpTypeDeclaration parent = (CSharpTypeDeclaration) psiElement.getParent();

			if(!parent.hasModifier(CSharpModifier.PARTIAL))
			{
				return;
			}

			val vmQName = parent.getVmQName();
			assert vmQName != null;
			DotNetTypeDeclaration[] types = CSharpPsiSearcher.getInstance(parent.getProject()).findTypes(vmQName, parent.getResolveScope());

			if(types.length > 1 && ArrayUtil.contains(parent, types))
			{
				val lineMarkerInfo = new LineMarkerInfo<PsiElement>(psiElement, psiElement.getTextRange(), AllIcons.Nodes.TreeDownArrow,
						Pass.UPDATE_OVERRIDEN_MARKERS, new Function<PsiElement, String>()

				{
					@Override
					public String fun(PsiElement element)
					{
						return "Navigate to partial types";
					}
				}, new GutterIconNavigationHandler<PsiElement>()
				{
					@Override
					public void navigate(MouseEvent mouseEvent, PsiElement element)
					{
						val typeDeclaration = (DotNetTypeDeclaration) element.getParent();

						DotNetTypeDeclaration[] types = CSharpPsiSearcher.getInstance(typeDeclaration.getProject()).findTypes(vmQName,
								typeDeclaration.getResolveScope());

						DotNetTypeDeclaration[] newArray = ArrayUtil.remove(types, typeDeclaration);

						JBPopup popup = NavigationUtil.getPsiElementPopup(newArray, "Open types (" + newArray.length + " items)");
						popup.show(new RelativePoint(mouseEvent));
					}
				}, GutterIconRenderer.Alignment.LEFT
				);
				lineMarkerInfos.add(lineMarkerInfo);
			}
		}
	}
}

@@ -755,16 +755,59 @@
 otNull;%0A
+import org.jetbrains.annotations.Nullable;%0A
 import o
@@ -1368,24 +1368,81 @@
 s.AllIcons;%0A
+import com.intellij.ide.util.PsiElementListCellRenderer;%0A
 import com.i
@@ -1561,22 +1561,218 @@
 lij.
-psi.PsiElement
+openapi.util.Iconable;%0Aimport com.intellij.openapi.vfs.VirtualFile;%0Aimport com.intellij.psi.PsiElement;%0Aimport com.intellij.psi.presentation.java.SymbolPresentationUtil;%0Aimport com.intellij.psi.util.PsiUtilCore
 ;%0Aim
@@ -2015,16 +2015,839 @@
 ector%0A%7B%0A
+%09private static class OurRender extends PsiElementListCellRenderer%3CPsiElement%3E%0A%09%7B%0A%09%09@Override%0A%09%09public String getElementText(PsiElement element)%0A%09%09%7B%0A%09%09%09VirtualFile virtualFile = PsiUtilCore.getVirtualFile(element);%0A%09%09%09return virtualFile == null ? SymbolPresentationUtil.getSymbolPresentableText(element) : virtualFile.getName();%0A%09%09%7D%0A%0A%09%09@Nullable%0A%09%09@Override%0A%09%09protected String getContainerText(PsiElement element, String name)%0A%09%09%7B%0A%09%09%09VirtualFile virtualFile = PsiUtilCore.getVirtualFile(element);%0A%09%09%09if(virtualFile == null)%0A%09%09%09%7B%0A%09%09%09%09return SymbolPresentationUtil.getSymbolContainerText(element);%0A%09%09%09%7D%0A%09%09%09else%0A%09%09%09%7B%0A%09%09%09%09VirtualFile parent = virtualFile.getParent();%0A%09%09%09%09return parent == null ? null : parent.getPath();%0A%09%09%09%7D%0A%09%09%7D%0A%0A%09%09@Override%0A%09%09protected int getIconFlags()%0A%09%09%7B%0A%09%09%09return Iconable.ICON_FLAG_VISIBILITY;%0A%09%09%7D%0A%09%7D%0A%0A
 %09@Overri
@@ -4357,16 +4357,33 @@
 ewArray,
+ new OurRender(),
  %22Open t

improve render for partial linemarker due dont need show list of duplicates