/*********
 * Short summery: takes two drawings and morph the first into the other.
 *  This code create a window where the user can drawa simple shape by choosing points
 *  in the window, then once he finish he hit "done drawing the first shape" the user
 *  is suppose to draw another shape that contant the same number of point, once
 *  he finish, he hit animate and he can see the first drawing move to fit into the
 *  shape of the sencond drawing
 *  Written by : Maan Ashgar
 *********/



import java.awt.*;
import java.awt.image.*;
import java.awt.event.*;
import javax.swing.*;
import java.io.*;
import java.lang.Thread;
import javax.swing.*;
import java.awt.Toolkit;




public class morph extends JFrame
{
 //the points holder array
 Point[] clicked_points;
 
 //point number
 int point_num;
 int sec_image_point_num;
 
 //the graphics context
 Graphics gx ;
 
 //the contorl panel on the screen
 Panel control = new Panel();
 
 //boolean switchs
 boolean first_image_done = false;
 boolean second_image_point_jump = false; 
 boolean clicking_started = false;
 boolean second_image_done = false ; 
 
 //buttons
 Button clear_button = new Button("Clear");
 Button nextimage_button = new Button("Done Drawing First Image");
 
 
 
 //create the interface
 public morph()
 {
  setupInterface();
  clicked_points = new Point[100];
  point_num = 0 ; 
 }
 
 //the main method 
 public static void main(String[] args) 
 {
  new morph();
 }
 
 public void setupInterface()
    {
     setSize( 620, 500 );
     
     getContentPane().setLayout( new BorderLayout());
     
     //add button
     control.add(clear_button);
     control.add(nextimage_button);
     getContentPane().add(control,BorderLayout.SOUTH);

     //mouse action listener
        addMouseListener( new mouseListener() );
        show();          
        gx = getContentPane().getGraphics();
    }
    
    //mouse clicks handler 
    private class mouseListener extends MouseAdapter
    {
        public void mouseClicked(MouseEvent e)
        {
         if(!second_image_done)
         { 
          clicked_points[point_num]=new Point(e.getX(),e.getY());
          clicking_started = true;
          System.out.println(clicked_points[point_num]+" "+point_num); //remove later
          repaint();
          point_num++;
         }
        }
    }
    
    //button actions handling
    public boolean action(Event e, Object o)
    {
     if (e.target == clear_button)
     { 
    clearScreen();
    return true;   
   }
   
   if (e.target == nextimage_button)
     { 
    if(!first_image_done)
    {
     clearScreen();
     //save the number of points clicked in first image
     sec_image_point_num = point_num;
     first_image_done = true;
     nextimage_button.setLabel("Animate");
     nextimage_button.setEnabled(false);
    }
   
    if( nextimage_button.isEnabled() && second_image_done)
    {
     animate(gx, clicked_points, point_num);
    } 
    return true;  
   }
   
   
   return true;
    }
    
    
    //the painting method
    public  void paint(Graphics g)
    { 

     int num_holder = point_num-1;
     if ((clicking_started) && !(second_image_done))
     {
      g.fillOval((int)clicked_points[num_holder].getX(), (int)clicked_points[num_holder].getY(), 2, 2);
     }
     if(!first_image_done)
     {
      if (num_holder >= 1)
      {
       //draw the lines
       g.drawLine((int)clicked_points[num_holder-1].getX(),(int)clicked_points[num_holder-1].getY(),(int)clicked_points[num_holder].getX(),(int)clicked_points[num_holder].getY());
      }
     }
     else if(first_image_done && (point_num <= sec_image_point_num*2 ))
     {
      if (second_image_point_jump)
      {
       //draw the lines
       g.drawLine((int)clicked_points[num_holder-1].getX(),(int)clicked_points[num_holder-1].getY(),(int)clicked_points[num_holder].getX(),(int)clicked_points[num_holder].getY());
       if (point_num == (sec_image_point_num*2))
       {
        nextimage_button.setEnabled(true);
        second_image_done = true;
       }
      }
      second_image_point_jump = true;
     }
     
    }
    
    public  void clearScreen()
    {
   gx.clearRect(0,0,500,500);
    }
    
    public void animate(Graphics g2, Point[] cp, int pnum )
    {

     int sec_shape = (pnum+1)/2 ;
     boolean not_done = true;
     Point[] draw_points = new Point[sec_shape];
     int loop_count = 0 ;
     Point current_point;
     int x = 0;
     int y = 0;
     int eraser = 0;
     //drawing to the end of the animation
     while(not_done)
     {
      loop_count = 0 ;
      //calculate the points at each drawing
      while (loop_count < sec_shape)
      {
       x = 0;
       y = 0;
              System.out.println("test 1 x: "+ x +" y: "+y);
       //assign the point of the first drawing to the cuurent_pint
       current_point = new Point(0,0);
       //check the distance from the current point to the second drawing point
       if(cp[loop_count] != cp[loop_count+sec_shape])
       {

     if(cp[loop_count].getX() == cp[loop_count+sec_shape].getX())
     { 
         x = (int)cp[loop_count].getX();
     } 
      
        else
        {
         if(cp[loop_count].getX() > cp[loop_count+sec_shape].getX())
          x = ((int)cp[loop_count].getX())-1;
        
         if(cp[loop_count].getX() < cp[loop_count+sec_shape].getX()) 
          x = ((int)cp[loop_count].getX())+1;
        } 
         
        if(cp[loop_count].getY() == cp[loop_count+sec_shape].getY())
        {
         y = (int)cp[loop_count].getY();
        } 

        else
        {
         if(cp[loop_count].getY() > cp[loop_count+sec_shape].getY())
          y = ((int)cp[loop_count].getY())-1;
         if(cp[loop_count].getY() < cp[loop_count+sec_shape].getY()) 
          y = ((int)cp[loop_count].getY())+1;
        }

       }

      // System.out.println(x+""+y);
       current_point.setLocation( x, y) ; // = new Point(((int)cp[loop_count].getX())+x,(int) cp[loop_count].getY()+y);
       draw_points[loop_count] = current_point ;
       cp[loop_count] = current_point ;
       System.out.println(current_point+" "+loop_count);

       loop_count++;
      }//coming out of this you get draw_points[] full, now draw it
      
      loop_count = 1 ;
      
      while (loop_count < sec_shape)
      {
       if(eraser == sec_shape-1)
       {
        clearScreen();
        eraser = 0;
       }
       g2.drawLine((int)draw_points[loop_count-1].getX(),(int)draw_points[loop_count-1].getY(),(int)draw_points[loop_count].getX(),(int)draw_points[loop_count].getY());
       loop_count++;
       eraser++;
       
      }
      loop_count = 0 ;
     not_done = false;
      while (loop_count < sec_shape)
      {
       if ((draw_points[loop_count].getX() != cp[loop_count+sec_shape].getX()) || (draw_points[loop_count].getY() != cp[loop_count+sec_shape].getY()))
        not_done = true ;
       loop_count++; 
      }
      
      
      try
    { 
                 Thread.sleep(50);  
                }
                catch (InterruptedException e)
                { 
                    System.out.println("interrupted"); 
                } 
      
     }
     
     
     
     
    }
  
}