/*
 * $Id: DefaultJavaReflector.java 161 2012-10-06 13:53:02Z andre@naef.com $
 * See LICENSE.txt for license terms.
 */

package com.naef.jnlua;

import java.beans.BeanInfo;
import java.beans.IntrospectionException;
import java.beans.Introspector;
import java.beans.PropertyDescriptor;
import java.lang.reflect.Array;
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.NavigableMap;
import java.util.Set;
import java.util.Map.Entry;
import java.util.concurrent.locks.ReadWriteLock;
import java.util.concurrent.locks.ReentrantReadWriteLock;

/**
 * Default implementation of the <code>JavaReflector</code> interface.
 */
public class DefaultJavaReflector implements JavaReflector {
	// -- Static
	private static final DefaultJavaReflector INSTANCE = new DefaultJavaReflector();
	private static final Object JAVA_FUNCTION_TYPE = new Object();
	private static final Object[] EMPTY_ARGUMENTS = new Object[0];

	// -- State
	private Map<Class<?>, Map<String, Accessor>> accessors = new HashMap<Class<?>, Map<String, Accessor>>();
	private ReadWriteLock accessorLock = new ReentrantReadWriteLock();
	private Map<LuaCallSignature, Invocable> invocableDispatches = new HashMap<LuaCallSignature, Invocable>();
	private ReadWriteLock invocableDispatchLock = new ReentrantReadWriteLock();
	private JavaFunction index = new Index();
	private JavaFunction newIndex = new NewIndex();
	private JavaFunction equal = new Equal();
	private JavaFunction length = new Length();
	private JavaFunction lessThan = new LessThan();
	private JavaFunction lessThanOrEqual = new LessThanOrEqual();
	private JavaFunction toString = new ToString();
	private JavaFunction pairs = new Pairs();
	private JavaFunction ipairs = new IPairs();
	private JavaFunction javaFields = new AccessorPairs(FieldAccessor.class);
	private JavaFunction javaMethods = new AccessorPairs(
			InvocableAccessor.class);
	private JavaFunction javaProperties = new AccessorPairs(
			PropertyAccessor.class);

	// -- Static methods
	/**
	 * Returns the instance of this class.
	 * 
	 * @return the instance
	 */
	public static DefaultJavaReflector getInstance() {
		return INSTANCE;
	}

	// -- Construction
	/**
	 * Creates a new instances;
	 */
	private DefaultJavaReflector() {
	}

	// -- JavaReflector methods
	@Override
	public JavaFunction getMetamethod(Metamethod metamethod) {
		switch (metamethod) {
		case INDEX:
			return index;
		case NEWINDEX:
			return newIndex;
		case LEN:
			return length;
		case EQ:
			return equal;
		case LT:
			return lessThan;
		case LE:
			return lessThanOrEqual;
		case TOSTRING:
			return toString;
		case PAIRS:
			return pairs;
		case IPAIRS:
			return ipairs;
		case JAVAFIELDS:
			return javaFields;
		case JAVAMETHODS:
			return javaMethods;
		case JAVAPROPERTIES:
			return javaProperties;
		default:
			return null;
		}
	}

	// -- Private methods
	/**
	 * Returns the accessors of an object.
	 */
	private Map<String, Accessor> getObjectAccessors(Object object) {
		// Check cache
		Class<?> clazz = getObjectClass(object);
		accessorLock.readLock().lock();
		try {
			Map<String, Accessor> result = accessors.get(clazz);
			if (result != null) {
				return result;
			}
		} finally {
			accessorLock.readLock().unlock();
		}

		// Fill in
		Map<String, Accessor> result = createClassAccessors(clazz);
		accessorLock.writeLock().lock();
		try {
			if (!accessors.containsKey(clazz)) {
				accessors.put(clazz, result);
			} else {
				result = accessors.get(clazz);
			}
		} finally {
			accessorLock.writeLock().unlock();
		}
		return result;
	}

