package org.arefgard.container.aop;

import java.lang.reflect.Method;
import java.util.List;

public class MethodStructure {

	private String methodName;
	private String returnType;
	private List<String> paramType = new java.util.ArrayList<String>();
	private Method method;
	
	public MethodStructure(String returnType, String methodName) {
		this.returnType = returnType;
		this.methodName = methodName;
	}

	public String getMethodName() {
		return methodName;
	}

	public void setMethodName(String methodName) {
		this.methodName = methodName;
	}

	public String getReturnType() {
		return returnType;
	}

	public void setReturnType(String returnType) {
		this.returnType = returnType;
	}

	public void addParameterType(String name) {
		this.paramType.add(name);	
	}
	
	public String getParameterType(int index) {
		return this.paramType.get(index);
	}
	
	public int length() {
		return this.paramType.size();
	}

	public Method getMethod() {
		return method;
	}

	public void setMethod(Method method) {
		this.method = method;
	}
	
	public static MethodStructure[] parse(Class cls) {
		Class superCls = cls.getSuperclass();
		Method[] methods = cls.getDeclaredMethods();
		Method[] superMethods = superCls.getMethods();
		MethodStructure[] structure = new MethodStructure[methods.length+superMethods.length];
		int size = methods.length;
		for(int i = 0; i < size; i++) {
			methods[i].setAccessible(true);
			String returnType = methods[i].getReturnType().getName();
			String methodName = methods[i].getName();
			MethodStructure method = new MethodStructure(returnType, methodName);
			Class[] paramClass = methods[i].getParameterTypes();
			int paramSize = paramClass.length;
			for(int j = 0; j < paramSize; j++) {
				method.addParameterType(getType(paramClass[j].getName()));
			}
			method.setMethod(methods[i]);
			structure[i] = method;
		}
		
		// 親の公開されているメソッドも取得する
		int superSize = superMethods.length;
		for(int i = 0; i < superSize; i++) {
			superMethods[i].setAccessible(true);
			String returnType = superMethods[i].getReturnType().getName();
			String methodName = superMethods[i].getName();
			MethodStructure method = new MethodStructure(returnType, methodName);
			Class[] paramClass = superMethods[i].getParameterTypes();
			int paramSize = paramClass.length;
			for(int j = 0; j < paramSize; j++) {
				method.addParameterType(getType(paramClass[j].getName()));
			}
			method.setMethod(superMethods[i]);
			structure[i+size] = method;
		}
		return structure;
	}
	
	private static String getType(String typeName) {
		if(typeName == null || typeName.equals("")) {
			return null;
		}
		if(typeName.equals("boolean")) {
			return "java.lang.Boolean";
		}else if(typeName.equals("byte")) {
			return "java.lang.Byte";
		}else if(typeName.equals("char")) {
			return "java.lang.Character";
		}else if(typeName.equals("double")) {
			return "java.lang.Double";
		}else if(typeName.equals("float")) {
			return "java.lang.Float";
		}else if(typeName.equals("int")) {
			return "java.lang.Integer";
		}else if(typeName.equals("long")) {
			return "java.lang.Long";
		}else if(typeName.equals("short")) {
			return "java.lang.Short";
		}else if(typeName.equals("void")) {
			return "java.lang.Void";
		}else {
			return typeName;
		}
	}
}
