package kalang.compiler.compile;

import kalang.compiler.ast.ClassNode;
import kalang.compiler.util.AstUtil;
import kalang.compiler.util.NameUtil;

import javax.annotation.Nullable;
import java.util.*;

/**
 *
 * @author Kason Yang
 */
public class TypeNameResolver {

    private Map<String, String> simpleToFullNames = new HashMap();

    private List<String> importPackages = new LinkedList();

    private AstLoader astLoader;

    public TypeNameResolver() {
    }

    public void importClass(String className){
        this.importClass(className,NameUtil.getSimpleClassName(className));
    }
    
    public void importClass(String className,String alias) {
        this.simpleToFullNames.put(alias , className);
    }

    public void importPackage(String packageName) {
        this.importPackages.add(packageName);
    }

    private String fixInnerClassName(String className) {
        String name = "";
        for (String n : className.split("\\.")) {
            name += n;
            if (astLoader !=null && astLoader.getAst(name) != null) {
                name += "$";
            } else {
                name += ".";
            }
        }
        return name.substring(0, name.length() - 1);
    }

    /**
     * 
     * @param id
     * @param topClass
     * @param declaringClass
     * @return full name of type,null if failed.
     */
    @Nullable
    public String resolve(String id,ClassNode topClass, ClassNode declaringClass) {
        if(id.contains(".")) return id;
        if (simpleToFullNames.containsKey(id)) {
            return this.fixInnerClassName(simpleToFullNames.get(id));
        } else if (id.contains("$")){
            String[] idParts = id.split("\\$");
            String outerClassName = this.resolve(idParts[0],topClass,declaringClass);
            if (outerClassName==null){
                return null;
            }
            return outerClassName + "$" + idParts[1];
        }else {
            String[] innerClassesNames = AstUtil.listInnerClassesNames(topClass, true);
            String path = declaringClass.name;
            while(!path.isEmpty()) {
                String name = path + "$" + id;
                for(String c:innerClassesNames) {
                    if (name.equals(c)) {
                        return c;
                    }
                }
                int last$ = path.lastIndexOf('$');
                path = last$ > 0 ? path.substring(0,last$) : "";
            }
            List<String> paths = new ArrayList<>(importPackages.size() + 1);
            paths.addAll(importPackages);
            paths.add(NameUtil.getPackageName(topClass.name));
            int pathSize = paths.size();
            for (int i=pathSize-1;i>=0;i--) {
                String p = paths.get(i);
                String clsName;
                if (p != null && p.length() > 0) {
                    clsName = p + "." + id;
                } else {
                    clsName = id;
                }
                if (astLoader!=null &&  astLoader.getAst(this.fixInnerClassName(clsName)) != null) {
                    return clsName;
                }
            }
        }
        return null;
    }

    public void setAstLoader(AstLoader astLoader) {
        this.astLoader = astLoader;
    }
    
}

@@ -830,405 +830,16 @@
  %7D%0A%0A
-    private String fixInnerClassName(String className) %7B%0A        String name = %22%22;%0A        for (String n : className.split(%22%5C%5C.%22)) %7B%0A            name += n;%0A            if (astLoader !=null && astLoader.getAst(name) != null) %7B%0A                name += %22$%22;%0A            %7D else %7B%0A                name += %22.%22;%0A            %7D%0A        %7D%0A        return name.substring(0, name.length() - 1);%0A    %7D%0A%0A
     /**%0A
     
@@ -834,16 +834,16 @@
     /**%0A
+
      * %0A
@@ -1174,39 +1174,16 @@
  return 
-this.fixInnerClassName(
 simpleTo
@@ -1199,17 +1199,16 @@
 .get(id)
-)
 ;%0A      
@@ -2615,39 +2615,16 @@
 Ast(
-this.fixInnerClassName(
 clsName)
 ) !=
@@ -2619,17 +2619,16 @@
 clsName)
-)
  != null

remove fixInnerClassName