/*
 * Licensed to the Apache Software Foundation (ASF) under one
 * or more contributor license agreements.  See the NOTICE file
 * distributed with this work for additional information
 * regarding copyright ownership.  The ASF licenses this file
 * to you 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 org.apache.felix.ipojo.util;

import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;

import org.apache.felix.ipojo.InstanceManager;
import org.apache.felix.ipojo.parser.FieldMetadata;
import org.apache.felix.ipojo.parser.MethodMetadata;

/**
 * A callback allows invoking a method on a POJO.
 * This class supports both public, protected and private methods of the
 * implementation class. This class also supports public method from super class.
 * The {@link Method} object is computed once and this computation is delayed
 * to the first invocation.
 * @author <a href="mailto:dev@felix.apache.org">Felix Project Team</a>
 */
public class Callback {

    /**
     * The method object.
     * Computed at the first call.
     */
    protected Method m_methodObj;

    /**
     * The name of the method to call.
     */
    private String m_method;

    /**
     * Is the method a static method ?
     * This implies calling the method on <code>null</code>
     */
    private boolean m_isStatic;

    /**
     * The reference on the instance manager.
     * Used to get POJO objects.
     */
    private InstanceManager m_manager;

    /**
     * The argument classes.
     * This array contains the list of argument class names.
     */
    private String[] m_args;

    /**
     * Creates a Callback.
     * If the argument array is not null the reflection type are computed.
     * @see Callback#computeArguments(String[])
     * @param method the name of the method to call
     * @param args the argument type name, or <code>null</code> if no arguments
     * @param isStatic is the method a static method
     * @param manager the instance manager of the component containing the method
     */
    public Callback(String method, String[] args, boolean isStatic, InstanceManager manager) {
        m_method = method;
        m_isStatic = isStatic;
        m_manager = manager;
        if (args != null) {
            computeArguments(args);
        } else {
        	m_args = new String[0];
        }
    }

    /**
     * Creates a Callback.
     * @param method the the name of the method to call
     * @param args the argument classes
     * @param isStatic the is the method a static method
     * @param manager the the instance manager of the component containing the method
     */
    public Callback(String method, Class[] args, boolean isStatic, InstanceManager manager) {
        m_method = method;
        m_isStatic = isStatic;
        m_manager = manager;
        m_args = new String[args.length];
        for (int i = 0; i < args.length; i++) {
            m_args[i] = args[i].getName();
        }
    }

    /**
     * Creates a Callback.
     * @param method the {@link MethodMetadata} obtained from manipulation
     * metadata ({@link org.apache.felix.ipojo.parser.PojoMetadata}).
     * @param manager the instance manager.
     */
    public Callback(MethodMetadata method, InstanceManager manager) {
        m_isStatic = false;
        m_method = method.getMethodName();
        m_manager = manager;
        computeArguments(method.getMethodArguments());
    }

    /**
     * Computes arguments of the method.
     * This method computes "reflection type" from given argument.
     * @see FieldMetadata#getReflectionType(String)
     * @param args the arguments of the method.
     */
    private void computeArguments(String[] args) {
        m_args = new String[args.length];
        for (int i = 0; i < args.length; i++) {
            m_args[i] = FieldMetadata.getReflectionType(args[i]);
        }
    }

    /**
     * Searches the {@link Method} in the given method arrays.
     * @param methods the method array in which the method should be found
     * @return the method object or <code>null</code> if not found
     */
    private Method searchMethodInMethodArray(Method[] methods) {
        for (int i = 0; i < methods.length; i++) {
            // First check the method name
            if (methods[i].getName().equals(m_method)) {
                // Check arguments
                Class[] clazzes = methods[i].getParameterTypes();
                if (clazzes.length == m_args.length) { // Test size to avoid useless loop
                    int argIndex = 0;
                    for (; argIndex < m_args.length; argIndex++) {
                        if (!m_args[argIndex].equals(clazzes[argIndex].getName())) {
                            break;
                        }
                    }
                    if (argIndex == m_args.length) { // No mismatch detected.
                        return methods[i]; // It is the looked method.
                    }
                }
            }
        }
        return null;
    }

