package com.cedricziel.idea.typo3.extensionScanner.codeInspection;

import com.intellij.codeInsight.daemon.GroupNames;
import com.intellij.codeInspection.ProblemsHolder;
import com.intellij.patterns.PlatformPatterns;
import com.intellij.psi.PsiElement;
import com.intellij.psi.PsiElementVisitor;
import com.intellij.psi.PsiFile;
import com.intellij.psi.search.FilenameIndex;
import com.intellij.psi.search.GlobalSearchScope;
import com.intellij.psi.search.PsiElementProcessor;
import com.intellij.psi.util.PsiTreeUtil;
import com.jetbrains.php.lang.inspections.PhpInspection;
import com.jetbrains.php.lang.parser.PhpElementTypes;
import com.jetbrains.php.lang.psi.elements.MethodReference;
import com.jetbrains.php.lang.psi.elements.PhpPsiElement;
import com.jetbrains.php.lang.psi.elements.StringLiteralExpression;
import com.jetbrains.php.lang.psi.visitors.PhpElementVisitor;
import org.jetbrains.annotations.Nls;
import org.jetbrains.annotations.NotNull;

import java.util.*;

public class MethodArgumentDroppedMatcherInspection extends PhpInspection {
    @Nls
    @NotNull
    @Override
    public String getGroupDisplayName() {
        return GroupNames.BUGS_GROUP_NAME;
    }

    @NotNull
    public String getDisplayName() {
        return "Number of arguments changed with TYPO3 9";
    }

    @NotNull
    @Override
    public PsiElementVisitor buildVisitor(@NotNull ProblemsHolder problemsHolder, boolean b) {
        return new PhpElementVisitor() {
            @Override
            public void visitPhpElement(PhpPsiElement element) {

                if (!PlatformPatterns.psiElement(PhpElementTypes.METHOD_REFERENCE).accepts(element)) {
                    return;
                }

                Map<String, Integer> changedMethods = getChangedMethods(element);
                MethodReference methodReference = (MethodReference) element;
                if (methodReference.getClassReference() != null && changedMethods.containsKey(methodReference.getClassReference().getInferredType() + "->" + methodReference.getText())) {
                    problemsHolder.registerProblem(element, "Number of arguments changed with TYPO3 9, consider using an alternative");
                }
            }
        };
    }

    private Map<String, Integer> getChangedMethods(PhpPsiElement element) {
        Set<PsiElement> elements = new HashSet<>();
        PsiFile[] classConstantMatcherFiles = FilenameIndex.getFilesByName(element.getProject(), "MethodArgumentDroppedMatcher.php", GlobalSearchScope.allScope(element.getProject()));
        for (PsiFile file : classConstantMatcherFiles) {

            Collections.addAll(
                    elements,
                    PsiTreeUtil.collectElements(file, el -> PlatformPatterns
                            .psiElement(StringLiteralExpression.class)
                            .withParent(
                                    PlatformPatterns.psiElement(PhpElementTypes.ARRAY_KEY)
                                            .withAncestor(
                                                    4,
                                                    PlatformPatterns.psiElement(PhpElementTypes.RETURN)
                                            )
                            )
                            .accepts(el)
                    )
            );
        }

        Map<String, Integer> methodMap = new HashMap<>();
        for (PsiElement gatheredElement : elements) {
            PsiElement[] numberOfArgumentsNumbers = PsiTreeUtil.processElements(
                    gatheredElement,
                    new PsiElementProcessor() {
                        @Override
                        public boolean execute(@NotNull PsiElement element) {
                            return false;
                        }
                    }
            );

            for (PsiElement el : numberOfArgumentsNumbers) {
                methodMap.put("\\" + ((StringLiteralExpression) gatheredElement).getContents(), Integer.parseInt(el.getFirstChild().getFirstChild().getText()));
            }
        }

        return methodMap;
    }
}

@@ -422,60 +422,8 @@
 pe;%0A
-import com.intellij.psi.search.PsiElementProcessor;%0A
 impo
@@ -614,31 +614,17 @@
 lements.
-MethodReference
+*
 ;%0Aimport
@@ -655,98 +655,29 @@
 psi.
-elements.PhpPsiElement;%0Aimport com.jetbrains.php.lang.psi.elements.StringLiteralExpression
+resolve.types.PhpType
 ;%0Aim
@@ -1738,126 +1738,474 @@
     
-if (methodReference.getClassReference() != null && changedMethods.containsKey(methodReference.getClassReference()
+ParameterList parameterList = methodReference.getParameterList();%0A                PhpExpression classReference = methodReference.getClassReference();%0A                if (classReference != null) %7B%0A                    PhpType inferredType = classReference.getInferredType();%0A                    if (changedMethods.containsKey(inferredType.toString() + %22-%3E%22 + methodReference.getName())) %7B%0A                        Integer maximumNumberOfArguments = changedMethods
 .get
-I
+(i
 nfer
@@ -2211,16 +2211,25 @@
 rredType
+.toString
 () + %22-%3E
@@ -2255,19 +2255,115 @@
 .get
-Text())) %7B%0A
+Name());%0A                        if (parameterList.getParameters().length != maximumNumberOfArguments)%0A    
     
@@ -2474,31 +2474,44 @@
 der 
-using an alternative%22);
+refactoring%22);%0A                    %7D
 %0A   
@@ -3706,24 +3706,25 @@
 ashMap%3C%3E();%0A
+%0A
         for 
@@ -3791,103 +3791,112 @@
 ment
-%5B%5D numberOfArgumentsNumbers = PsiTreeUtil.processElements(%0A                    gathered
+ parent = gatheredElement.getParent().getParent();%0A            if (parent instanceof ArrayHash
 Element
-,
+) %7B
 %0A   
@@ -3912,191 +3912,288 @@
     
-    new PsiElementProcessor() %7B%0A                        @Override%0A                        public boolean execute(@NotNull PsiElement element) %7B%0A                            return fals
+ArrayHashElement arr = (ArrayHashElement) parent;%0A                PhpPsiElement value = arr.getValue();%0A                if (value != null && value instanceof ArrayCreationExpression) %7B%0A                    ArrayCreationExpression creationExpression = (ArrayCreationExpression) valu
 e;%0A 
@@ -4215,35 +4215,59 @@
     
-    %7D%0A                    %7D
+creationExpression.getHashElements().forEach(x -%3E %7B
 %0A   
@@ -4275,20 +4275,16 @@
         
-);%0A%0A
         
@@ -4291,57 +4291,85 @@
     
-for (PsiElement el : numberOfArgumentsNumbers) %7B%0A
+if (x.getKey().getText().contains(%22maximumNumberOfArguments%22)) %7B%0A            
     
@@ -4481,55 +4481,101 @@
 Int(
-el
+x
 .get
-FirstChild().getFirstChild().getText()));
+Value().getText()));%0A                        %7D%0A                    %7D);%0A                %7D
 %0A   

Correct MethodArgumentDroppedMatcherInspection