	/**
	 * Creates the accessors of a class.
	 */
	private Map<String, Accessor> createClassAccessors(Class<?> clazz) {
		Map<String, Accessor> result = new HashMap<String, Accessor>();

		// Fields
		Field[] fields = clazz.getFields();
		for (int i = 0; i < fields.length; i++) {
			result.put(fields[i].getName(), new FieldAccessor(fields[i]));
		}

		// Methods
		Map<String, Map<List<Class<?>>, Invocable>> accessibleMethods = new HashMap<String, Map<List<Class<?>>, Invocable>>();
		Method[] methods = clazz.getMethods();
		for (int i = 0; i < methods.length; i++) {
			// Do not overwrite fields
			Method method = methods[i];
			if (result.containsKey(method.getName())) {
				continue;
			}

			// Attempt to find the method in a public class if the declaring
			// class is not public
			if (!Modifier.isPublic(method.getDeclaringClass().getModifiers())) {
				method = getPublicClassMethod(clazz, method.getName(),
						method.getParameterTypes());
				if (method == null) {
					continue;
				}
			}

			// For each method name and parameter type list, keep
			// only the method declared by the most specific class
			Map<List<Class<?>>, Invocable> overloaded = accessibleMethods
					.get(method.getName());
			if (overloaded == null) {
				overloaded = new HashMap<List<Class<?>>, Invocable>();
				accessibleMethods.put(method.getName(), overloaded);
			}
			List<Class<?>> parameterTypes = Arrays.asList(method
					.getParameterTypes());
			Invocable currentInvocable = overloaded.get(parameterTypes);
			if (currentInvocable != null
					&& method.getDeclaringClass().isAssignableFrom(
							currentInvocable.getDeclaringClass())) {
				continue;
			}
			overloaded.put(parameterTypes, new InvocableMethod(method));
		}
		for (Map.Entry<String, Map<List<Class<?>>, Invocable>> entry : accessibleMethods
				.entrySet()) {
			result.put(entry.getKey(), new InvocableAccessor(clazz, entry
					.getValue().values()));
		}

		// Constructors
		Constructor<?>[] constructors = clazz.getConstructors();
		List<Invocable> accessibleConstructors = new ArrayList<Invocable>(
				constructors.length);
		for (int i = 0; i < constructors.length; i++) {
			// Ignore constructor if the declaring class is not public
			if (!Modifier.isPublic(constructors[i].getDeclaringClass()
					.getModifiers())) {
				continue;
			}
			accessibleConstructors
					.add(new InvocableConstructor(constructors[i]));
		}
		if (clazz.isInterface()) {
			accessibleConstructors.add(new InvocableProxy(clazz));
		}
		if (!accessibleConstructors.isEmpty()) {
			result.put("new", new InvocableAccessor(clazz,
					accessibleConstructors));
		}

		// Properties
		BeanInfo beanInfo;
		try {
			beanInfo = Introspector.getBeanInfo(clazz);
		} catch (IntrospectionException e) {
			throw new RuntimeException(e);
		}
		PropertyDescriptor[] propertyDescriptors = beanInfo
				.getPropertyDescriptors();
		for (int i = 0; i < propertyDescriptors.length; i++) {
			// Do not overwrite fields or methods
			if (result.containsKey(propertyDescriptors[i].getName())) {
				continue;
			}

			// Attempt to find the read/write methods in a public class if the
			// declaring class is not public
			Method method = propertyDescriptors[i].getReadMethod();
			if (method != null
					&& !Modifier.isPublic(method.getDeclaringClass()
							.getModifiers())) {
				method = getPublicClassMethod(clazz, method.getName(),
						method.getParameterTypes());
				try {
					propertyDescriptors[i].setReadMethod(method);
				} catch (IntrospectionException e) {
				}
			}
			method = propertyDescriptors[i].getWriteMethod();
			if (method != null
					&& !Modifier.isPublic(method.getDeclaringClass()
							.getModifiers())) {
				method = getPublicClassMethod(clazz, method.getName(),
						method.getParameterTypes());
				try {
					propertyDescriptors[i].setWriteMethod(method);
				} catch (IntrospectionException e) {
				}
			}

			// Do not process properties without a read and a write method
			if (propertyDescriptors[i].getReadMethod() == null
					&& propertyDescriptors[i].getWriteMethod() == null) {
				continue;
			}
			result.put(propertyDescriptors[i].getName(), new PropertyAccessor(
					clazz, propertyDescriptors[i]));
		}
		return result;
	}

	/**
	 * Returns a public class method matching a method name and parameter list.
	 * The public class can be a superclass or interface.
	 */
	private Method getPublicClassMethod(Class<?> clazz, String methodName,
			Class<?>[] parameterTypes) {
		Method method = getPublicSuperclassMethod(clazz, methodName,
				parameterTypes);
		if (method != null) {
			return method;
		}
		return getInterfaceMethod(clazz, methodName, parameterTypes);
	}

	/**
	 * Returns a public superclass method matching a method name and parameter
	 * list.
	 */
	private Method getPublicSuperclassMethod(Class<?> clazz, String methodName,
			Class<?>[] parameterTypes) {
		Class<?> superclass = clazz.getSuperclass();
		while (superclass != null) {
			// Ignore non-public superclasses
			if (!Modifier.isPublic(superclass.getModifiers())) {
				continue;
			}

			// Find method in superclass
			try {
				Method method = superclass.getDeclaredMethod(methodName,
						parameterTypes);
				if (Modifier.isPublic(method.getModifiers())) {
					return method;
				}
			} catch (NoSuchMethodException e) {
				// Not found
			}

			// Check superclass
			superclass = superclass.getSuperclass();
		}

		// Not found
		return null;
	}

	/**
	 * Returns an interface method matching a method name and parameter list.
	 */
	private Method getInterfaceMethod(Class<?> clazz, String methodName,
			Class<?>[] parameterTypes) {
		do {
			// Get interfaces
			Class<?>[] interfaces = clazz.getInterfaces();
			for (int i = 0; i < interfaces.length; i++) {
				// Ignore non-public interfaces
				if (!Modifier.isPublic(interfaces[i].getModifiers())) {
					continue;
				}

				// Find method in the current interface
				try {
					return interfaces[i].getDeclaredMethod(methodName,
							parameterTypes);
				} catch (NoSuchMethodException e) {
					// Not found
				}

				// Check superinterfaces
				Method method = getInterfaceMethod(interfaces[i], methodName,
						parameterTypes);
				if (method != null) {
					return method;
				}
			}

			// Check superclass
			clazz = clazz.getSuperclass();
		} while (clazz != null);

		// Not found
		return null;
	}

	/**
	 * Returns the class of an object, or the class itself if the object is
	 * already a class.
	 */
	private Class<?> getObjectClass(Object object) {
		return object instanceof Class<?> ? (Class<?>) object : object
				.getClass();
	}

	// -- Nested types
	/**
	 * <code>__index</code> metamethod implementation.
	 */
	private class Index implements JavaFunction {
		public int invoke(LuaState luaState) {
			// Get object and class
			Object object = luaState.toJavaObject(1, Object.class);
			Class<?> objectClass = getObjectClass(object);

			// Handle arrays
			if (objectClass.isArray()) {
				if (!luaState.isNumber(2)) {
					throw new LuaRuntimeException(String.format(
							"attempt to read array with %s accessor",
							luaState.typeName(2)));
				}
				int index = luaState.toInteger(2);
				int length = Array.getLength(object);
				if (index < 1 || index > length) {
					throw new LuaRuntimeException(String.format(
							"attempt to read array of length %d at index %d",
							length, index));
				}
				luaState.pushJavaObject(Array.get(object, index - 1));
				return 1;
			}

			// Handle objects
			Map<String, Accessor> objectAccessors = getObjectAccessors(object);
			String key = luaState.toString(-1);
			if (key == null) {
				throw new LuaRuntimeException(String.format(
						"attempt to read class %s with %s accessor", object
								.getClass().getCanonicalName(), luaState
								.typeName(-1)));
			}
			Accessor accessor = objectAccessors.get(key);
			if (accessor == null) {
				throw new LuaRuntimeException(
						String.format(
								"attempt to read class %s with accessor '%s' (undefined)",
								objectClass.getCanonicalName(), key));
			}
			accessor.read(luaState, object);
			return 1;
		}
	}

