/*
 * 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.Method;
import java.lang.reflect.Modifier;
import java.util.HashSet;
import java.util.Set;
import java.util.concurrent.atomic.AtomicLong;

import com.alibaba.dubbo.common.utils.ClassHelper;
import com.alibaba.dubbo.common.utils.ReflectUtils;

/**
 * Mixin
 * 
 * @author qian.lei
 */

public abstract class Mixin
{
	private static AtomicLong MIXIN_CLASS_COUNTER = new AtomicLong(0);

	private static final String PACKAGE_NAME = Mixin.class.getPackage().getName();

	public static interface MixinAware{ void setMixinInstance(Object instance); }

	/**
	 * mixin interface and delegates.
	 * all class must be public.
	 * 
	 * @param ics interface class array.
	 * @param dc delegate class.
	 * @return Mixin instance.
	 */
	public static Mixin mixin(Class<?>[] ics, Class<?> dc)
	{
		return mixin(ics, new Class[]{dc});
	}

	/**
	 * mixin interface and delegates.
	 * all class must be public.
	 * 
	 * @param ics interface class array.
	 * @param dc delegate class.
	 * @param cl class loader.
	 * @return Mixin instance.
	 */
	public static Mixin mixin(Class<?>[] ics, Class<?> dc, ClassLoader cl)
	{
		return mixin(ics, new Class[]{dc}, cl);
	}

	/**
	 * mixin interface and delegates.
	 * all class must be public.
	 * 
	 * @param ics interface class array.
	 * @param dcs delegate class array.
	 * @return Mixin instance.
	 */
	public static Mixin mixin(Class<?>[] ics, Class<?>[] dcs)
	{
		return mixin(ics, dcs, ClassHelper.getClassLoader(ics[0]));
	}

	/**
	 * mixin interface and delegates.
	 * all class must be public.
	 * 
	 * @param ics interface class array.
	 * @param dcs delegate class array.
	 * @param cl class loader.
	 * @return Mixin instance.
	 */
	public static Mixin mixin(Class<?>[] ics, Class<?>[] dcs, ClassLoader cl)
	{
		assertInterfaceArray(ics);

		long id = MIXIN_CLASS_COUNTER.getAndIncrement();
		String pkg = null;
		ClassGenerator ccp = null, ccm = null;
		try
		{
			ccp = ClassGenerator.newInstance(cl);

			// impl constructor
			StringBuilder code = new StringBuilder();
			for(int i=0;i<dcs.length;i++)
			{
				if( !Modifier.isPublic(dcs[i].getModifiers()) )
				{
					String npkg = dcs[i].getPackage().getName();
					if( pkg == null )
					{
						pkg = npkg;
					}
					else
					{
						if( !pkg.equals(npkg)  )
							throw new IllegalArgumentException("non-public interfaces class from different packages");
					}
				}

				ccp.addField("private " + dcs[i].getName() + " d" + i + ";");

				code.append("d").append(i).append(" = (").append(dcs[i].getName()).append(")$1[").append(i).append("];\n");
				if( MixinAware.class.isAssignableFrom(dcs[i]) )
					code.append("d").append(i).append(".setMixinInstance(this);\n");
			}
			ccp.addConstructor(Modifier.PUBLIC, new Class<?>[]{ Object[].class }, code.toString());

			// impl methods.
			Set<String> worked = new HashSet<String>();
			for(int i=0;i<ics.length;i++)
			{
				if( !Modifier.isPublic(ics[i].getModifiers()) )
				{
					String npkg = ics[i].getPackage().getName();
					if( pkg == null )
					{
						pkg = npkg;
					}
					else
					{
						if( !pkg.equals(npkg)  )
							throw new IllegalArgumentException("non-public delegate class from different packages");
					}
				}

				ccp.addInterface(ics[i]);

				for( Method method : ics[i].getMethods() )
				{
					if( "java.lang.Object".equals(method.getDeclaringClass().getName()) )
						continue;

					String desc = ReflectUtils.getDesc(method);
					if( worked.contains(desc) )
						continue;
					worked.add(desc);

					int ix = findMethod(dcs, desc);
					if( ix < 0 )
						throw new RuntimeException("Missing method [" + desc + "] implement.");

					Class<?> rt = method.getReturnType();
					String mn = method.getName();
					if( Void.TYPE.equals(rt) )
						ccp.addMethod(mn, method.getModifiers(), rt, method.getParameterTypes(), method.getExceptionTypes(),
								"d" + ix + "." + mn + "($$);");
					else
						ccp.addMethod(mn, method.getModifiers(), rt, method.getParameterTypes(), method.getExceptionTypes(),
								"return ($r)d" + ix + "." + mn + "($$);");
				}
			}

			if( pkg == null )
				pkg = PACKAGE_NAME;

			// create MixinInstance class.
			String micn = pkg + ".mixin" + id;
			ccp.setClassName(micn);
			ccp.toClass();

			// create Mixin class.
			String fcn = Mixin.class.getName() + id;
			ccm = ClassGenerator.newInstance(cl);
			ccm.setClassName(fcn);
			ccm.addDefaultConstructor();
			ccm.setSuperClass(Mixin.class.getName());
			ccm.addMethod("public Object newInstance(Object[] delegates){ return new " + micn + "($1); }");
			Class<?> mixin = ccm.toClass();
			return (Mixin)mixin.newInstance();
		}
		catch(RuntimeException e)
		{
			throw e;
		}
		catch(Exception e)
		{
			throw new RuntimeException(e.getMessage(), e);
		}
		finally
		{
			// release ClassGenerator
			if( ccp != null )
				ccp.release();
			if( ccm != null )
				ccm.release();
		}
	}

	/**
	 * new Mixin instance.
	 * 
	 * @param ds delegates instance.
	 * @return instance.
	 */
	abstract public Object newInstance(Object[] ds);

	protected Mixin(){}

	private static int findMethod(Class<?>[] dcs, String desc)
	{
		Class<?> cl;
		Method[] methods;
		for(int i=0;i<dcs.length;i++)
		{
			cl = dcs[i];
			methods = cl.getMethods();
			for( Method method : methods )
			{
				if( desc.equals(ReflectUtils.getDesc(method)) )
					return i;
			}
		}
		return -1;
	}

	private static void assertInterfaceArray(Class<?>[] ics)
	{
		for(int i=0;i<ics.length;i++)
			if( !ics[i].isInterface() )
				throw new RuntimeException("Class " + ics[i].getName() + " is not a interface.");
	}
}