package com.cedricziel.idea.typo3.extbase.persistence;

import com.cedricziel.idea.typo3.extbase.ExtbaseUtils;
import com.cedricziel.idea.typo3.psi.PhpElementsUtil;
import com.cedricziel.idea.typo3.util.ExtbaseUtility;
import com.intellij.psi.util.PsiTreeUtil;
import com.jetbrains.php.PhpIndex;
import com.jetbrains.php.lang.psi.elements.*;
import com.jetbrains.php.lang.psi.resolve.PhpReferenceResolver2;
import org.apache.commons.lang.StringUtils;

import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.List;

@SuppressWarnings("UnstableApiUsage")
public class ExtbasePersistenceReferenceResolver implements PhpReferenceResolver2 {
    @Override
    public Collection<? extends PhpNamedElement> resolve(PhpReference phpReference, Collection<? extends PhpNamedElement> candidates) {
        List<PhpNamedElement> elements = new ArrayList<>();

        if (!(phpReference instanceof MethodReference)) {
            return Collections.emptyList();
        }

        String methodName = phpReference.getName();
        if (methodName == null || (!methodName.startsWith("countBy") && !methodName.startsWith("findOneBy") && !methodName.startsWith("findBy"))) {
            return Collections.emptyList();
        }

        PhpTypedElement variable = PsiTreeUtil.findChildOfType(phpReference, PhpTypedElement.class);
        if (variable == null) {
            return Collections.emptyList();
        }

        Collection<PhpClass> classesByFQN = new ArrayList<>();

        for (String s: variable.getType().getTypes()) {
            classesByFQN.addAll(PhpIndex.getInstance(phpReference.getProject()).getClassesByFQN(s));
        }

        if (classesByFQN.isEmpty()) {
            return Collections.emptyList();
        }

        classesByFQN.forEach(repositoryClass -> {
            if (!PhpElementsUtil.hasSuperClass(repositoryClass, ExtbaseUtils.TYPO3_CMS_EXTBASE_PERSISTENCE_REPOSITORY)) {
                return;
            }

            String entityFQN = ExtbaseUtility.convertRepositoryFQNToEntityFQN(repositoryClass.getFQN());
            Collection<PhpClass> entityClasses = PhpIndex.getInstance(phpReference.getProject()).getClassesByFQN(entityFQN);
            if (entityClasses.isEmpty()) {
                return;
            }

            String fieldName;
            if (methodName.startsWith("countBy")) {
                fieldName = StringUtils.uncapitalize(methodName.substring("countBy".length()));
            } else if (methodName.startsWith("findOneBy")) {
                fieldName = StringUtils.uncapitalize(methodName.substring("findOneBy".length()));
            } else if (methodName.startsWith("findBy")) {
                fieldName = StringUtils.uncapitalize(methodName.substring("findBy".length()));
            } else {
                return;
            }

            entityClasses.forEach(c -> {
                // field
                Field fieldByName = c.findFieldByName(fieldName, false);
                if (fieldByName != null) {
                    elements.add(fieldByName);
                }

                // __call method
                Method callMethod = repositoryClass.findMethodByName("__call");
                if (callMethod != null) {
                    elements.add(callMethod);
                }
            });
        });

        return elements;
    }
}

@@ -49,16 +49,74 @@
 tence;%0A%0A
+import com.cedricziel.idea.typo3.TYPO3CMSProjectSettings;%0A
 import c
@@ -458,16 +458,71 @@
 olver2;%0A
+import org.apache.commons.collections.CollectionUtils;%0A
 import o
@@ -618,61 +618,8 @@
 ion;
-%0Aimport java.util.Collections;%0Aimport java.util.List;
 %0A%0A@S
@@ -900,59 +900,104 @@
     
-List%3CPhpNamedElement%3E elements = new ArrayList%3C%3E();
+if (!TYPO3CMSProjectSettings.isEnabled(phpReference)) %7B%0A            return candidates;%0A        %7D
 %0A%0A  
@@ -1071,39 +1071,26 @@
  return 
-Collections.emptyList()
+candidates
 ;%0A      
@@ -1313,39 +1313,26 @@
  return 
-Collections.emptyList()
+candidates
 ;%0A      
@@ -1492,44 +1492,97 @@
 urn 
-Collections.empt
+candidates;%0A        %7D%0A%0A        Collection%3CPhpNamedElement%3E elements = new Arra
 yList
+%3C%3E
 ();%0A
-        %7D%0A%0A
     
@@ -1870,31 +1870,18 @@
 urn 
-Collections.emptyList()
+candidates
 ;%0A  
@@ -3472,16 +3472,90 @@
   return
+ (Collection%3C? extends PhpNamedElement%3E) CollectionUtils.union(candidates,
  element
@@ -3555,16 +3555,17 @@
 elements
+)
 ;%0A    %7D%0A

Return candidates when resolving references (#299)