	/**
	 * <code>__newindex</code> metamethod implementation.
	 */
	private class NewIndex implements JavaFunction {
		public int invoke(LuaState luaState) {
			// Get object and class
			Object object = luaState.toJavaObject(1, Object.class);
			Class<?> objectClass = getObjectClass(object);

			// Handle arrays
			if (objectClass.isArray()) {
				if (!luaState.isNumber(2)) {
					throw new LuaRuntimeException(String.format(
							"attempt to write array with %s accessor",
							luaState.typeName(2)));
				}
				int index = luaState.toInteger(2);
				int length = Array.getLength(object);
				if (index < 1 || index > length) {
					throw new LuaRuntimeException(String.format(
							"attempt to write array of length %d at index %d",
							length, index));
				}
				Class<?> componentType = objectClass.getComponentType();
				if (!luaState.isJavaObject(3, componentType)) {
					throw new LuaRuntimeException(
							String.format(
									"attempt to write array of %s at index %d with %s value",
									componentType.getCanonicalName(), 3,
									luaState.typeName(3)));
				}
				Object value = luaState.toJavaObject(3, componentType);
				Array.set(object, index - 1, value);
				return 0;
			}

			// Handle objects
			Map<String, Accessor> objectAccessors = getObjectAccessors(object);
			String key = luaState.toString(2);
			if (key == null) {
				throw new LuaRuntimeException(String.format(
						"attempt to write class %s with %s accessor", object
								.getClass().getCanonicalName(), luaState
								.typeName(2)));
			}
			Accessor accessor = objectAccessors.get(key);
			if (accessor == null) {
				throw new LuaRuntimeException(
						String.format(
								"attempt to write class %s with accessor '%s' (undefined)",
								objectClass.getCanonicalName(), key));
			}
			accessor.write(luaState, object);
			return 0;
		}
	}

	/**
	 * <code>__len</code> metamethod implementation.
	 */
	private class Length implements JavaFunction {
		@Override
		public int invoke(LuaState luaState) {
			Object object = luaState.toJavaObject(1, Object.class);
			if (object.getClass().isArray()) {
				luaState.pushInteger(Array.getLength(object));
				return 1;
			}
			luaState.pushInteger(0);
			return 1;
		}
	}

	/**
	 * <code>__eq</code> metamethod implementation.
	 */
	private class Equal implements JavaFunction {
		@Override
		public int invoke(LuaState luaState) {
			Object object1 = luaState.toJavaObject(1, Object.class);
			Object object2 = luaState.toJavaObject(2, Object.class);
			luaState.pushBoolean(object1 == object2 || object1 != null
					&& object1.equals(object2));
			return 1;
		}
	}

	/**
	 * <code>__lt</code> metamethod implementation.
	 */
	private class LessThan implements JavaFunction {
		@SuppressWarnings("unchecked")
		@Override
		public int invoke(LuaState luaState) {
			if (!luaState.isJavaObject(1, Comparable.class)) {
				throw new LuaRuntimeException(String.format(
						"class %s does not implement Comparable",
						luaState.typeName(1)));
			}
			Comparable<Object> comparable = luaState.toJavaObject(1,
					Comparable.class);
			Object object = luaState.toJavaObject(2, Object.class);
			luaState.pushBoolean(comparable.compareTo(object) < 0);
			return 1;
		}
	}

	/**
	 * <code>__le</code> metamethod implementation.
	 */
	private class LessThanOrEqual implements JavaFunction {
		@SuppressWarnings("unchecked")
		@Override
		public int invoke(LuaState luaState) {
			if (!luaState.isJavaObject(1, Comparable.class)) {
				throw new LuaRuntimeException(String.format(
						"class %s does not implement Comparable",
						luaState.typeName(1)));
			}
			Comparable<Object> comparable = luaState.toJavaObject(1,
					Comparable.class);
			Object object = luaState.toJavaObject(2, Object.class);
			luaState.pushBoolean(comparable.compareTo(object) <= 0);
			return 1;
		}
	}

	/**
	 * <code>__tostring</code> metamethod implementation.
	 */
	private class ToString implements JavaFunction {
		@Override
		public int invoke(LuaState luaState) {
			Object object = luaState.toJavaObject(1, Object.class);
			luaState.pushString(object != null ? object.toString() : "null");
			return 1;
		}
	}

	/**
	 * Provides an iterator for maps. For <code>NavigableMap</code> objects, the
	 * function returns a stateless iterator which allows concurrent
	 * modifications to the map. For other maps, the function returns an
	 * iterator based on <code>Iterator</code> which does not support concurrent
	 * modifications.
	 */
	private static class Pairs implements NamedJavaFunction {
		// -- Static
		private final JavaFunction navigableMapNext = new NavigableMapNext();

		// -- JavaFunction methods
		@SuppressWarnings("unchecked")
		@Override
		public int invoke(LuaState luaState) {
			Map<Object, Object> map = luaState.checkJavaObject(1, Map.class);
			luaState.checkArg(1, map != null,
					String.format("expected map, got %s", luaState.typeName(1)));
			if (map instanceof NavigableMap) {
				luaState.pushJavaFunction(navigableMapNext);
			} else {
				luaState.pushJavaFunction(new MapNext(map.entrySet().iterator()));
			}
			luaState.pushJavaObject(map);
			luaState.pushNil();
			return 3;
		}

