/*
 * Copyright 1999-2011 Alibaba Group.
 *  
 * 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.alibaba.dubbo.common.bytecode;

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.HashMap;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.atomic.AtomicLong;
import java.util.regex.Matcher;

import com.alibaba.dubbo.common.utils.ClassHelper;
import com.alibaba.dubbo.common.utils.ReflectUtils;

/**
 * Wrapper.
 * 
 * @author qian.lei
 */

public abstract class Wrapper
{
	private static AtomicLong WRAPPER_CLASS_COUNTER = new AtomicLong(0);

	private static final Map<Class<?>, Wrapper> WRAPPER_MAP = new ConcurrentHashMap<Class<?>, Wrapper>(); //class wrapper map

	private static final String[] EMPTY_STRING_ARRAY = new String[0];

	private static final String[] OBJECT_METHODS = new String[]{"getClass", "hashCode", "toString", "equals"};

	private static final Wrapper OBJECT_WRAPPER = new Wrapper(){
		public String[] getMethodNames(){ return OBJECT_METHODS; }
		public String[] getDeclaredMethodNames(){ return OBJECT_METHODS; }
		public String[] getPropertyNames(){ return EMPTY_STRING_ARRAY; }
		public Class<?> getPropertyType(String pn){ return null; }
		public Object getPropertyValue(Object instance, String pn) throws NoSuchPropertyException{ throw new NoSuchPropertyException("Property [" + pn + "] not found."); }
		public void setPropertyValue(Object instance, String pn, Object pv) throws NoSuchPropertyException{ throw new NoSuchPropertyException("Property [" + pn + "] not found."); }
		public boolean hasProperty(String name){ return false; }
		public Object invokeMethod(Object instance, String mn, Class<?>[] types, Object[] args) throws NoSuchMethodException
		{
			if( "getClass".equals(mn) ) return instance.getClass();
			if( "hashCode".equals(mn) ) return instance.hashCode();
			if( "toString".equals(mn) ) return instance.toString();
			if( "equals".equals(mn) )
			{
				if( args.length == 1 ) return instance.equals(args[0]);
				throw new IllegalArgumentException("Invoke method [" + mn + "] argument number error.");
			}
			throw new NoSuchMethodException("Method [" + mn + "] not found.");
		}
	};

	/**
	 * get wrapper.
	 * 
	 * @param c Class instance.
	 * @return Wrapper instance(not null).
	 */
	public static Wrapper getWrapper(Class<?> c)
    {
        while( ClassGenerator.isDynamicClass(c) ) // can not wrapper on dynamic class.
            c = c.getSuperclass();

        if( c == Object.class )
            return OBJECT_WRAPPER;

        Wrapper ret = WRAPPER_MAP.get(c);
        if( ret == null )
        {
            ret = makeWrapper(c);
            WRAPPER_MAP.put(c,ret);
        }
        return ret;
    }
	/**
	 * get property name array.
	 * 
	 * @return property name array.
	 */
	abstract public String[] getPropertyNames();

	/**
	 * get property type.
	 * 
	 * @param pn property name.
	 * @return Property type or nul.
	 */
	abstract public Class<?> getPropertyType(String pn);

	/**
	 * has property.
	 * 
	 * @param name property name.
	 * @return has or has not.
	 */
	abstract public boolean hasProperty(String name);

	/**
	 * get property value.
	 * 
	 * @param instance instance.
	 * @param pn property name.
	 * @return value.
	 */
	abstract public Object getPropertyValue(Object instance, String pn) throws NoSuchPropertyException, IllegalArgumentException;

	/**
	 * set property value.
	 * 
	 * @param instance instance.
	 * @param pn property name.
	 * @param pv property value.
	 */
	abstract public void setPropertyValue(Object instance, String pn, Object pv) throws NoSuchPropertyException, IllegalArgumentException;

	/**
	 * get property value.
	 * 
	 * @param instance instance.
	 * @param pns property name array.
	 * @return value array.
	 */
	public Object[] getPropertyValues(Object instance, String[] pns) throws NoSuchPropertyException, IllegalArgumentException
	{
		Object[] ret = new Object[pns.length];
		for(int i=0;i<ret.length;i++)
			ret[i] = getPropertyValue(instance, pns[i]);
		return ret;
	}

	/**
	 * set property value.
	 * 
	 * @param instance instance.
	 * @param pns property name array.
	 * @param pvs property value array.
	 */
	public void setPropertyValues(Object instance, String[] pns, Object[] pvs) throws NoSuchPropertyException, IllegalArgumentException
	{
		if( pns.length != pvs.length )
			throw new IllegalArgumentException("pns.length != pvs.length");

		for(int i=0;i<pns.length;i++)
			setPropertyValue(instance, pns[i], pvs[i]);
	}

	/**
	 * get method name array.
	 * 
	 * @return method name array.
	 */
	abstract public String[] getMethodNames();

	/**
	 * get method name array.
	 * 
	 * @return method name array.
	 */
	abstract public String[] getDeclaredMethodNames();

