var EM_WRAPPERS = [];

function translateProgram(progg){
    var str = ""
    str += translateImports(progg[0]) + "\n"
    
    PROG = PROGRAM.concat([])
    CLASSES = []
    appendLocalClasses(PROG,CURRENT_PROJECT)
    for(a in lib.java.lang) PROG.push(lib.java.lang[a]) //import all java.lang.* package
    
    EM_WRAPPERS = [];
    progg.each(function(i, item){
	if(item.implement.indexOf("emDependent") == -1) item.implement.push("emDependent")
    })
    progg.each(function(i, item){
        str += translateClass(item)
    })
    
    //EmDependent interface for subclass state trigger update listener
    str += "\n//Interface for classes to send / receive variable update events\n"
    str += "interface emDependent{\n"
    str += "\tpublic void emUpdate(String property);\n"
    str += "\tpublic void emUpdate(Object obj, String property);\n"
    str += "}\n\n"
    
    /*//EmDependent interface for subclass state trigger update listener
    str += "//Wrapper classes for all objects, to be replaced by classes below\n"
    str += "class emObject<E>{\n"
    str += "\tpublic E item;\n"
    str += "\tpublic emObject(E obj){\n"
    str += "\t\titem = obj;\n"
    str += "\t}\n"
    str += "}\n\n"*/
    
    str += "//Wrapper classes for all objects who are the results of dependencies\n"
    EM_WRAPPERS.each(function(i,item){
	str += translateEMWrapper(item);
    })
    
    str += "\n//Annotation interface for dependency labelling\n";
    str += "@Retention(RetentionPolicy.RUNTIME)\n";
    str += "@Target(ElementType.FIELD)\n";
    str += "@interface EDEN_DESCRIPTION {\n";
    str += "\tString definition();\n";
    str += "}\n";
    
    return str;
}
function translateImports(cls){
    var str = "import java.util.ArrayList;\n"
    str += "import java.lang.annotation.*;\n"
    
    function f(imp){
	    if(imp.sub) return imp.name + "." + f(imp.sub)
	    if(imp.name) return imp.name
	    return "*"
    }
    cls.imports.each(function(i,item){
    	str += "import " + f(item) + ";\n"
    })
    return str;
}
function translateClass(cls){
    var str = ""
    EM_Generated = ""
    EM_INTERCLASSES = emGetInterclasses(cls)
    importClasses(cls, cls)
    var found = classSearch(cls.extends, clsPack(cls))
    //if(EM_WRAPPERS.indexOf(cls.extends) > -1) emAddWrapperType(cls.name)
    
    if(cls.name + ".java" == CURRENT_FILENAME) str += cls.vis ? "public " : "private "
    str += "class "
    str += cls.name
    if(cls.generic){
    	str += translateGeneric(cls.generic)
    }
    str += " "
    str += "extends " + cls.extends
    
    if(cls.implement && cls.implement.length > 0){
	var imp = ""
	cls.implement.each(function(i,item){
	    imp += ", " + item
	})
	str += " implements " + imp.substring(2)
    }
    str += "{\n"
    
    var stat = 0, inst = 0;
    cls.vars.each(function(i,item){
        str += "\t" + translateVariable(item, cls)
        
        var assign;
        if(item.static) assign = cls.vardef.stat[stat];
        else assign = cls.vardef.inst[inst];
        if(assign){
	    var stat = translateStatement(assign, clsPack(getSemClass(cls, false)), 0, item)
	    if(!item.emdef && stat.indexOf("new em") == 0) stat += ".item";
	    if(!primType(item.type) && (item.emdef/* || item.vis*/)){
		if(localClass(item.type) && stat.indexOf("new") != 0){
		    stat = "new em" + item.type[0].toUpperCase() + item.type.substring(1) + "(" + stat + ")"
		}
		if(EM_INTERCLASSES.indexOf(item.name) > -1){
		    stat = stat.substring(0, stat.length - 1) + ".registerDependent(this))" 
		}
		str += " = " + stat
	    }else str += " = " + stat
        }
        str += ";\n"
	
	cls.static = false
	if(item.emdef) translateEMVariable(item, assign, cls)
	if(item.emdef || (item.dependents && item.dependents.length > 0)) translateEMDependency(item, cls)
	else if(item.vis || funSearch(cls, item.name + "_updated", false, "void", [])) translateEMDependency(item, cls)
	
        if(item.static) stat++
        else inst++
    })
    str += "\tprivate ArrayList<emDependent> emDependents = new ArrayList<emDependent>();\n"
    str += "\tprivate static ArrayList<emDependent> emDependentsStatic = new ArrayList<emDependent>();\n"
    
    str += "\n"
    _.each(cls.funs, function(group){
        group.each(function(i,fun){
	    var pack = clsPack(getSemClass(cls, false))
            str += "\t" + translateFunction(fun, pack) + "\n";
        })
    })
    
    //Dependancy register
    str += "\n\tpublic " + cls.name + " registerDependent(emDependent depend){\n"
    str += "\t\temDependents.add(depend);\n"
    str += "\t\treturn this;\n"
    str += "\t}\n"
    
    str += "\n\tpublic void emAddDependent(emDependent depend){\n"
    str += "\t\temDependents.add(depend);\n"
    str += "\t}\n"
    
    var first = true;
    //Parent update method
    str += "\n\tpublic void emUpdate(Object obj, String property) {\n"
    found.vars.each(function(i,item){
	str += "\t\t" + (first ? "" : "else ") + "if(property.equals(\""+item.name+"\")){"
	cls.vars.each(function(j, v){
	    if(!v.dependencies || v.dependencies.length == 0) return;
	    
	    v.dependencies.each(function(k, dep){
		if(dep.fun == item.name)
		    str += "em_update" + v.name[0].toUpperCase() + v.name.substring(1) + "(); ";
	    })
	})
	var fun = funSearch(cls, item.name + "_updated", false, "void", [])
	if(fun) str += item.name + "_updated();"
	
	str += "}\n";
	first = false;
    })
    
    cls.vars.each(function(j, v){//register interclass dependency events
	if(!v.dependencies || v.dependencies.length == 0) return;
	
	v.dependencies.each(function(k, dep){
	    
	    if(dep.is == IS_CALL && dep.subcall && dep.subcall.args == null && !dep.subcall.subcall){
		var callVar = getVar(clsPack(getSemClass(cls, false)).vars, dep.fun, false, "")
		if(!callVar) return;
		str += "\t\t" + (first ? "" : "else ") + "if(property.equals(\""+callVar.type + "." + dep.subcall.fun+"\") && " + dep.fun + ((emIsWrappedType(callVar.type) && callVar.emdef ? ".item" : "") ? ".item" : "") + " == obj){"
		str += "em_update" + v.name[0].toUpperCase() + v.name.substring(1) + "(); ";
		str += "}\n";
		first = false;
	    }
	})
    })
    
    str += "\t\temTriggerUpdate"+cls.name+"(property);\n";
    str += "\t}\n"
    
    str += "\n\tpublic void emUpdate(String property) {\n"
    str += "\t}\n"
    //}
    
    //Send dependency update
    str += "\n\tprivate void emTriggerUpdate"+cls.name+"(String property){\n"
    str += "\t\tfor(int i = 0; i < emDependents.size(); i++){\n"
    str += "\t\t\temDependents.get(i).emUpdate(this, property);\n"
    str += "\t\t}\n"
    str += "\t}\n"
    
    //Send dependency update - static
    str += "\n\tpublic static void emTriggerUpdateStatic"+cls.name+"(String property){\n"
    str += "\t\tfor(int i = 0; i < emDependentsStatic.size(); i++){\n"
    str += "\t\t\temDependentsStatic.get(i).emUpdate(property);\n"
    str += "\t\t}\n"
    str += "\t}\n"
    
    str += EM_Generated + "\n" //Add em generated functions at the end of class code
    
    str += "}\n"
    
    
    return str;
}
function translateVariable(v, cls){
    var str = ""
    
    if(v.emdef) {
	var emDef = translateStatement(v.emdef, clsPack(getSemClass(cls, false)))
	if(emDef.indexOf("new em") == 0){
	    emDef = emDef.substring(emDef.indexOf("(") + 1, emDef.length - 1)
	}
	str += '@EDEN_DESCRIPTION(definition = "' + emDef.replace(/\"/gi, "\\\"") + '")\n'
	str += "\tprivate "
    }else str += v.vis ? "public " : "private "
    
    str += v.static ? "static " : ""
    if(primType(v.type)) str += translateType(v.type)
    else if(v.emdef && localClass(v.type)){
	//str += "emObject<" + translateType(v.type)
	//if(v.generic) str += translateGeneric(v.generic)
	//str += ">"
	str += "em" + translateType(v.type)
	emAddWrapperType(v.type)
    }else {
	str += translateType(v.type)
	if(v.generic) str += translateGeneric(v.generic)
    }
    
    str += " "
    str += v.name
    return str;
}
function translateGeneric(generic, inst){
    var gen = ""
    generic.each(function(i,item){
    	gen += ", " + (inst || true ? "" : "? extends ") + item
    })
    return "<" + gen.substring(2) + ">"
}
function translateFunction(fun, p){
    var str = ""
    str += fun.vis ? "public " : "private "
    
    if(fun.type != fun.name) {
	str += fun.static ? "static " : ""
	str += translateType(fun.type) + " "
    }
    str += fun.name
    str += "(" + translateArgs(fun.args, fun.name) + ")"
    var pack = new packSet(new varSet(p.vars.cl, copyFunVars(fun.vars), fun.args))
    str += translateBlock(fun, pack, 0)
    if(fun.type == fun.name) {
	if(CURRENT_FILENAME == fun.name + ".java" || p.vars.cl.ext_cl.implement.indexOf("emDependent") > -1)
	    str = str.substring(0,str.length - 2) + "\n\t\tsuper.emAddDependent(this);  "
	str = str.substring(0,str.length - 2) + "\n\t\tEvaluator.addInstance(this);\n"
	
	/*p.vars.cl.vars.each(function(i,item){
	    if(item.emdef){
		str += "\n\t\tem_update" + item.name[0].toUpperCase() + item.name.substring(1) + "();"
	    }
	})*/
	
	str += "}\t\n";
    }
    return str;
}
function translateBlock(block, p, indent){
    var str = ""
    str += "{\n"
    block.stats.each(function(i,item){
        str += "\t\t" + "\t".repeat(indent) + translateStatement(item, p, indent) + (eolCheck(item.is) ? ";" : "") +"\n"
	p.type = null
    })
    str += "\n\t" + "\t".repeat(indent) + "}\n"
    return str
}
function translateArgs(args, name){
    var str = ""
    args.each(function(i,arg){
        str += ", "
        str += (emIsWrappedType(arg.type) && name == "add" ? "em" : "") + translateType(arg.type) + " "
        str += arg.name
    })
    return str.substring(2);
}
function translateType(type){
    if(type[0] == "["){
	var i = type.lastIndexOf("]")
	return type.substring(i + 1) + type.substring(0, i + 1);
    }
    return type;
}
function translateStatement(s, p, indent, v){
    var str = ""
    if(indent == null) indent = 0;
    
    switch(s.is){
	case IS_CALL: str += translateCall(s, p); break;
	case IS_LR: str += translateLR(s, p); break;
	case IS_VAR: str += translateValue(s, p); break;
	case IS_OP: str += translateOp(s, p); break;
	case IS_NEW: str += translateNew(s, p, v); break;
	case IS_IF: str = translateIf(s, p, indent); break;
	//case IS_WHILE: r = doWhile(s,p); break;
	case IS_FOR: str += translateFor(s, p, indent); break;
	//case IS_SWITCH: r = doSwitch(s,p); break;
	//case IS_TRY: r = doTry(s,p); break;
	case IS_RETURN: str += translateReturn(s, p); break;
	case IS_BREAK: str = translateBreak(s, p); break;
	case IS_CONV: str = translateCast(s, p); break;
	case IS_DEF: str += translateDef(s, p); break;
	case IS_BLOCK: str += translateBlock(s, p, indent); break;
    }
    if(s.subcall != null) str += "." + translateStatement(s.subcall, p)
    return str;
}
function translateCall(s, p){
    var str = ""
    if(!s.args){//variable call
	if(p && emIsWrappedType(p.type)) str += "get" + s.fun[0].toUpperCase() + s.fun.substring(1) + "()"
	else str += s.fun
	
	var v = (p ? getVar(p.vars, s.fun, false, "") : null)
	if(s.arr){
	    var res = ""
	    s.arr.arr.each(function(i,item){
		res += "[" + translateStatement(item, p, 0) + "]"
	    })
	    str += res
	}
	
	if(v) {
	    p.type = v.type
	    if(v.emdef && !primType(v.type) && emIsWrappedType(v.type)) {
		str += ".item"
	    }
	}
	//if(v && v.emdef) str += ".item"
    }else if(!s.custom){
        str += s.fun
        
        var args = ""
        s.args.each(function(i,item){
	    if(p) p.type = null
	    
            args += ", " + translateStatement(item, p)
	    if(s.fun == "add" && args.endsWith(".item")) args = args.substring(0, args.length - 5)
        })
        
        if(s.gen){
	    str += translateGeneric(s.gen, true)
	}
	
        str += "(" + args.substring(2) + ")"
    }
    return str;
}
function translateNew(s, p, v){
    var str = ""
    if(s.cls){
	if(EM_WRAPPERS.indexOf(s.cls.fun) > -1) str += "new em" + s.cls.fun + "(new " + translateCall(s.cls, p) + ")";
    	else str += "new " + translateCall(s.cls, clonePack(p))
    }else if(s.arr){
	var arr = s.arr
	var res = ""
	if(arr.is == IS_ARR_ACT){
	    arr.arr.each(function(i,item){
		res += ", " + translateStatement(item, p)
	    })//new " + s.type.substring(s.type.lastIndexOf("]")+1) + "[]
	    str += "new " + translateType(v.type) + "{" + res.substring(2) + "}"
	}else if(arr.is == IS_ARR){
	    arr.arr.each(function(i,item){
		res += "[" + translateStatement(item, p) + "]"
	    })
	    str += "new " + arr.type + res
	}
	
    }else{
        str += '"' + s.str + '"'
    }
    return str
}
function translateReturn(s, p){
    var str = "return "
    str += translateStatement(s.fun, p)
    return str
}
function translateLR(s, p){
    var str = ""
    var left = translateStatement(s.left)
    var right = translateStatement(s.right, p)
    var v = getVar(p.vars, s.left.fun, false, "");
    
    if(right.indexOf("new em") == 0) right += ".item"
    if(v && (v.vis || (v.dependents && v.dependents.length > 0) || (funSearch(p.vars.cl, v.name + "_updated", false, "void", [])))){
	if(s.left.subcall && emIsWrappedType(v.type)){
	    if(s.left.subcall.arr) {
		str += left
		str += " = "
		str += right
		str += ";" + v.name + ".setArray" + s.left.subcall.fun[0].toUpperCase() + s.left.subcall.fun.substring(1, left.indexOf("[")) + "()"
	    }else{
		str += v.name + ".set" + s.left.subcall.fun[0].toUpperCase() + s.left.subcall.fun.substring(1) + "("
		str += right + ")"
	    }
	}else if(!(varIsInList(v, p.vars.fun) || varIsInList(v, p.vars.args))){
	    if(s.left.arr) {
		str += left
		str += " = "
		str += right
		str += ";setArray" + left[0].toUpperCase() + left.substring(1, left.indexOf("[")) + "()"
	    }else{
		str += "set" + left[0].toUpperCase() + left.substring(1) + "("
		str += right + ")"
	    }
	}else {
	    str += left
	    str += " = "
	    str += right
	}
    }
    else {
	str += left
	str += " = "
	str += right
    }
    return str
}
function translateOp(s, p){
    if(s.op == "!") return "!" + translateStatement(s.left, clonePack(p))
    
    var str = "("
    str += translateStatement(s.left, clonePack(p))
    str += " " + s.op + " "
    str += translateStatement(s.right, clonePack(p)) + ")"
    return str
}
function translateValue(s, p){
    var str = ""
    if(s.value.is == IS_NULL) str += "null"
    else{
	str += s.value
	if((s.type == "double" || s.type == "float") && String(s.value).indexOf(".") == -1) str += ".0"
    }
    return str
}
function translateDef(s, p){
    var str = "";
    p.vars.fun.concat(p.vars.args).each(function (i,item){
	if(item.name == s.va) {
	    //str += (emIsWrappedType(item.type) ? "em" : "") + item.type
	    str += translateType(item.type)
	    item.value = 1
	    return true;
	}
    })
    if(str == "") debugger
    str += " " + s.va
    return str
}
function translateCast(s, p){
    var str = "("
    str += "(" + (emIsWrappedType(s.type) ? "em" : "")  + translateType(s.type) + ")"
    str += " (" + translateStatement(s.stat) + "))"
    return str
}
function translateBreak(s, p){
    if(s.brk) return "break"
    else return "continue"
}
function translateIf(s, p, indent){
    var str = ""
    var pack = p;
    pack = new packSet(new varSet(p.vars.cl, p.vars.fun, p.vars.args))
    if(s.ternary){
	str += "(" + translateStatement(s.con, pack) + " ? " + translateStatement(s.thenf, p) + " : " + translateStatement(s.elsef, p)  + ")"
    }else{
	str += "if(" + translateStatement(s.con, pack) + ") "
	
	var pack = p;
	if(s.thenf){
	    if(s.thenf.vars) pack = new packSet(new varSet(p.vars.cl, p.vars.fun.concat(copyFunVars(s.thenf.vars)), p.vars.args))
	    str += translateStatement(s.thenf, pack, indent + 1) + (eolCheck(s.thenf.is) ? ";" : "")
	}
	if(s.elsef){
	    str += "\n\t" + "\t".repeat(indent + 1) + "else "
	    str += translateStatement(s.elsef, p, indent + 1) + (eolCheck(s.elsef.is) ? ";" : "")
	}
    }
    
    return str
}
function translateFor(s, p, indent){
    var str = ""
    str += "for("
    
    var pack = new packSet(new varSet(p.vars.cl, p.vars.fun.concat(copyFunVars(s.dof.vars)), p.vars.args))
    if(s.def[0].is == IS_DEF){
	pack.vars.fun.each(function (i,item){
	    if(item.name == s.def[0].va) {
		str += item.type + " "
		return true;
	    }
	})
    }
    str += translateStatement(s.def.slice(-1)[0], pack) + "; " //TODO: fix for definitions ie int x = 0;
    str += translateStatement(s.con, pack) + "; "
    str += translateStatement(s.inc, pack) + ")"
    
    str += translateBlock(s.dof, pack, indent + 1)
    
    return str
}