		@Override
		public String getName() {
			return "pairs";
		}

		/**
		 * Provides a stateful iterator function for maps.
		 */
		private static class MapNext implements JavaFunction {
			// -- State
			private Iterator<Map.Entry<Object, Object>> iterator;

			// -- Construction
			/**
			 * Creates a new instance.
			 */
			public MapNext(Iterator<Map.Entry<Object, Object>> iterator) {
				this.iterator = iterator;
			}

			// -- JavaFunction methods
			public int invoke(LuaState luaState) {
				if (iterator.hasNext()) {
					Map.Entry<Object, Object> entry = iterator.next();
					luaState.pushJavaObject(entry.getKey());
					luaState.pushJavaObject(entry.getValue());
					return 2;
				} else {
					luaState.pushNil();
					return 1;
				}
			}
		}

		/**
		 * Provides a stateless iterator function for navigable maps.
		 */
		private static class NavigableMapNext implements JavaFunction {
			// -- JavaFunction methods
			@SuppressWarnings("unchecked")
			public int invoke(LuaState luaState) {
				NavigableMap<Object, Object> navigableMap = luaState
						.checkJavaObject(1, NavigableMap.class);
				Object key = luaState.checkJavaObject(2, Object.class);
				Map.Entry<Object, Object> entry;
				if (key != null) {
					entry = navigableMap.higherEntry(key);
				} else {
					entry = navigableMap.firstEntry();
				}
				if (entry != null) {
					luaState.pushJavaObject(entry.getKey());
					luaState.pushJavaObject(entry.getValue());
					return 2;
				} else {
					luaState.pushNil();
					return 1;
				}
			}
		}
	}

	/**
	 * Provides an iterator for lists and arrays.
	 */
	private static class IPairs implements NamedJavaFunction {
		// -- Static
		private final JavaFunction listNext = new ListNext();
		private final JavaFunction arrayNext = new ArrayNext();

		// -- JavaFunction methods
		@Override
		public int invoke(LuaState luaState) {
			Object object;
			if (luaState.isJavaObject(1, List.class)) {
				object = luaState.toJavaObject(1, List.class);
				luaState.pushJavaFunction(listNext);
			} else {
				object = luaState.checkJavaObject(1, Object.class);
				luaState.checkArg(1, object.getClass().isArray(), String
						.format("expected list or array, got %s",
								luaState.typeName(1)));
				luaState.pushJavaFunction(arrayNext);
			}
			luaState.pushJavaObject(object);
			luaState.pushInteger(0);
			return 3;
		}

		@Override
		public String getName() {
			return "ipairs";
		}

		/**
		 * Provides a stateless iterator function for lists.
		 */
		private static class ListNext implements JavaFunction {
			public int invoke(LuaState luaState) {
				List<?> list = luaState.checkJavaObject(1, List.class);
				int size = list.size();
				int index = luaState.checkInteger(2);
				index++;
				if (index >= 1 && index <= size) {
					luaState.pushInteger(index);
					luaState.pushJavaObject(list.get(index - 1));
					return 2;
				} else {
					luaState.pushNil();
					return 1;
				}
			}
		}

		/**
		 * Provides a stateless iterator function for arrays.
		 */
		private static class ArrayNext implements JavaFunction {
			public int invoke(LuaState luaState) {
				Object array = luaState.checkJavaObject(1, Object.class);
				int length = java.lang.reflect.Array.getLength(array);
				int index = luaState.checkInteger(2);
				index++;
				if (index >= 1 && index <= length) {
					luaState.pushInteger(index);
					luaState.pushJavaObject(Array.get(array, index - 1));
					return 2;
				} else {
					luaState.pushNil();
					return 1;
				}
			}
		}
	}

	/**
	 * Provides an iterator for accessors.
	 */
	private class AccessorPairs implements JavaFunction {
		// -- State
		private Class<?> accessorClass;

		// -- Construction
		/**
		 * Creates a new instance.
		 */
		public AccessorPairs(Class<?> accessorClass) {
			this.accessorClass = accessorClass;
		}

		// -- JavaFunction methods
		@Override
		public int invoke(LuaState luaState) {
			// Get object
			Object object = luaState.toJavaObject(1, Object.class);
			Class<?> objectClass = getObjectClass(object);

			// Create iterator
			Map<String, Accessor> objectAccessors = getObjectAccessors(object);
			Iterator<Entry<String, Accessor>> iterator = objectAccessors
					.entrySet().iterator();
			luaState.pushJavaObject(new AccessorNext(iterator,
					objectClass == object));
			luaState.pushJavaObject(object);
			luaState.pushNil();
			return 3;
		}

		// -- Member types
		/**
		 * Provides the next function for iterating accessors.
		 */
		private class AccessorNext implements JavaFunction {
			// -- State
			private Iterator<Entry<String, Accessor>> iterator;
			private boolean isStatic;

			// -- Construction
			/**
			 * Creates a new instance.
			 */
			public AccessorNext(Iterator<Entry<String, Accessor>> iterator,
					boolean isStatic) {
				this.iterator = iterator;
				this.isStatic = isStatic;
			}

			// -- JavaFunction methods
			@Override
			public int invoke(LuaState luaState) {
				while (iterator.hasNext()) {
					Entry<String, Accessor> entry = iterator.next();
					Accessor accessor = entry.getValue();

					// Filter by accessor class
					if (accessor.getClass() != accessorClass) {
						continue;
					}

					// Filter by non-static, static
					if (isStatic) {
						if (!accessor.isStatic()) {
							continue;
						}
					} else {
						if (!accessor.isNotStatic()) {
							continue;
						}
					}

					// Push match
					luaState.pushString(entry.getKey());
					Object object = luaState.toJavaObject(1, Object.class);
					accessor.read(luaState, object);
					return 2;
				}

				// End iteration
				return 0;
			}
		}
	}

