package de.espend.idea.shopware;

import com.intellij.openapi.application.ApplicationManager;
import com.intellij.openapi.components.ProjectComponent;
import com.intellij.openapi.progress.ProgressIndicator;
import com.intellij.openapi.progress.ProgressManager;
import com.intellij.openapi.progress.Task;
import com.intellij.openapi.project.DumbService;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.startup.StartupManager;
import com.intellij.openapi.vfs.VfsUtil;
import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.psi.PsiElement;
import com.intellij.psi.search.GlobalSearchScope;
import com.intellij.util.indexing.FileBasedIndex;
import com.jetbrains.php.lang.PhpFileType;
import de.espend.idea.shopware.index.EventConfigGoToIndex;
import de.espend.idea.shopware.util.HookSubscriberUtil;
import de.espend.idea.shopware.util.ShopwareUtil;
import de.espend.idea.shopware.util.dict.PsiParameterStorageRunnable;
import fr.adrienbrault.idea.symfony2plugin.Symfony2ProjectComponent;
import fr.adrienbrault.idea.symfony2plugin.util.PhpElementsUtil;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;

import java.util.*;

/**
 * @author Daniel Espendiller <daniel@espendiller.net>
 */
public class ShopwareProjectComponent implements ProjectComponent {

    private static final int DUMPER_PERIODE = 600 * 1000;

    private final Project project;
    private Timer timer;

    public ShopwareProjectComponent(Project project) {
        this.project = project;
    }

    @Override
    public void projectOpened() {

        if(!Symfony2ProjectComponent.isEnabled(project)) {
            return;
        }

        StartupManager.getInstance(project).runWhenProjectIsInitialized(() -> {
            timer = new Timer();
            timer.schedule(new MyTimerTask(), 0, DUMPER_PERIODE);
        });
    }

    @Override
    public void projectClosed() {
        if(this.timer != null) {
            this.timer.cancel();
            timer.purge();
            timer = null;
        }
    }

    @Override
    public void initComponent() {

    }

    @Override
    public void disposeComponent() {

    }

    public static boolean isValidForProject(@Nullable PsiElement psiElement) {
        if(ApplicationManager.getApplication().isUnitTestMode()) {
            return true;
        }

        return psiElement != null && isValidForProject(psiElement.getProject());
    }

    public static boolean isValidForProject(@Nullable Project project) {
        if(project == null || Symfony2ProjectComponent.isEnabled(project)) {
            return true;
        }

        if(VfsUtil.findRelativeFile(project.getBaseDir(), "engine", "Shopware", "Kernel.php") != null) {
            return true;
        }

        return PhpElementsUtil.getClassInterface(project, "\\Enlight_Controller_Action") != null;
    }


    @NotNull
    @Override
    public String getComponentName() {
        return "Shopware Plugin";
    }

    private class MyTimerTask extends TimerTask {
        public void run() {
            DumbService.getInstance(project).smartInvokeLater(() -> {
                if (DumbService.getInstance(project).isDumb()) {
                    return;
                }

                if (PhpElementsUtil.getClassInterface(project, "\\Enlight_Controller_Action") == null) {
                    return;
                }

                ProgressManager.getInstance().run(new Task.Backgroundable(project, "Shopware: Event indexer", false) {
                    @Override
                    public void run(@NotNull ProgressIndicator progressIndicator) {
                        final Map<String, Collection<String>> events = new HashMap<>();
                        final Set<String> configs = new HashSet<>();

                        final Collection<VirtualFile> containingFiles = new HashSet<>();

                        for (String methodName : EventConfigGoToIndex.METHOD_NAMES) {
                            ApplicationManager.getApplication().runReadAction(() -> {
                                FileBasedIndex.getInstance().getFilesWithKey(EventConfigGoToIndex.KEY, new HashSet<>(Collections.singletonList(methodName)), virtualFile -> {
                                    containingFiles.add(virtualFile);
                                    return true;
                                }, GlobalSearchScope.getScopeRestrictedByFileTypes(GlobalSearchScope.allScope(project), PhpFileType.INSTANCE));
                            });
                        }

                        DumbService.getInstance(project).smartInvokeLater(() -> {
                            for (VirtualFile virtualFile : containingFiles) {
                                ApplicationManager.getApplication().runReadAction(new PsiParameterStorageRunnable(project, virtualFile, events, configs));
                            }

                            HookSubscriberUtil.NOTIFY_EVENTS_MAP.clear();
                            HookSubscriberUtil.NOTIFY_EVENTS_MAP.putAll(events);

                            ShopwareUtil.PLUGIN_CONFIGS.clear();
                            ShopwareUtil.PLUGIN_CONFIGS.addAll(configs);
                        });
                    }
                });
            });
        }
    }
}

@@ -3617,24 +3617,110 @@
 ndicator) %7B%0A
+                        DumbService.getInstance(project).smartInvokeLater(() -%3E %7B%0A    
             
@@ -3791,24 +3791,28 @@
 ashMap%3C%3E();%0A
+    
             
@@ -3889,24 +3889,28 @@
             
+    
 final Collec
@@ -3983,24 +3983,28 @@
             
+    
 for (String 
@@ -4049,24 +4049,28 @@
 OD_NAMES) %7B%0A
+    
             
@@ -4175,16 +4175,20 @@
         
+    
 FileBase
@@ -4357,16 +4357,20 @@
         
+    
 containi
@@ -4423,32 +4423,36 @@
                 
+    
 return true;%0A   
@@ -4480,16 +4480,20 @@
         
+ 
+   
 %7D, Globa
@@ -4608,32 +4608,8 @@
     
-                    %7D);%0A
     
@@ -4621,33 +4621,34 @@
                %7D
-%0A
+);
 %0A               
@@ -4660,65 +4660,14 @@
     
-DumbService.getInstance(project).smartInvokeLater(() -%3E %7B
+    %7D%0A
 %0A   

move index background also in a smart invoker to fix index error messages