package lectures.animation.threads_commands;
import util.annotations.WebDocuments;

import lectures.animation.threads_commands.extra.SingleShuttleAnimation;
import lectures.composite.objects_shapes.PlottedShuttle;
import lectures.mvc.properties.AnObservablePlottedShuttle;
import bus.uigen.OEFrame;
import bus.uigen.ObjectEditor;
/*
 * You see the nature of threads in three stages.
 * First, you see visually, in animating user-interfaces,
 * the consequence of having multiple threads.
 * 
 * Second,  you see threads more directly, through console prints and 
 * the debugger, the existence of threads.
 * 
 * Finally, you see them most closely, through new kinds of object that 
 * result in the threads being created.
 * 
 * Study the code in this class, and follow the instructions at the end.
 */

@WebDocuments({"Lectures/AnimationThreadsCommands.pptx", "Lectures/AnimationThreadsCommands.pdf", "Videos/AnimationThreadsCommands.avi"})
public class ConcurrentShuttleLaunchAnimation extends SingleShuttleAnimation  {
    static int threadNumber = 0;
    protected final static String SHUTTLE_THREAD_NAME = "Shuttle Animation";
    protected final static int START_FRAME_X = 50;
    protected final static int START_FRAME_Y = 50;
    protected final static int SHUTTLE2_X = 100;
    protected final static int SHUTTLE2_Y = 50;
    
    protected static int shuttleNumber = 0;
    protected static PlottedShuttle shuttle1;
    protected static PlottedShuttle shuttle2;
    protected  static ShuttleAnimator shuttleAnimator1;
    protected static ShuttleAnimator shuttleAnimator2;
    
    protected static void printAllThreads() {
        System.out.println ("Current threads:" + Thread.getAllStackTraces().keySet());
    }
    
    public static void concurrentDemoShuttleAnimation(ShuttleAnimator aShuttleAnimator, PlottedShuttle aShuttle) {
        
        /* Comment this out and uncomment the following line when asked */
        Thread aThread = new Thread(
            new AShuttleAnimationCommand(
                    aShuttleAnimator, aShuttle, 
                    ANIMATION_STEP, 
                    ANIMATION_PAUSE_TIME));
        
//      Thread thread = new Thread();
        
        threadNumber++;
        aThread.setName(SHUTTLE_THREAD_NAME + " " + threadNumber);
        
        /*
         * Comment this out when asked:
         */
        aThread.start();
        System.out.println ("Thread:" + Thread.currentThread() + " has started " + aThread);
    }
    
    public static void serialShuttleAnimation() {
        serialShuttleAnimation(shuttleAnimator1, shuttle1);
        serialShuttleAnimation(shuttleAnimator2, shuttle2);
    }
    public static void concurrentShuttleAnimation() {
        concurrentDemoShuttleAnimation(shuttleAnimator1, shuttle1);
        concurrentDemoShuttleAnimation(shuttleAnimator2, shuttle2);
    }