    /**
     * Searches the {@link Method} object in the POJO by analyzing implementation
     * class methods. The name of the method and the argument type are checked.
     * @throws NoSuchMethodException if the method cannot be found either in the
     * implementation class or in parent classes.
     */
    protected void searchMethod() throws NoSuchMethodException {
        Method[] methods = m_manager.getClazz().getDeclaredMethods();
        m_methodObj = searchMethodInMethodArray(methods);

        if (m_methodObj == null) { // look at parent classes
            methods = m_manager.getClazz().getMethods();
            m_methodObj = searchMethodInMethodArray(methods);
        }

        if (m_methodObj == null) {
            throw new NoSuchMethodException(m_method);
        } else {
            if (! m_methodObj.isAccessible()) {
                // If not accessible, try to set the accessibility.
                m_methodObj.setAccessible(true);
            }
        }
    }

    /**
     * Invokes the method without arguments.
     * If several the instance contains several objects, the method is invoked
     * on every objects.
     * @return the result of the invocation, <code>null</code> for <code>void</code>
     * method, the last result for multi-object instance
     * @throws NoSuchMethodException if Method is not found in the class
     * @throws InvocationTargetException if the method throws an exception
     * @throws IllegalAccessException if the method can not be invoked
     */
    public Object call() throws NoSuchMethodException, IllegalAccessException, InvocationTargetException {
        return call(new Object[0]);
    }

    /**
     * Invokes the method without arguments.
     * The method is invokes on the specified object.
     * @param instance the instance on which call the callback
     * @return the result of the invocation, <code>null</code> for
     * <code>void</code> method
     * @throws NoSuchMethodException if the method was not found
     * @throws IllegalAccessException if the method cannot be called
     * @throws InvocationTargetException if an error happens in the method
     */
    public Object call(Object instance) throws NoSuchMethodException, IllegalAccessException, InvocationTargetException {
        return call(instance, new Object[0]);
    }

    /**
     * Invokes the method on every created objects with the specified
     * arguments.
     * @param arg the method arguments
     * @return the result of the invocation, <code>null</code> for
     * <code>void</code> method, the last result for instance containing
     * several objects.
     * @throws NoSuchMethodException if the callback method is not found
     * @throws IllegalAccessException if the callback method cannot be called
     * @throws InvocationTargetException if an error is thrown by the called method
     */
    public Object call(Object[] arg) throws NoSuchMethodException, IllegalAccessException, InvocationTargetException {
        if (m_methodObj == null) {
            searchMethod();
        }

        if (m_isStatic) {
            return m_methodObj.invoke(null, arg);
        } else {
            // Two cases :
            // - if instances already exists : call on each instances
            // - if no instance exists : create an instance
            if (m_manager.getPojoObjects() == null) {
                return  m_methodObj.invoke(m_manager.getPojoObject(), arg);
            } else {
                Object newObject = null;
                for (int i = 0; i < m_manager.getPojoObjects().length; i++) {
                    newObject = m_methodObj.invoke(m_manager.getPojoObjects()[i], arg);
                }
                return newObject;
            }
        }
    }

    /**
     * Invokes the method on the given object with the specified
     * arguments.
     * @param instance the instance on which call the method
     * @param arg the argument array
     * @return the result of the invocation, <code>null</code> for
     * <code>void</code> method
     * @throws NoSuchMethodException if the callback method is not found
     * @throws IllegalAccessException if the callback method cannot be called
     * @throws InvocationTargetException if an error is thrown by the called method
     */
    public Object call(Object instance, Object[] arg) throws NoSuchMethodException, IllegalAccessException, InvocationTargetException {
        if (m_methodObj == null) {
            searchMethod();
        }

        return m_methodObj.invoke(instance, arg);
    }

    /**
     * Gets the method name.
     * @return the method name
     */
    public String getMethod() {
        return m_method;
    }

    /**
     * Gets the method arguments.
     * @return the arguments.
     */
    public String[] getArguments() {
    	return m_args;
    }
}