	/**
	 * Provides access to class or object members.
	 */
	private interface Accessor {
		/**
		 * Reads the object member.
		 */
		void read(LuaState luaState, Object object);

		/**
		 * Writes the object member.
		 */
		void write(LuaState luaState, Object object);

		/**
		 * Returns whether this accessor is applicable in a non-static context.
		 */
		boolean isNotStatic();

		/**
		 * Returns whether this accessor is applicable in a static context.
		 */
		boolean isStatic();
	}

	/**
	 * Provides field access.
	 */
	private class FieldAccessor implements Accessor {
		// -- State
		private Field field;

		// -- Construction
		/**
		 * Creates a new instance.
		 */
		public FieldAccessor(Field field) {
			this.field = field;
		}

		// -- Accessor methods
		@Override
		public void read(LuaState luaState, Object object) {
			try {
				Class<?> objectClass = getObjectClass(object);
				if (objectClass == object) {
					object = null;
				}
				luaState.pushJavaObject(field.get(object));
			} catch (IllegalArgumentException e) {
				throw new RuntimeException(e);
			} catch (IllegalAccessException e) {
				throw new RuntimeException(e);
			}
		}

		@Override
		public void write(LuaState luaState, Object object) {
			try {
				Class<?> objectClass = getObjectClass(object);
				if (objectClass == object) {
					object = null;
				}
				Object value = luaState.checkJavaObject(-1, field.getType());
				field.set(object, value);
			} catch (IllegalArgumentException e) {
				throw new RuntimeException(e);
			} catch (IllegalAccessException e) {
				throw new RuntimeException(e);
			}
		}

		@Override
		public boolean isNotStatic() {
			return !Modifier.isStatic(field.getModifiers());
		}

		@Override
		public boolean isStatic() {
			return Modifier.isStatic(field.getModifiers());
		}
	}

	/**
	 * Provides invocable access.
	 */
	private class InvocableAccessor implements Accessor, JavaFunction {
		// -- State
		private Class<?> clazz;
		private List<Invocable> invocables;

		// -- Construction
		/**
		 * Creates a new instance.
		 */
		public InvocableAccessor(Class<?> clazz,
				Collection<Invocable> invocables) {
			this.clazz = clazz;
			this.invocables = new ArrayList<Invocable>(invocables);
		}

		// -- Properties
		/**
		 * Returns the name of the invocable.
		 */
		public String getName() {
			return invocables.get(0).getName();
		}

		/**
		 * Returns what this invocable accessor is for.
		 */
		public String getWhat() {
			return invocables.get(0).getWhat();
		}

		// -- Accessor methods
		@Override
		public void read(LuaState luaState, Object object) {
			Class<?> objectClass = getObjectClass(object);
			if (objectClass == object) {
				object = null;
			}
			luaState.pushJavaFunction(this);
		}

		@Override
		public void write(LuaState luaState, Object object) {
			Class<?> objectClass = getObjectClass(object);
			throw new LuaRuntimeException(String.format(
					"attempt to write class %s with accessor '%s' (a %s)",
					objectClass.getCanonicalName(), getName(), getWhat()));
		}

		@Override
		public boolean isNotStatic() {
			for (Invocable invocable : invocables) {
				if (!Modifier.isStatic(invocable.getModifiers())) {
					return true;
				}
			}
			return false;
		}

		@Override
		public boolean isStatic() {
			for (Invocable invocable : invocables) {
				if (Modifier.isStatic(invocable.getModifiers())) {
					return true;
				}
			}
			return false;
		}

		// -- JavaFunction methods
		@Override
		public int invoke(LuaState luaState) {
			// Argument sanity checks
			Object object = luaState.checkJavaObject(1, Object.class);
			Class<?> objectClass = getObjectClass(object);
			luaState.checkArg(1, clazz.isAssignableFrom(objectClass), String
					.format("class %s is not a subclass of %s",
							objectClass.getCanonicalName(),
							clazz.getCanonicalName()));
			if (objectClass == object) {
				object = null;
			}

			// Invocable dispatch
			LuaCallSignature luaCallSignature = getLuaCallSignature(luaState);
			Invocable invocable;
			invocableDispatchLock.readLock().lock();
			try {
				invocable = invocableDispatches.get(luaCallSignature);
			} finally {
				invocableDispatchLock.readLock().unlock();
			}
			if (invocable == null) {
				invocable = dispatchInvocable(luaState, object == null);
				invocableDispatchLock.writeLock().lock();
				try {
					if (!invocableDispatches.containsKey(luaCallSignature)) {
						invocableDispatches.put(luaCallSignature, invocable);
					} else {
						invocable = invocableDispatches.get(luaCallSignature);
					}
				} finally {
					invocableDispatchLock.writeLock().unlock();
				}
			}

			// Prepare arguments
			int argCount = luaState.getTop() - 1;
			int parameterCount = invocable.getParameterCount();
			Object[] arguments = new Object[parameterCount];
			if (invocable.isVarArgs()) {
				for (int i = 0; i < parameterCount - 1; i++) {
					arguments[i] = luaState.toJavaObject(i + 2,
							invocable.getParameterType(i));
				}
				arguments[parameterCount - 1] = Array.newInstance(
						invocable.getParameterType(parameterCount - 1),
						argCount - (parameterCount - 1));
				for (int i = parameterCount - 1; i < argCount; i++) {
					Array.set(
							arguments[parameterCount - 1],
							i - (parameterCount - 1),
							luaState.toJavaObject(i + 2,
									invocable.getParameterType(i)));
				}
			} else {
				for (int i = 0; i < parameterCount; i++) {
					arguments[i] = luaState.toJavaObject(i + 2,
							invocable.getParameterType(i));
				}
			}

			// Invoke
			Object result;
			try {
				result = invocable.invoke(object, arguments);
			} catch (InstantiationException e) {
				throw new RuntimeException(e);
			} catch (IllegalArgumentException e) {
				throw new RuntimeException(e);
			} catch (IllegalAccessException e) {
				throw new RuntimeException(e);
			} catch (InvocationTargetException e) {
				throw new RuntimeException(e.getTargetException());
			}

			// Return
			if (invocable.getReturnType() != Void.TYPE) {
				if (invocable.isRawReturn()) {
					luaState.pushJavaObjectRaw(result);
				} else {
					luaState.pushJavaObject(result);
				}
				return 1;
			} else {
				return 0;
			}
		}