//EM: Translators for EM specific dependencies
var EM_Generated = ""
function translateEMVariable(v, stat, cls){
    var str = ""
    var stat = translateStatement(stat, clsPack(getSemClass(cls, false)), 0, v)
    if(!primType(v.type) && localClass(v.type) && stat.indexOf("new") != 0) stat = "new em" + v.type[0].toUpperCase() + v.type.substring(1) + "(" + stat + ")"
    
    str += "\tprivate " + (v.static ? "static " : "") + "void em_update"+v.name[0].toUpperCase() + v.name.substring(1) + "(){\n"
    str += "\t\ttry{\n"
    str += "\t\t\t" + (emIsWrappedType(v.type) ? "em" : "") +translateType(v.type)+" new_" + v.name + " = " + stat + ";\n"
    //str += "\t\t\tif(new_" + v.name + " != " + v.name + (v.emdef && !primType(v.type)? ".item" : "") + "){\n"
    
    if(v.emdef || (v.dependents && v.dependents.length > 0)){
	str += "\t\t\tset" + v.name[0].toUpperCase() + v.name.substring(1) + "(new_" + v.name + (emIsWrappedType(v.type) ? ".item" : "") + ");\n"
    }else str += "\t\t\t" + v.name + (v.emdef && !primType(v.type) ? ".item" : "") + " = new_" + v.name + ";\n"
    
    /*if(funSearch(cls, v.name + "_updated", false, "void", [])){
	str += "\t\t\t\t" + v.name + "_updated();\n"
    }*/
    //str += "\t\t\t}\n"
    str += "\t\t}catch(Exception e){\n"
    if(primType(v.type)) str += "\t\t\t" + v.name + " = " + (v.type == "boolean" ? "false" : "0") + ";\n"
    else str += "\t\t\t" + v.name + (emIsWrappedType(v.type) ? ".item" : "") + " = null;\n"
    str += "\t\t}\n"
    str += "\t}\n"
    
    EM_Generated += str;
}

