/*
 * Copyright 2000-2015 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.findUsages;

import com.intellij.lang.cacheBuilder.WordsScanner;
import com.intellij.lang.findUsages.FindUsagesProvider;
import com.intellij.psi.*;
import com.intellij.psi.util.PsiFormatUtil;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.plugins.groovy.lang.psi.api.statements.GrLabeledStatement;
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.impl.synthetic.GrBindingVariable;
import org.jetbrains.plugins.groovy.refactoring.rename.PropertyForRename;

/**
 * @author ven
 */
public class GroovyFindUsagesProvider implements FindUsagesProvider {

    @Override
    @Nullable
    public WordsScanner getWordsScanner() {
        return new GroovyWordsScanner();
    }

    @Override
    public boolean canFindUsagesFor(@NotNull PsiElement psiElement) {
        return psiElement instanceof PsiClass ||
                psiElement instanceof PsiMethod ||
                psiElement instanceof GrVariable;
    }

    @Override
    @Nullable
    public String getHelpId(@NotNull PsiElement psiElement) {
        return null;
    }

    @Override
    @NotNull
    public String getType(@NotNull PsiElement element) {
        if (element instanceof PsiClass) return "class";
        if (element instanceof PsiMethod) return "method";
        if (element instanceof PsiField) return "field";
        if (element instanceof PsiParameter) return "parameter";
        if (element instanceof GrBindingVariable) return "script binding variable";
        if (element instanceof PsiVariable) return "variable";
        if (element instanceof GrLabeledStatement) return "label";
        if (element instanceof PropertyForRename) return "property";
        if (element instanceof GrClosableBlock) return "closure";
        return "";
    }

    @Override
    @NotNull
    public String getDescriptiveName(@NotNull PsiElement element) {
        if (element instanceof PsiClass) {
            final PsiClass aClass = (PsiClass) element;
            String qName = aClass.getQualifiedName();
            return qName == null ? "" : qName;
        } else if (element instanceof PsiMethod) {
            final PsiMethod method = (PsiMethod) element;
            String result = PsiFormatUtil.formatMethod(method,
                    PsiSubstitutor.EMPTY, PsiFormatUtil.SHOW_NAME | PsiFormatUtil.SHOW_PARAMETERS,
                    PsiFormatUtil.SHOW_TYPE);
            final PsiClass clazz = method.getContainingClass();
            if (clazz != null) {
                result += " of " + getDescriptiveName(clazz);
            }

            return result;
        } else if (element instanceof PsiVariable) {
            final String name = ((PsiVariable) element).getName();
            if (name != null) {
                return name;
            }
        } else if (element instanceof GrLabeledStatement) {
            return ((GrLabeledStatement)element).getName();
        } else if (element instanceof PropertyForRename) {
          return ((PropertyForRename)element).getPropertyName();
        } else if (element instanceof GrClosableBlock) {
          return "closure";
        }

        return "";
    }

    @Override
    @NotNull
    public String getNodeText(@NotNull PsiElement element, boolean useFullName) {
        if (element instanceof PsiClass) {
            String name = ((PsiClass) element).getQualifiedName();
            if (name == null || !useFullName) {
                name = ((PsiClass) element).getName();
            }
            if (name != null) return name;
        } else if (element instanceof PsiMethod) {
            return PsiFormatUtil.formatMethod((PsiMethod) element,
                    PsiSubstitutor.EMPTY,
                    PsiFormatUtil.SHOW_NAME | PsiFormatUtil.SHOW_PARAMETERS,
                    PsiFormatUtil.SHOW_TYPE);

        } else if (element instanceof PsiVariable) {
            final String name = ((PsiVariable) element).getName();
            if (name != null) {
                return name;
            }
        }

        return "";
    }
}

@@ -21,9 +21,9 @@
 -201
-5
+6
  Jet
@@ -644,16 +644,53 @@
 sages;%0A%0A
+import com.intellij.lang.LangBundle;%0A
 import c
@@ -1181,16 +1181,384 @@
 eBlock;%0A
+import org.jetbrains.plugins.groovy.lang.psi.api.statements.typedef.GrAnnotationTypeDefinition;%0Aimport org.jetbrains.plugins.groovy.lang.psi.api.statements.typedef.GrEnumTypeDefinition;%0Aimport org.jetbrains.plugins.groovy.lang.psi.api.statements.typedef.GrInterfaceDefinition;%0Aimport org.jetbrains.plugins.groovy.lang.psi.api.statements.typedef.GrTraitTypeDefinition;%0A
 import o
@@ -2295,32 +2295,32 @@
 de%0A    @NotNull%0A
-
     public Strin
@@ -2352,32 +2352,427 @@
 ment element) %7B%0A
+        if (element instanceof GrTraitTypeDefinition) return %22trait%22;%0A        if (element instanceof GrInterfaceDefinition) return LangBundle.message(%22java.terms.interface%22);%0A        if (element instanceof GrAnnotationTypeDefinition) return LangBundle.message(%22java.terms.annotation.interface%22);%0A        if (element instanceof GrEnumTypeDefinition) return LangBundle.message(%22java.terms.enum%22);%0A
         if (elem

return proper PsiElement type name in FU (IDEA-142282)