		// -- Private methods
		/**
		 * Creates a Lua call signature.
		 */
		private LuaCallSignature getLuaCallSignature(LuaState luaState) {
			int argCount = luaState.getTop() - 1;
			Object[] types = new Object[argCount];
			for (int i = 0; i < argCount; i++) {
				LuaType type = luaState.type(i + 2);
				switch (type) {
				case FUNCTION:
					types[i] = luaState.isJavaFunction(i + 2) ? JAVA_FUNCTION_TYPE
							: LuaType.FUNCTION;
					break;
				case USERDATA:
					if (luaState.isJavaObjectRaw(i + 2)) {
						Object object = luaState.toJavaObjectRaw(i + 2);
						if (object instanceof TypedJavaObject) {
							types[i] = ((TypedJavaObject) object).getType();
						} else {
							types[i] = object.getClass();
						}
					} else {
						types[i] = LuaType.USERDATA;
					}
					break;
				default:
					types[i] = type;
				}
			}
			return new LuaCallSignature(clazz, getName(), types);
		}

		/**
		 * Dispatches an invocable.
		 */
		private Invocable dispatchInvocable(LuaState luaState,
				boolean staticDispatch) {
			// Begin with all candidates
			Set<Invocable> candidates = new HashSet<Invocable>(invocables);

			// Eliminate methods with an invalid static modifier
			for (Iterator<Invocable> i = candidates.iterator(); i.hasNext();) {
				Invocable invocable = i.next();
				if (Modifier.isStatic(invocable.getModifiers()) != staticDispatch) {
					i.remove();
				}
			}

			// Eliminate methods with an invalid parameter count
			int argCount = luaState.getTop() - 1;
			for (Iterator<Invocable> i = candidates.iterator(); i.hasNext();) {
				Invocable invocable = i.next();
				if (invocable.isVarArgs()) {
					if (argCount < invocable.getParameterCount() - 1) {
						i.remove();
					}
				} else {
					if (argCount != invocable.getParameterCount()) {
						i.remove();
					}
				}
			}

			// Eliminate methods that are not applicable
			Converter converter = luaState.getConverter();
			outer: for (Iterator<Invocable> i = candidates.iterator(); i
					.hasNext();) {
				Invocable invocable = i.next();
				for (int j = 0; j < argCount; j++) {
					int distance = converter.getTypeDistance(luaState, j + 2,
							invocable.getParameterType(j));
					if (distance == Integer.MAX_VALUE) {
						i.remove();
						continue outer;
					}
				}
			}

			// Eliminate variable arguments methods in the presence of fix
			// arguments methods
			boolean haveFixArgs = false;
			boolean haveVarArgs = false;
			for (Invocable invocable : candidates) {
				haveFixArgs = haveFixArgs || !invocable.isVarArgs();
				haveVarArgs = haveVarArgs || invocable.isVarArgs();
			}
			if (haveVarArgs && haveFixArgs) {
				for (Iterator<Invocable> i = candidates.iterator(); i.hasNext();) {
					Invocable invocable = i.next();
					if (invocable.isVarArgs()) {
						i.remove();
					}
				}
			}

			// Eliminate methods that are not closest
			outer: for (Iterator<Invocable> i = candidates.iterator(); i
					.hasNext();) {
				Invocable invocable = i.next();
				inner: for (Invocable other : candidates) {
					if (other == invocable) {
						continue;
					}
					int parameterCount = Math.min(
							argCount,
							Math.max(invocable.getParameterCount(),
									other.getParameterCount()));
					boolean delta = false;
					for (int j = 0; j < parameterCount; j++) {
						int distance = converter.getTypeDistance(luaState,
								j + 2, invocable.getParameterType(j));
						int otherDistance = converter.getTypeDistance(luaState,
								j + 2, other.getParameterType(j));
						if (otherDistance > distance) {
							// Other is not closer
							continue inner;
						}
						delta = delta || distance != otherDistance;
					}

					// If there is no delta, other is not closer
					if (!delta) {
						continue;
					}

					// Other is closer
					i.remove();
					continue outer;
				}
			}

			// Eliminate methods that are not most precise
			outer: for (Iterator<Invocable> i = candidates.iterator(); i
					.hasNext();) {
				Invocable invocable = i.next();
				inner: for (Invocable other : candidates) {
					if (other == invocable) {
						continue;
					}
					int parameterCount = Math.min(
							argCount,
							Math.max(invocable.getParameterCount(),
									other.getParameterCount()));
					boolean delta = false;
					for (int j = 0; j < parameterCount; j++) {
						Class<?> type = invocable.getParameterType(j);
						Class<?> otherType = other.getParameterType(j);
						if (!type.isAssignableFrom(otherType)) {
							// Other is not more specific
							continue inner;
						}
						delta = delta || type != otherType;
					}

					// If there is no delta, other is not more specific
					if (!delta) {
						continue;
					}

					// Other is more specific
					i.remove();
					continue outer;
				}
			}

			// Handle outcomes
			if (candidates.isEmpty()) {
				throw getSignatureMismatchException(luaState);
			}
			if (candidates.size() > 1) {
				throw getSignatureAmbivalenceException(luaState, candidates);
			}

			// Return
			return candidates.iterator().next();
		}