function translateEMDependency(v, cls){
    var str = ""
    
    str += "\t" + (v.vis ? "public " : "private ") + (v.static ? "static " : "") + "void set" + v.name[0].toUpperCase() + v.name.substring(1)
    str += "(" + translateType(v.type) + " em_" + v.name + "){\n"
    
    if(primType(v.type)) {
	str += "\t\tif(" + v.name + " != em_" + v.name + "){\n"
	str += "\t\t\t" + v.name + " = em_" + v.name + ";\n"
    }else {
	str += "\t\tif(" + v.name + (emIsWrappedType(v.type) && v.emdef ? ".item" : "") + " == null || !" + v.name + (emIsWrappedType(v.type) && v.emdef  ? ".item" : "") + ".equals(em_" + v.name + ")){\n"
	str += "\t\t\t" + v.name + (emIsWrappedType(v.type) && v.emdef  ? ".item" : "") + " = em_" + v.name + ";\n"
    }
    
    v.dependents.each(function(i,item){
	str += "\t\t\tem_update" + item.name[0].toUpperCase() + item.name.substring(1) + "();\n"
    })
    
    if(funSearch(cls, v.name + "_updated", false, "void", [])){
	str += "\t\t\t" + v.name + "_updated();\n"
    }
    str += "\t\t\temTriggerUpdate" + (v.static ? "Static" : "") + cls.name+"(\"" + v.name + "\");\n"
    str += "\t\t\temTriggerUpdate" + (v.static ? "Static" : "") + cls.name+"(\"" + cls.name + "." + v.name + "\");\n"
	
    str += "\t\t}\n"
    str += "\t}\n"
    
    if(v.type.contains("[")){
	str += "\t" + (v.vis ? "public " : "private ") + (v.static ? "static " : "") + "void setArray" + v.name[0].toUpperCase() + v.name.substring(1)
	str += "(){\n"
	v.dependents.each(function(i,item){
	    str += "\t\t\tem_update" + item.name[0].toUpperCase() + item.name.substring(1) + "();\n"
	})
	
	if(funSearch(cls, v.name + "_updated", false, "void", [])){
	    str += "\t\t\t" + v.name + "_updated();\n"
	}
	str += "\t\t\temTriggerUpdate" + (v.static ? "Static" : "") + cls.name+"(\"" + v.name + "\");\n"
	str += "\t\t\temTriggerUpdate" + (v.static ? "Static" : "") + cls.name+"(\"" + cls.name + "." + v.name + "\");\n"
	
	str += "\t}\n"
    }
    
    if(v.vis){
	str += "\tpublic " + (v.static ? "static " : "") + translateType(v.type) + " get" + v.name[0].toUpperCase() + v.name.substring(1)
	str += "(){\n"
	if(primType(v.type)) str += "\t\treturn " + v.name + ";\n"
	else str += "\t\treturn " + v.name + (emIsWrappedType(v.type) ? ".item" : "") + ";\n"
	str += "\t}\n"
    }
    
    EM_Generated += str;
}
function translateEMWrapper(name){
    var str = ""
    
    var cls = classSearch(name, clsPack(PROGRAM[0]))
    str += "class em" + name + " extends " + (cls.extends != "Object" ? "em" : "") + cls.extends + "{\n"
    str += "\tpublic " + name + " item;\n\n"
    
    str += "\tpublic em" + name + " (" + name + " obj){\n"
    if(emIsWrappedType(cls.extends)) str += "\t\t super(obj);\n";
    else str += "\t\t super();\n"
    str += "\t\t item = obj;\n"
    str += "\t}\n\n"
    
    str += "\tpublic em" + name + " (){}\n"
    
    _.each(cls.funs, function(group){
        group.each(function(i,fun){
	    if(!fun.vis || fun.static || fun.type == fun.name) return;
	    
	    str += "\tpublic " + (fun.static ? "static " : "") + translateType(fun.type) + " " + fun.name + "(" + translateArgs(fun.args, fun.name) + "){"
	    str += "" + (fun.type != "void" ? "return " : "") + "item." + fun.name
	    
	    var args = ""
	    fun.args.each(function(a, arg){
		args += ", " + arg.name
	    })
	    str += "(" + args.substring(2) + ");"
	    
	    str += "}\n"
        })
    })
    
    cls.vars.each(function(i,item){
	if(item.vis){
	    str += "\tpublic " + (item.static ? "static " : "") + " void  set" + item.name[0].toUpperCase() + item.name.substring(1) + "(" + translateType(item.type) + " obj){"
	    str += "item.set" + item.name[0].toUpperCase() + item.name.substring(1) + "(obj);}\n"
	    
	    str += "\tpublic " + (item.static ? "static " : "") + translateType(item.type) + " get" + item.name[0].toUpperCase() + item.name.substring(1) + "(){"
	    str += "return item.get" + item.name[0].toUpperCase() + item.name.substring(1) + "();}\n"
	}
    })
    
    str += "}\n"
    
    return str
}

