package de.espend.idea.shopware.index;

import com.intellij.lang.javascript.JavaScriptFileType;
import com.intellij.lang.javascript.psi.JSFile;
import com.intellij.openapi.fileTypes.FileType;
import com.intellij.psi.PsiFile;
import com.intellij.util.indexing.*;
import com.intellij.util.io.DataExternalizer;
import com.intellij.util.io.EnumeratorStringDescriptor;
import com.intellij.util.io.KeyDescriptor;
import com.jetbrains.smarty.SmartyFile;
import com.jetbrains.smarty.SmartyFileType;
import de.espend.idea.shopware.util.SnippetUtil;
import de.espend.idea.shopware.util.dict.ShopwareSnippet;
import fr.adrienbrault.idea.symfony2plugin.Symfony2ProjectComponent;
import fr.adrienbrault.idea.symfony2plugin.stubs.indexes.externalizer.StringSetDataExternalizer;
import gnu.trove.THashMap;
import org.jetbrains.annotations.NotNull;

import java.util.Collections;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;

public class SnippetIndex extends FileBasedIndexExtension<String, Set<String>> {

    public static final ID<String, Set<String>> KEY = ID.create("de.espend.idea.shopware.snippets");
    private final KeyDescriptor<String> myKeyDescriptor = new EnumeratorStringDescriptor();

    @NotNull
    @Override
    public ID<String, Set<String>> getName() {
        return KEY;
    }

    @NotNull
    @Override
    public DataIndexer<String, Set<String>, FileContent> getIndexer() {
        return inputData -> {
            if(!Symfony2ProjectComponent.isEnabled(inputData.getProject())) {
                return Collections.emptyMap();
            }

            final Map<String, Set<String>> snippets = new THashMap<>();

            PsiFile psiFile = inputData.getPsiFile();
            if (psiFile instanceof SmartyFile) {
                // template files

                for (ShopwareSnippet snippet : SnippetUtil.getSnippetsInFile((SmartyFile) psiFile)) {
                    snippets.putIfAbsent(snippet.getNamespace(), new HashSet<>());
                    snippets.get(snippet.getNamespace()).add(snippet.getName());
                }
            } else if ("ini".equalsIgnoreCase((inputData.getFile().getExtension()))) {
                // ini files

                String presentableUrl = inputData.getFile().getUrl();
                int i = presentableUrl.lastIndexOf("/snippets/");
                if(i > 0) {
                    Set<String> iniKeys = SnippetUtil.getIniKeys(inputData.getContentAsText().toString());
                    if(iniKeys.size() > 0) {
                        String namespace = presentableUrl.substring(i + "/snippets/".length(), presentableUrl.length() - 4);
                        snippets.putIfAbsent(namespace, new HashSet<>());
                        snippets.get(namespace).addAll(iniKeys);
                    }
                }
            } else if (psiFile instanceof JSFile) {
                for (ShopwareSnippet snippet : SnippetUtil.getSnippetsInFile((JSFile) psiFile)) {
                    snippets.putIfAbsent(snippet.getNamespace(), new HashSet<>());
                    snippets.get(snippet.getNamespace()).add(snippet.getName());
                }
            }

            return snippets;
        };
    }

    @NotNull
    @Override
    public KeyDescriptor<String> getKeyDescriptor() {
        return this.myKeyDescriptor;
    }


    @NotNull
    @Override
    public DataExternalizer<Set<String>> getValueExternalizer() {
        return new StringSetDataExternalizer();
    }

    @NotNull
    @Override
    public FileBasedIndex.InputFilter getInputFilter() {
        return file -> {
            FileType fileType = file.getFileType();
            return fileType == SmartyFileType.INSTANCE || fileType == JavaScriptFileType.INSTANCE || "ini".equalsIgnoreCase(file.getExtension());
        };
    }

    @Override
    public boolean dependsOnFileContent() {
        return true;
    }

    @Override
    public int getVersion() {
        return 1;
    }
}

@@ -189,41 +189,8 @@
 pe;%0A
-import com.intellij.psi.PsiFile;%0A
 impo
@@ -895,16 +895,79 @@
 l.Set;%0A%0A
+/**%0A * @author Daniel Espendiller %3Cdaniel@espendiller.net%3E%0A */%0A
 public c
@@ -1616,22 +1616,16 @@
         
-final 
 Map%3CStri
@@ -1687,22 +1687,24 @@
     
-Psi
 File
- psiFil
+Type fileTyp
 e = 
@@ -1720,15 +1720,16 @@
 .get
-Psi
 File
+Type
 ();%0A
@@ -1740,31 +1740,85 @@
         if (
-p
+fileType == SmartyFileType.INSTANCE && inputData.getP
 siFile
+()
  instanceof 
@@ -1952,31 +1952,46 @@
 SmartyFile) 
-p
+inputData.getP
 siFile
+()
 )) %7B%0A       
@@ -2192,67 +2192,47 @@
 if (
-%22ini%22.equalsIgnoreCase((inputData.getFile().getExtension())
+inputData.getFileName().endsWith(%22.ini%22
 )) %7B
@@ -2905,23 +2905,82 @@
 lse if (
-p
+fileType  == JavaScriptFileType.INSTANCE && inputData.getP
 siFile
+()
  instanc
@@ -3083,15 +3083,30 @@
 le) 
-p
+inputData.getP
 siFile
+()
 )) %7B

fix exception in INI files / snippet indexing #62