package pers.fw.tplugin.model;

import com.intellij.util.indexing.ID;
import pers.fw.tplugin.beans.LaravelIcons;
import com.intellij.codeInsight.lookup.LookupElement;
import com.intellij.codeInsight.lookup.LookupElementBuilder;
import com.intellij.lang.Language;
import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.patterns.PlatformPatterns;
import com.intellij.psi.PsiElement;
import com.intellij.psi.PsiFile;
import com.intellij.psi.PsiManager;
import com.intellij.psi.search.GlobalSearchScope;
import com.intellij.util.Processor;
import com.intellij.util.indexing.FileBasedIndex;
import com.jetbrains.php.lang.PhpFileType;
import com.jetbrains.php.lang.PhpLanguage;
import com.jetbrains.php.lang.psi.elements.*;
import pers.fw.tplugin.config.CollectProjectUniqueKeys;
import pers.fw.tplugin.inter.GotoCompletionContributor;
import pers.fw.tplugin.inter.GotoCompletionLanguageRegistrar;
import pers.fw.tplugin.inter.GotoCompletionProvider;
import pers.fw.tplugin.inter.GotoCompletionRegistrarParameter;
import org.apache.commons.lang.StringUtils;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import pers.fw.tplugin.util.PsiElementUtil;
import pers.fw.tplugin.util.Tool;
import pers.fw.tplugin.util.Util;

import java.util.*;

public class ModelReference implements GotoCompletionLanguageRegistrar {
//    private static MethodMatcher.CallToSignature[] CONFIG = new MethodMatcher.CallToSignature[]{
//            new MethodMatcher.CallToSignature("\\think\\Loader", "pers.fw.tplugin.model")
//    };

    @Override
    public boolean support(@NotNull Language language) {
        return PhpLanguage.INSTANCE == language;
    }

    @Override
    public void register(GotoCompletionRegistrarParameter registrar) {
        registrar.register(PlatformPatterns.psiElement(), new GotoCompletionContributor() {
            @Nullable
            @Override
            public GotoCompletionProvider getProvider(@Nullable PsiElement psiElement) {
                if (psiElement == null) {// || !LaravelProjectComponent.isEnabled(psiElement)) {
                    return null;
                }

                PsiElement parent = psiElement.getParent();

                if(parent == null)return null;
                if (PsiElementUtil.isFunctionReference(parent, "model", 0)) {
                    return new ModelReference.ModelProvider(parent);
                }else if(PsiElementUtil.isFunctionReference(parent, "controller", 0)){
                    return new ModelReference.ControllerProvider(parent);
                }
                return null;
            }
        });
    }

    public static class ControllerProvider extends ModelReference.ModelProvider {

        public ControllerProvider(PsiElement element) {
            super(element);
            this.key=ControllerStubIndex.KEY;
        }
    }

    private static class ModelProvider extends GotoCompletionProvider {

        protected ID<String, Void> key=ModelStubIndex.KEY;

        public ModelProvider(PsiElement element) {
            super(element);
        }

        @NotNull
        @Override
        public Collection<LookupElement> getLookupElements() {


            final Collection<LookupElement> lookupElements = new ArrayList<>();
            CollectProjectUniqueKeys ymlProjectProcessor = new CollectProjectUniqueKeys(getProject(), key);
            FileBasedIndex.getInstance().processAllKeys(key, ymlProjectProcessor, getProject());
            String curModule = Util.getCurTpModuleName(getElement()) + "/";
            for (String key : ymlProjectProcessor.getResult()) {    //从ymlProjectProcessor中获取结果
                lookupElements.add(LookupElementBuilder.create(key).withIcon(LaravelIcons.TEMPLATE_CONTROLLER_LINE_MARKER));
                if (key.startsWith(curModule)) {    //去掉前缀的模型提示
                    key = key.replace(curModule, "");
                    lookupElements.add(LookupElementBuilder.create(key).withIcon(LaravelIcons.TEMPLATE_CONTROLLER_LINE_MARKER));
                }
            }
            return lookupElements;
        }

        @NotNull
        @Override
        public Collection<PsiElement> getPsiTargets(StringLiteralExpression psiElement) {
//            return super.getPsiTargets(psiElement, offset, editor);
            final Set<PsiElement> targets = new HashSet<>();

            String contents = psiElement.getContents();
            if (StringUtils.isBlank(contents)) {
                return targets;
            }

            //判断是否有模块名
            String curTpModuleName = Util.getCurTpModuleName(getElement())+"/";
            String content2="";
            if(!contents.startsWith(curTpModuleName)){
                content2=curTpModuleName+contents;
            }

            //忽略大小写
            Collection<String> allKeys = FileBasedIndex.getInstance().getAllKeys(key, getElement().getProject());

            contents = Util.getKeyWithCase(allKeys, contents);
            if(!allKeys.contains(contents))
                contents = Util.getKeyWithCase(allKeys, content2);

            FileBasedIndex.getInstance().getFilesWithKey(key, new HashSet<>(Collections.singletonList(contents)),
                    new Processor<VirtualFile>() {
                        @Override
                        public boolean process(VirtualFile virtualFile) {
                            if (virtualFile != null) {
                                PsiFile psiFileTarget = PsiManager.getInstance(ModelReference.ModelProvider.this.getProject()).findFile(virtualFile);
                                targets.add(psiFileTarget);
                            }
                            return true;
                        }
                    }, GlobalSearchScope.getScopeRestrictedByFileTypes(GlobalSearchScope.allScope(getProject()), PhpFileType.INSTANCE));

            return targets;
        }
    }
}