		/**
		 * Returns a Lua runtime exception indicating that no matching invocable
		 * has been found.
		 */
		private LuaRuntimeException getSignatureMismatchException(
				LuaState luaState) {
			return new LuaRuntimeException(String.format(
					"no %s of class %s matches '%s(%s)'", getWhat(),
					clazz.getCanonicalName(), getName(),
					getLuaSignatureString(luaState)));
		}

		/**
		 * Returns a Lua runtime exception indicating that an invocable is
		 * ambivalent.
		 */
		private LuaRuntimeException getSignatureAmbivalenceException(
				LuaState luaState, Set<Invocable> candidates) {
			StringBuffer sb = new StringBuffer();
			sb.append(String.format(
					"%s '%s(%s)' on class %s is ambivalent among ", getWhat(),
					getName(), getLuaSignatureString(luaState),
					clazz.getCanonicalName()));
			boolean first = true;
			for (Invocable invocable : candidates) {
				if (first) {
					first = false;
				} else {
					sb.append(", ");
				}
				sb.append(String.format("'%s(%s)'", getName(),
						getJavaSignatureString(invocable.getParameterTypes())));
			}
			return new LuaRuntimeException(sb.toString());
		}

		/**
		 * Returns a Lua value signature string for diagnostic messages.
		 */
		private String getLuaSignatureString(LuaState luaState) {
			int argCount = luaState.getTop() - 1;
			StringBuffer sb = new StringBuffer();
			for (int i = 0; i < argCount; i++) {
				if (i > 0) {
					sb.append(", ");
				}
				sb.append(luaState.typeName(i + 2));
			}
			return sb.toString();
		}

		/**
		 * Returns a Java type signature string for diagnostic messages.
		 */
		private String getJavaSignatureString(Class<?>[] types) {
			StringBuffer sb = new StringBuffer();
			for (int i = 0; i < types.length; i++) {
				if (i > 0) {
					sb.append(", ");
				}
				sb.append(types[i].getCanonicalName());
			}
			return sb.toString();
		}
	}

	/**
	 * Provides property access.
	 */
	private class PropertyAccessor implements Accessor {
		// -- State
		private Class<?> clazz;
		private PropertyDescriptor propertyDescriptor;

		// -- Construction
		/**
		 * Creates a new instance.
		 */
		public PropertyAccessor(Class<?> clazz,
				PropertyDescriptor propertyDescriptor) {
			this.clazz = clazz;
			this.propertyDescriptor = propertyDescriptor;
		}

		// -- Accessor methods
		@Override
		public void read(LuaState luaState, Object object) {
			if (propertyDescriptor.getReadMethod() == null) {
				throw new LuaRuntimeException(
						String.format(
								"attempt to read class %s with accessor '%s' (a write-only property)",
								clazz.getCanonicalName(),
								propertyDescriptor.getName()));
			}
			try {
				luaState.pushJavaObject(propertyDescriptor.getReadMethod()
						.invoke(object, EMPTY_ARGUMENTS));
			} catch (IllegalArgumentException e) {
				throw new RuntimeException(e);
			} catch (IllegalAccessException e) {
				throw new RuntimeException(e);
			} catch (InvocationTargetException e) {
				throw new RuntimeException(e.getTargetException());
			}
		}

		@Override
		public void write(LuaState luaState, Object object) {
			if (propertyDescriptor.getWriteMethod() == null) {
				throw new LuaRuntimeException(
						String.format(
								"attempt to write class %s with acessor '%s' (a read-only property)",
								clazz.getCanonicalName(),
								propertyDescriptor.getName()));
			}
			try {
				Object value = luaState.checkJavaObject(-1,
						propertyDescriptor.getPropertyType());
				propertyDescriptor.getWriteMethod().invoke(object, value);
			} catch (IllegalArgumentException e) {
				throw new RuntimeException(e);
			} catch (IllegalAccessException e) {
				throw new RuntimeException(e);
			} catch (InvocationTargetException e) {
				throw new RuntimeException(e.getTargetException());
			}
			luaState.pop(1);
		}

		@Override
		public boolean isNotStatic() {
			return true;
		}

		@Override
		public boolean isStatic() {
			return false;
		}
	}

	/**
	 * Virtual superinterface for methods and constructors.
	 */
	private interface Invocable {
		/**
		 * Returns what this invocable is, for use in diagnostic messages.
		 */
		public String getWhat();

		/**
		 * Returns the declaring class of this invocable.
		 */
		public Class<?> getDeclaringClass();

		/**
		 * Returns the modifiers of this invocable.
		 */
		public int getModifiers();

		/**
		 * Returns the name of this invocable.
		 */
		public String getName();

		/**
		 * Returns the return type of this invocable.
		 */
		public Class<?> getReturnType();

		/**
		 * Returns whether this invocable has a return value that must be pushed
		 * raw.
		 */
		public boolean isRawReturn();

		/**
		 * Returns the number of parameters.
		 */
		public int getParameterCount();

		/**
		 * Returns the parameter types of this invocable.
		 */
		public Class<?>[] getParameterTypes();

		/**
		 * Returns a parameter type, flattening variable arguments.
		 */
		public Class<?> getParameterType(int index);

		/**
		 * Returns whether this invocable has a variable number of arguments.
		 */
		public boolean isVarArgs();

		/**
		 * Invokes this invocable.
		 */
		public Object invoke(Object obj, Object... args)
				throws InstantiationException, IllegalAccessException,
				IllegalArgumentException, InvocationTargetException;
	}

	/**
	 * Invocable method.
	 */
	private static class InvocableMethod implements Invocable {
		private Method method;
		private Class<?>[] parameterTypes;

		/**
		 * Creates a new instance.
		 */
		public InvocableMethod(Method method) {
			this.method = method;
			this.parameterTypes = method.getParameterTypes();
		}

		@Override
		public String getWhat() {
			return "method";
		}

		@Override
		public Class<?> getDeclaringClass() {
			return method.getDeclaringClass();
		}

		@Override
		public int getModifiers() {
			return method.getModifiers();
		}