    public static void main(String[] args) {
        shuttle1 = new AnObservablePlottedShuttle(SHUTTLE1_X, SHUTTLE1_Y);
        shuttle2 = new AnObservablePlottedShuttle(SHUTTLE2_X, SHUTTLE2_Y);
        displayShuttleFrame(shuttle1);
        displayShuttleFrame(shuttle2);
        shuttleAnimator1 = new AShuttleAnimator();
        shuttleAnimator2 = new AShuttleAnimator();  
        
        // you will need to switch between the two calls
        serialShuttleAnimation();       
//      concurrentShuttleAnimation();
        
        System.out.println ("Main terminates");

    }
/*
 * SERIAL VS CONCURRENT ANIMATIONS
 * 
 * Run the program and observe the animations in the object editor user interfaces.
 * 
 * Now uncomment the call to concurrentShuttleAnimation in main and comment out the
 * call to serialShuttleAnimation.
 * 
 * Observe the animations again.
 * 
 * (T/F) serialShuttleAnimation starts animating shuttle2 after finishing animating
 * shuttle1.
 * 
 * (T/F) serialShuttleAnimation ensures that the two shuttles do not climb up at the same
 * time. 
 * 
 * (T/F) concurrentShuttleAnimation starts animating shuttle2 after finishing 
 * animating shuttle1. 
 * 
 * (T/F) concurrentShuttleAnimation ensures that the two shuttles do not climb up at the same
 * time.
 * 
 */
/*
 * THREAD OBJECTS
 * 
 * We will go through the same process again, but this time look at the console
 * output in addition to the OE display.
 * 
 * The idea is to understand the nature of Thread objects, where Thread is
 * a predefined Java class.
 * 
 * The program displays these objects using strings of the form:
 * Thread[<Thread Name>} 
 * where <Thread Name> is a name given to the Thread object. 
 * 
 * In this program, we give each Thread object a different name.
 * 
 * 
 * Run main again and observe console output and see how many different Thread 
 * objects are printed out.
 * 
 * Switch back to serialShuttleAnimation and run main again and observe console
 * output and see how many different Thread objects are printed out.
 * 
 * When serialShuttleAnimation runs, the number of thread objects printed is:
 *    0
 *    1
 *    2
 *    3
 * When concurrentShuttleAnimation runs, the number of thread objects printed is:
 *    0
 *    1
 *    2
 *    3 
 * 
 * To get further under the hood, let us try and understand where these objects
 * are being printed.
 * 
 * Go to the AShuttleAnimator class and answer the questions there. You will need to
 * switch between serial and concurrent execution in this class.
 */
    
/*
 * COMMAND OBJECTS
 * 
 * You saw in AShuttleAnimator something about the behavior of running threads.
 * Let us try to understand how threads are started.
 * 
 * We saw that each runnable thread is associated with a Thread object. 
 * We also saw that other than the main thread, all threads have Thread.run()
 * at the base of the stack.
 * If different threads do different things, then somehow different Thread.run() calls
 * should call different methods.
 * 
 * Thread.run() does not take parameters. So, this means that when a Thread object is
 * constructed, we must tell the constructor which method to call and what the parameters
 * of the method should be.
 * 
 * These two pieces of information are encapsulated in a command object, which
 * is passed to the thread constructor.
 * 
 * concurrentDemoShuttleAnimation shows the use of Thread objects.
 * 
 * It creates a thread and then starts it.
 * 
 * Look at the output produced by it.
 * 
 * Thread[Shuttle Animation 2] is started by:
 *   (a) Thread[Shuttle Animation 1]
 *   (b) Thread[main]
 * 
 * 
 * Comment out Thread.start(), switch to concurrent animation, and observe what
 * happens.
 * 
 * (T/F) If a thread is not started, then its run method is not called.
 * 
 * Uncomment Thread.start() and switch to the alternate commented out Thread 
 * instantiation and observe what happens.
 * 
 * (T/F) If the command object is not passed to the Thread constructor, then
 * the animation does not start.
 * 
 *  Go to AShuttleAnimationCommand
 */
    
    
/*
 * THREAD AND ANIMATION DESIGN PATTERN
 * We see here a design pattern for using threads to animate objects that has
 * the following components:
 * 
 * Animated object - the object being animated. In this case it is an instance of
 * AnObservablePlottedShuttle.
 * 
 * The animating object -  the object implementing the animation. In this case,
 * it is an instance of AShuttleAnimator.
 * 
 * Command object - this object wraps a call to the animating object so that it
 * can be placed inside a separate thread. The command object is what starts the
 * animation (here, it is AShuttleAnimationCommand).
 * 
 * Thread object - this object takes a command object and allows the animation to
 * proceed in a separate, concurrent thread. This is the Java Thread object.
 * 
 * 
 * Based on this design pattern answer the following questions:
 * 
 * (T/F) The class of the animated object must be changed to change the animation.
 * 
 * (T/F) A Thread object knows how an object is animated.
 * 
 * (T/F) A Thread object interacts with a command object directly.  
 * 
 * (T/F) A Thread object interacts with an animating object directly.
 * 
 * (T/F) A command object interacts with an animated object directly.
 * 
 * (T/F) A command object interacts with an animating object directly.
 * 
 * (T/F) The class of a command object is a subclass of the Thread class.
 * 
 * (T/F) It is possible to create two different threads and command objects that
 * animate the same object simultaneously. 
 * (You do not see the answer directly in the praxis so have to deduce it from what you have learned)
 * 
 * (T/F) A command object can be used only to start threads. 
 * (You do not see the answer directly in the praxis so have to deduce it from what you have learned)
 */
}