	/**
	 * has method.
	 * 
	 * @param name method name.
	 * @return has or has not.
	 */
	public boolean hasMethod(String name)
	{
		for( String mn : getMethodNames() )
			if( mn.equals(name) ) return true;
		return false;
	}

	/**
	 * invoke method.
	 * 
	 * @param instance instance.
	 * @param mn method name.
	 * @param types 
	 * @param args argument array.
	 * @return return value.
	 */
	abstract public Object invokeMethod(Object instance, String mn, Class<?>[] types, Object[] args) throws NoSuchMethodException, InvocationTargetException;

	private static Wrapper makeWrapper(Class<?> c)
	{
		if( c.isPrimitive() )
			throw new IllegalArgumentException("Can not create wrapper for primitive type: " + c);

		String name = c.getName();
		ClassLoader cl = ClassHelper.getClassLoader(c);

		StringBuilder c1 = new StringBuilder("public void setPropertyValue(Object o, String n, Object v){ ");
		StringBuilder c2 = new StringBuilder("public Object getPropertyValue(Object o, String n){ ");
		StringBuilder c3 = new StringBuilder("public Object invokeMethod(Object o, String n, Class[] p, Object[] v) throws " + InvocationTargetException.class.getName() + "{ ");

		c1.append(name).append(" w; try{ w = ((").append(name).append(")$1); }catch(Throwable e){ throw new IllegalArgumentException(e); }");
		c2.append(name).append(" w; try{ w = ((").append(name).append(")$1); }catch(Throwable e){ throw new IllegalArgumentException(e); }");
		c3.append(name).append(" w; try{ w = ((").append(name).append(")$1); }catch(Throwable e){ throw new IllegalArgumentException(e); } try{");

		Map<String, Class<?>> pts = new HashMap<String, Class<?>>(); // <property name, property types>
		Map<String, Method> ms = new LinkedHashMap<String, Method>(); // <method desc, Method instance>
		List<String> mns = new ArrayList<String>(); // method names.
		List<String> dmns = new ArrayList<String>(); // declaring method names.
		
		// get all public field.
		for( Field f : c.getFields() )
		{
			String fn = f.getName();
			Class<?> ft = f.getType();
			if( Modifier.isStatic(f.getModifiers()) || Modifier.isTransient(f.getModifiers()) )
				continue;

			c1.append(" if( $2.equals(\"").append(fn).append("\") ){ w.").append(fn).append("=").append(arg(ft, "$3")).append("; return; }");
			c2.append(" if( $2.equals(\"").append(fn).append("\") ){ return ($w)w.").append(fn).append("; }");
			pts.put(fn, ft);
		}
		
		Method[] methods = c.getMethods();
		// get all public method.
		for( Method m : methods )
		{
			if( m.getDeclaringClass() == Object.class ) //ignore Object's method.
				continue;

			String mn = m.getName();
			c3.append(" if( \"").append(mn).append("\".equals( $2 ) ");
            int len = m.getParameterTypes().length;
            c3.append(" && ").append(" $3.length == ").append(len);
			
			boolean override = false;
			for( Method m2 : methods ) {
				if (m != m2 && m.getName().equals(m2.getName())) {
					override = true;
					break;
				}
			}
			if (override) {
				if (len > 0) {
					for (int l = 0; l < len; l ++) {
						c3.append(" && ").append(" $3[").append(l).append("].getName().equals(\"")
							.append(m.getParameterTypes()[l].getName()).append("\")");
					}
				}
			}
			
			c3.append(" ) { ");
			
			if( m.getReturnType() == Void.TYPE )
				c3.append(" w.").append(mn).append('(').append(args(m.getParameterTypes(), "$4")).append(");").append(" return null;");
			else
				c3.append(" return ($w)w.").append(mn).append('(').append(args(m.getParameterTypes(), "$4")).append(");");

			c3.append(" }");
			
			mns.add(mn);
			if( m.getDeclaringClass() == c )
				dmns.add(mn);
			ms.put(ReflectUtils.getDesc(m), m);
		}
		c3.append(" } catch(Throwable e) { " );
		c3.append("     throw new java.lang.reflect.InvocationTargetException(e); " );
		c3.append(" }");
		c3.append(" throw new " + NoSuchMethodException.class.getName() + "(\"Not found method \\\"\"+$2+\"\\\" in class " + c.getName() + ".\"); }");
		
		// deal with get/set method.
		Matcher matcher;
		for( Map.Entry<String,Method> entry : ms.entrySet() )
		{
			String md = entry.getKey();
			Method method = (Method)entry.getValue();
			if( ( matcher = ReflectUtils.GETTER_METHOD_DESC_PATTERN.matcher(md) ).matches() )
			{
				String pn = propertyName(matcher.group(1));
				c2.append(" if( $2.equals(\"").append(pn).append("\") ){ return ($w)w.").append(method.getName()).append("(); }");
				pts.put(pn, method.getReturnType());
			}
			else if( ( matcher = ReflectUtils.IS_HAS_CAN_METHOD_DESC_PATTERN.matcher(md) ).matches() )
			{
				String pn = propertyName(matcher.group(1));
				c2.append(" if( $2.equals(\"").append(pn).append("\") ){ return ($w)w.").append(method.getName()).append("(); }");
				pts.put(pn, method.getReturnType());
			}
			else if( ( matcher = ReflectUtils.SETTER_METHOD_DESC_PATTERN.matcher(md) ).matches() )
			{
				Class<?> pt = method.getParameterTypes()[0];
				String pn = propertyName(matcher.group(1));
				c1.append(" if( $2.equals(\"").append(pn).append("\") ){ w.").append(method.getName()).append("(").append(arg(pt,"$3")).append("); return; }");
				pts.put(pn, pt);
			}
		}
		c1.append(" throw new " + NoSuchPropertyException.class.getName() + "(\"Not found property \\\"\"+$2+\"\\\" filed or setter method in class " + c.getName() + ".\"); }");
		c2.append(" throw new " + NoSuchPropertyException.class.getName() + "(\"Not found property \\\"\"+$2+\"\\\" filed or setter method in class " + c.getName() + ".\"); }");

		// make class
		long id = WRAPPER_CLASS_COUNTER.getAndIncrement();
		ClassGenerator cc = ClassGenerator.newInstance(cl);
		cc.setClassName( ( Modifier.isPublic(c.getModifiers()) ? Wrapper.class.getName() : c.getName() + "$sw" ) + id );
		cc.setSuperClass(Wrapper.class);

		cc.addDefaultConstructor();
		cc.addField("public static String[] pns;"); // property name array.
		cc.addField("public static " + Map.class.getName() + " pts;"); // property type map.
		cc.addField("public static String[] mns;"); // all method name array.
		cc.addField("public static String[] dmns;"); // declared method name array.
		for(int i=0,len=ms.size();i<len;i++)
			cc.addField("public static Class[] mts" + i + ";");

		cc.addMethod("public String[] getPropertyNames(){ return pns; }");
		cc.addMethod("public boolean hasProperty(String n){ return pts.containsKey($1); }");
		cc.addMethod("public Class getPropertyType(String n){ return (Class)pts.get($1); }");
		cc.addMethod("public String[] getMethodNames(){ return mns; }");
		cc.addMethod("public String[] getDeclaredMethodNames(){ return dmns; }");
		cc.addMethod(c1.toString());
		cc.addMethod(c2.toString());
		cc.addMethod(c3.toString());

		try
		{
			Class<?> wc = cc.toClass();
			// setup static field.
			wc.getField("pts").set(null, pts);
			wc.getField("pns").set(null, pts.keySet().toArray(new String[0]));
			wc.getField("mns").set(null, mns.toArray(new String[0]));
			wc.getField("dmns").set(null, dmns.toArray(new String[0]));
			int ix = 0;
			for( Method m : ms.values() )
				wc.getField("mts" + ix++).set(null, m.getParameterTypes());
			return (Wrapper)wc.newInstance();
		}
		catch(RuntimeException e)
		{
			throw e;
		}
		catch(Throwable e)
		{
			throw new RuntimeException(e.getMessage(), e);
		}
		finally
		{
			cc.release();
			ms.clear();
			mns.clear();
			dmns.clear();
		}
	}