function varIsInList(v, vars){
    var found = false;
    vars.each(function(i,item){
	if(item.name == v.name) found = true;
    })
    return found;
}
function emAddWrapperType(type){
    type = type.replace(/\[\]/gi, "")
    if(EM_WRAPPERS.indexOf(type) == -1) {
	var cls = classSearch(type, clsPack(PROGRAM[0]))
	if(cls){
	    EM_WRAPPERS.push(type)
	    if(cls.extends != "Object") emAddWrapperType(cls.extends)
	    emAddChildWrappers(cls.name)
	}else {alert("Error:: type not found for translation '" + type + "'"); debugger}
    }
}
function emAddChildWrappers(name){
    PROGRAM.each(function(i,cls){
	if(cls.extends == name && !emIsWrappedType(cls.name)) {
	    EM_WRAPPERS.push(cls.name)
	    emAddChildWrappers(cls.name)
	}
    })
}
function emIsWrappedType(type){
    return EM_WRAPPERS.indexOf(type) > -1
}


function localClass(name){
    var found = false
    DB_FILES({parent:CURRENT_PROJECT}).each(function (r){
		if(r.name == name + ".class") {found = true;}
			
	})
	return found || isEmClass(name);
}
function isEmClass(name){
    return ["Shape", "Group", "Text", "Line", "Rect", "Arc"].indexOf(name) > -1
}

function emGetInterclasses(cls){
    var results = []
    cls.vars.each(function(j, v){//register interclass dependency events
	if(!v.dependencies || v.dependencies.length == 0) return;
	
	v.dependencies.each(function(k, dep){
	    
	    if(dep.is == IS_CALL && dep.subcall && dep.subcall.args == null && !dep.subcall.subcall){
		  results.push(dep.fun)
	    }
	})
    })
    return results
}

function clonePack(p){
    if(p == null) return null;
    return new packSet(new varSet(p.vars.cl, p.vars.fun, p.vars.args))
}