import java.lang.reflect.*;
import java.util.*;
import java.text.*;

/** Invokes a given method on a given object at a given
 *  interval. Uses Reflection API.
 */
public class TimedMethodInvoker implements Runnable, UsefulConstants {

    public static final int ONE_HOUR          = 1000*60*60*1;
    public static final int TWO_HOURS         = 1000*60*60*2;
    public static final int THREE_HOURS       = 1000*60*60*3;
    public static final int FOUR_HOURS        = 1000*60*60*4;
    public static final int FIVE_HOURS        = 1000*60*60*5;
    public static final int SIX_HOURS         = 1000*60*60*6;
    public static final int SEVEN_HOURS       = 1000*60*60*7;
    public static final int EIGHT_HOURS       = 1000*60*60*8;
    public static final int NINE_HOURS        = 1000*60*60*9;
    public static final int TEN_HOURS         = 1000*60*60*10;
    public static final int ELEVEN_HOURS      = 1000*60*60*11;
    public static final int TWELVE_HOURS      = 1000*60*60*12;
    public static final int TWENTY_FOUR_HOURS = 1000*60*60*24;


    private Object o;
    private Method myMethod;
    private Object[] args;
    private int sleep;


    /** Constructor
     *  @param i_o the Object containing the Method to be invoked
     *  @param methodName the name of the Method to be invoked
     *  @param parms an ArrayList of Class Objects representing the parameter
     *               signature of the Method to be invoked
     *  @param i_args an Array of Objects representing the arguments to pass
     *                to the method when invoked
     *  @param i_sleep an integer representing the time delay between method invocations
     */
    public TimedMethodInvoker(Object i_o, String methodName, ArrayList parms, Object[] i_args, int i_sleep)
        throws NoSuchMethodException
    {

        // Initialize the member variables
        o = i_o;
        myMethod = o.getClass().getMethod(methodName, (Class[])parms.toArray(new Class[0]));
        args = i_args;
        sleep = i_sleep;

    }


    public void run() {

        while ( true ) {

            try {

                // Call the supplied method
                Object obj = myMethod.invoke(o, args);

                // Keep a log of all invocations
                Date now = new Date();
                SimpleDateFormat sdf = new SimpleDateFormat("MM.dd.yyyy HH:mm:ss");
                System.err.println(sdf.format(now) + ": TimedMethodInvoker called on " +
                                   myMethod.toString());

                // sleep for the specified duration
                Thread t = Thread.currentThread();
                t.sleep(sleep);
            }
            catch ( InterruptedException ie ) {
                System.err.println("InterruptedException caught in TimedMethodInvoker: " + ie.getMessage());
                return;
            }
            catch ( Throwable t ) {
                System.err.println("Throwable caught in TimedMethodInvoker");
                t.printStackTrace();
                return;
            }
        }
    }

}