	private static String arg(Class<?> cl, String name)
	{
		if( cl.isPrimitive() )
		{
			if( cl == Boolean.TYPE )
				return "((Boolean)" + name + ").booleanValue()";
			if( cl == Byte.TYPE )
				return "((Byte)" + name + ").byteValue()";
			if( cl == Character.TYPE )
				return "((Character)" + name + ").charValue()";
			if( cl == Double.TYPE )
				return "((Number)" + name + ").doubleValue()";
			if( cl == Float.TYPE )
				return "((Number)" + name + ").floatValue()";
			if( cl == Integer.TYPE )
				return "((Number)" + name + ").intValue()";
			if( cl == Long.TYPE )
				return "((Number)" + name + ").longValue()";
			if( cl == Short.TYPE )
				return "((Number)" + name + ").shortValue()";
			throw new RuntimeException("Unknown primitive type: " + cl.getName());
		}
		return "(" + ReflectUtils.getName(cl) + ")" + name;
	}

	private static String args(Class<?>[] cs,String name)
	{
		int len = cs.length;
		if( len == 0 ) return "";
		StringBuilder sb = new StringBuilder();
		for(int i=0;i<len;i++)
		{
			if( i > 0 )
				sb.append(',');
			sb.append(arg(cs[i],name+"["+i+"]"));
		}
		return sb.toString();
	}

	private static String propertyName(String pn)
	{
		return pn.length() == 1 || Character.isLowerCase(pn.charAt(1)) ? Character.toLowerCase(pn.charAt(0)) + pn.substring(1) : pn;
	}
}