package org.luaj.vm2.luajc;

import org.luaj.vm2.LuaFunction;
import org.luaj.vm2.LuaValue;
import org.luaj.vm2.Prototype;
import squiddev.cctweaks.core.utils.DebugLogger;

import java.util.HashMap;
import java.util.Map;

/**
 * ****************************************************************************
 * Copyright (c) 2010 Luaj.org. All rights reserved.
 * <p/>
 * Permission is hereby granted, free of charge, to any person obtaining a copy
 * of this software and associated documentation files (the "Software"), to deal
 * in the Software without restriction, including without limitation the rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 * copies of the Software, and to permit persons to whom the Software is
 * furnished to do so, subject to the following conditions:
 * <p/>
 * The above copyright notice and this permission notice shall be included in
 * all copies or substantial portions of the Software.
 * <p/>
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
 * THE SOFTWARE.
 * ****************************************************************************
 */
public class JavaLoaderRewrite extends ClassLoader {

	private final LuaValue env;
	private final ClassLoader parent;

	private Map<String, byte[]> unloaded = new HashMap<String, byte[]>();

	public JavaLoaderRewrite(LuaValue env) {
		this.env = env;
		parent = getClass().getClassLoader();
	}

	public LuaFunction load(Prototype p, String className, String fileName) {
		JavaGenRewrite jg = new JavaGenRewrite(p, className, fileName);
		return load(jg);
	}

	public LuaFunction load(JavaGenRewrite jg) {
		include(jg);
		return load(jg.classname);
	}

	public LuaFunction load(String className) {
		try {
			Class c = loadClass(className);

			Object o = c.newInstance();
			DebugLogger.debug(o.toString());
			Class parent = o.getClass();
			do {
				DebugLogger.debug("\tExtends " + parent.getName());
				DebugLogger.debug("\t  Same class: " + (parent.equals(LuaFunction.class) ? "Yes" : "No"));
				DebugLogger.debug("\t  Assignable: " + (LuaFunction.class.isAssignableFrom(parent) ? "Yes" : "No"));
				DebugLogger.debug("\t  From Assignable: " + (parent.isAssignableFrom(o.getClass()) ? "Yes" : "No"));
				try {
					DebugLogger.debug("\t  Can cast: " + parent.cast(o).toString());
				} catch(Exception e) {
					DebugLogger.debug("\t  Cannot cast " + e.toString());
				}
			} while((parent = parent.getSuperclass())!= null);

			try {
				Object t = LuaFunction.class.cast(o);
				LuaFunction f = (LuaFunction) t;
				LuaValue v = (LuaValue) o;
				LuaFunction func = (LuaFunction) v;
			} catch(Exception e) {
				DebugLogger.error(e.getMessage());
			}

			LuaFunction v = (LuaFunction) o;
			v.setfenv(env);
			return v;
		} catch (Exception e) {
			e.printStackTrace();
			throw new IllegalStateException("bad class gen: " + e);
		}
	}

	public void include(JavaGenRewrite jg) {
		unloaded.put(jg.classname, jg.bytecode);
		for (int i = 0, n = jg.inners != null ? jg.inners.length : 0; i < n; i++)
			include(jg.inners[i]);
	}

	public Class findClass(String classname) throws ClassNotFoundException {
		byte[] bytes = unloaded.get(classname);
		if (bytes != null) return defineClass(classname, bytes, 0, bytes.length);
		return super.findClass(classname);
	}

}

@@ -119,57 +119,8 @@
 ype;
-%0Aimport squiddev.cctweaks.core.utils.DebugLogger;
 %0A%0Aim
@@ -1563,43 +1563,8 @@
 env;
-%0A%09private final ClassLoader parent;
 %0A%0A%09p
@@ -1681,45 +1681,37 @@
 %7B%0A%09%09
-this.env = env;%0A%09%09parent = getC
+super(JavaLoaderRewrite.c
 lass
-()
 .get
@@ -1723,16 +1723,35 @@
 Loader()
+);%0A%09%09this.env = env
 ;%0A%09%7D%0A%0A%09p
@@ -2066,1000 +2066,72 @@
 %0A%09%09%09
-Class c = loadClass(className);%0A%0A%09%09%09Object o = c.newInstance();%0A%09%09%09DebugLogger.debug(o.toString());%0A%09%09%09Class parent = o.getClass();%0A%09%09%09do %7B%0A%09%09%09%09DebugLogger.debug(%22%5CtExtends %22 + parent.getName());%0A%09%09%09%09DebugLogger.debug(%22%5Ct  Same class: %22 + (parent.equals(LuaFunction.class) ? %22Yes%22 : %22No%22));%0A%09%09%09%09DebugLogger.debug(%22%5Ct  Assignable: %22 + (LuaFunction.class.isAssignableFrom(parent) ? %22Yes%22 : %22No%22));%0A%09%09%09%09DebugLogger.debug(%22%5Ct  From Assignable: %22 + (parent.isAssignableFrom(o.getClass()) ? %22Yes%22 : %22No%22));%0A%09%09%09%09try %7B%0A%09%09%09%09%09DebugLogger.debug(%22%5Ct  Can cast: %22 + parent.cast(o).toString());%0A%09%09%09%09%7D catch(Exception e) %7B%0A%09%09%09%09%09DebugLogger.debug(%22%5Ct  Cannot cast %22 + e.toString());%0A%09%09%09%09%7D%0A%09%09%09%7D while((parent = parent.getSuperclass())!= null);%0A%0A%09%09%09try %7B%0A%09%09%09%09Object t = LuaFunction.class.cast(o);%0A%09%09%09%09LuaFunction f = (LuaFunction) t;%0A%09%09%09%09LuaValue v = (LuaValue) o;%0A%09%09%09%09LuaFunction func = (LuaFunction) v;%0A%09%09%09%7D catch(Exception e) %7B%0A%09%09%09%09DebugLogger.error(e.getMessage());%0A%09%09%09%7D%0A%0A%09%09%09LuaFunction v = (LuaFunction) o
+LuaFunction v = (LuaFunction) loadClass(className).newInstance()
 ;%0A%09%09

Fix ClassLoader