/*
 * Copyright (c) 2017. tangzx(love.tangzx@qq.com)
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package com.tang.intellij.lua.stubs.index;

import com.intellij.psi.stubs.StringStubIndexExtension;
import com.intellij.psi.stubs.StubIndexKey;
import com.tang.intellij.lua.comment.psi.LuaDocClassDef;
import com.tang.intellij.lua.lang.LuaLanguage;
import com.tang.intellij.lua.lang.type.LuaType;
import com.tang.intellij.lua.psi.LuaClassField;
import com.tang.intellij.lua.search.SearchContext;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;

import java.util.Collection;

/**
 *
 * Created by tangzx on 2016/12/10.
 */
public class LuaClassFieldIndex extends StringStubIndexExtension<LuaClassField> {

    public static final StubIndexKey<String, LuaClassField> KEY = StubIndexKey.createIndexKey("lua.index.class.field");

    private static final LuaClassFieldIndex INSTANCE = new LuaClassFieldIndex();

    public static LuaClassFieldIndex getInstance() {
        return INSTANCE;
    }

    @Override
    public int getVersion() { return LuaLanguage.INDEX_VERSION;}

    @NotNull
    @Override
    public StubIndexKey<String, LuaClassField> getKey() {
        return KEY;
    }

    public static LuaClassField find(@NotNull String key, @NotNull SearchContext context) {
        if (context.isDumb())
            return null;

        Collection<LuaClassField> list = INSTANCE.get(key, context.getProject(), context.getScope());
        if (!list.isEmpty())
            return list.iterator().next();
        return null;
    }

    public static Collection<LuaClassField> find(@NotNull String className, @NotNull String fieldName, @NotNull SearchContext context) {
        if (context.isDumb())
            return null;

        String key = className + "." + fieldName;
        Collection<LuaClassField> list = INSTANCE.get(key, context.getProject(), context.getScope());

        if (!list.isEmpty())
            return list;

        // from supper
        LuaDocClassDef classDef = LuaClassIndex.find(className, context);
        if (classDef != null) {
            LuaType type = classDef.getClassType();
            if (type != null) {
                String superClassName = type.getSuperClassName();
                if (superClassName != null) {
                    list = find(superClassName, fieldName, context);
                    if (list != null && !list.isEmpty())
                        return list;
                }
            }
        }

        return list;
    }

    @Nullable
    public static LuaClassField find(LuaType type, String fieldName, SearchContext context) {
        Collection<LuaClassField> fields = findAll(type, fieldName, context);
        if (!fields.isEmpty())
            return fields.iterator().next();
        return null;
    }

    public static Collection<LuaClassField> findAll(LuaType type, String fieldName, SearchContext context) {
        Collection<LuaClassField> fields = find(type.getClassName(), fieldName, context);
        if (fields == null) {
            type.initAliasName(context);
            if (type.getAliasName() != null)
                fields = find(type.getAliasName(), fieldName, context);
        }
        return fields;
    }
}

@@ -806,16 +806,73 @@
 assDef;%0A
+import com.tang.intellij.lua.comment.psi.LuaDocFieldDef;%0A
 import c
@@ -1171,16 +1171,46 @@
 lection;
+%0Aimport java.util.Collections;
 %0A%0A/**%0A *
@@ -2155,32 +2155,45 @@
 rn null;%0A    %7D%0A%0A
+    @NotNull%0A
     public stati
@@ -2354,36 +2354,55 @@
          return 
-null
+Collections.emptyList()
 ;%0A%0A        Strin
@@ -3018,24 +3018,8 @@
 if (
-list != null && 
 !lis
@@ -3337,75 +3337,193 @@
     
-if (!fields.isEmpty())%0A            return fields.iterator().next();
+LuaClassField perfect = null;%0A        for (LuaClassField field : fields) %7B%0A            perfect = field;%0A            if (field instanceof LuaDocFieldDef)%0A                break;%0A        %7D
 %0A   
@@ -3526,36 +3526,39 @@
 %0A        return 
-null
+perfect
 ;%0A    %7D%0A%0A    pub
@@ -3542,32 +3542,45 @@
 perfect;%0A    %7D%0A%0A
+    @NotNull%0A
     public stati
@@ -3784,16 +3784,18 @@
 elds
- == null
+.isEmpty()
 ) %7B%0A

clean code