		@Override
		public String getName() {
			return method.getName();
		}

		@Override
		public Class<?> getReturnType() {
			return method.getReturnType();
		}

		@Override
		public boolean isRawReturn() {
			return false;
		}

		@Override
		public int getParameterCount() {
			return parameterTypes.length;
		}

		@Override
		public Class<?>[] getParameterTypes() {
			return parameterTypes;
		}

		@Override
		public Class<?> getParameterType(int index) {
			if (method.isVarArgs() && index >= parameterTypes.length - 1) {
				return parameterTypes[parameterTypes.length - 1]
						.getComponentType();
			} else {
				return parameterTypes[index];
			}
		}

		@Override
		public boolean isVarArgs() {
			return method.isVarArgs();
		}

		@Override
		public Object invoke(Object obj, Object... args)
				throws IllegalAccessException, IllegalArgumentException,
				InvocationTargetException {
			return method.invoke(obj, args);
		}

		@Override
		public String toString() {
			return method.toString();
		}
	}

	/**
	 * Invocable constructor.
	 */
	private static class InvocableConstructor implements Invocable {
		// -- State
		private Constructor<?> constructor;
		private Class<?>[] parameterTypes;

		/**
		 * Creates a new instance.
		 */
		public InvocableConstructor(Constructor<?> constructor) {
			this.constructor = constructor;
			this.parameterTypes = constructor.getParameterTypes();
		}

		@Override
		public String getWhat() {
			return "constructor";
		}

		@Override
		public Class<?> getDeclaringClass() {
			return constructor.getDeclaringClass();
		}

		@Override
		public int getModifiers() {
			return constructor.getModifiers() | Modifier.STATIC;
		}

		@Override
		public String getName() {
			return "new";
		}

		@Override
		public Class<?> getReturnType() {
			return constructor.getDeclaringClass();
		}

		@Override
		public boolean isRawReturn() {
			return false;
		}

		@Override
		public int getParameterCount() {
			return parameterTypes.length;
		}

		@Override
		public Class<?>[] getParameterTypes() {
			return parameterTypes;
		}

		@Override
		public Class<?> getParameterType(int index) {
			if (constructor.isVarArgs() && index >= parameterTypes.length - 1) {
				return parameterTypes[parameterTypes.length - 1]
						.getComponentType();
			} else {
				return parameterTypes[index];
			}
		}

		@Override
		public boolean isVarArgs() {
			return constructor.isVarArgs();
		}

		@Override
		public Object invoke(Object obj, Object... args)
				throws InstantiationException, IllegalAccessException,
				IllegalArgumentException, InvocationTargetException {
			return constructor.newInstance(args);
		}

		@Override
		public String toString() {
			return constructor.toString();
		}
	}

	/**
	 * Invocable proxy.
	 */
	private static class InvocableProxy implements Invocable {
		// -- Static
		private static final Class<?>[] PARAMETER_TYPES = new Class<?>[] { LuaValueProxy.class };

		// -- State
		private Class<?> interfaze;

		/**
		 * Creates a new instance.
		 */
		public InvocableProxy(Class<?> interfaze) {
			this.interfaze = interfaze;
		}

		@Override
		public String getWhat() {
			return "proxy";
		}

		@Override
		public Class<?> getDeclaringClass() {
			return interfaze;
		}

		@Override
		public int getModifiers() {
			return interfaze.getModifiers() | Modifier.STATIC;
		}

		@Override
		public String getName() {
			return "new";
		}

		@Override
		public Class<?> getReturnType() {
			return interfaze;
		}

		@Override
		public boolean isRawReturn() {
			return true;
		}

		@Override
		public int getParameterCount() {
			return 1;
		}

		@Override
		public Class<?>[] getParameterTypes() {
			return PARAMETER_TYPES;
		}

		@Override
		public Class<?> getParameterType(int index) {
			return PARAMETER_TYPES[0];
		}

		@Override
		public boolean isVarArgs() {
			return false;
		}

		@Override
		public Object invoke(Object obj, Object... args)
				throws InstantiationException, IllegalAccessException,
				IllegalArgumentException, InvocationTargetException {
			LuaValueProxy luaValueProxy = (LuaValueProxy) args[0];
			luaValueProxy.pushValue();
			Object proxy = luaValueProxy.getLuaState().getProxy(-1, interfaze);
			luaValueProxy.getLuaState().pop(1);
			return proxy;
		}

		@Override
		public String toString() {
			return interfaze.toString();
		}
	}

	/**
	 * Lua call signature.
	 */
	private static class LuaCallSignature {
		// -- State
		private Class<?> clazz;
		private String invocableName;
		private Object[] types;
		private int hashCode;

		// -- Construction
		/**
		 * Creates a new instance.
		 */
		public LuaCallSignature(Class<?> clazz, String invocableName,
				Object[] types) {
			this.clazz = clazz;
			this.invocableName = invocableName;
			this.types = types;
			hashCode = clazz.hashCode();
			hashCode = hashCode * 65599 + invocableName.hashCode();
			for (int i = 0; i < types.length; i++) {
				hashCode = hashCode * 65599 + types[i].hashCode();
			}
		}

		@Override
		public int hashCode() {
			return hashCode;
		}

		@Override
		public boolean equals(Object obj) {
			if (obj == this) {
				return true;
			}
			if (!(obj instanceof LuaCallSignature)) {
				return false;
			}
			LuaCallSignature other = (LuaCallSignature) obj;
			if (clazz != other.clazz
					|| !invocableName.equals(other.invocableName)
					|| types.length != other.types.length) {
				return false;
			}
			for (int i = 0; i < types.length; i++) {
				if (types[i] != other.types[i]) {
					return false;
				}
			}
			return true;
		}

		@Override
		public String toString() {
			return clazz.getCanonicalName() + ": " + invocableName + "("
					+ Arrays.asList(types) + ")";
		}
	}
}
