package visual.statik.sampled;

import java.awt.*;
import java.awt.event.*;
import java.awt.color.*;
import java.awt.geom.*;
import java.awt.image.*;
import java.io.*;
import java.util.*;
import javax.imageio.*;
import javax.swing.*;

import app.*;
import io.*;


/**
 * An example that illustrates the rotation of
 * sampled static visual content
 *
 * @author  Prof. David Bernstein, James Madison University
 * @version 1.0
 */
public class      RotationApp
       extends    AbstractMultimediaApp
       implements ActionListener
{

    private BeforeAndAfterCanvas                 canvas;       
    private BufferedImage                        after, before;    
    private IdentityOp                           identityOp;
    private Image                                original;    
    private ImageFactory                         imageFactory;       
    private JTextField                           angleField;    

    private static final Font DEFAULT_FONT = 
                              new Font("Sans Serif", Font.PLAIN, 11);


    /**
     * Default Constructor
     *
     */
    public RotationApp()
    {
       super();    
       imageFactory    = new ImageFactory();
       this.identityOp = new IdentityOp();
    }


    /**
     * Handle actionPerformed messages
     * (required by ActionListener)
     *
     * @param evt   The ActionEvent that generated the message
     */
    public void actionPerformed(ActionEvent evt)
    {
       BufferedImageOp        op;
       double                 theta;       
       String                 command, text;
       
       theta   = 0.0;       
       command = evt.getActionCommand();       

       if (command.startsWith("Reset"))
       {
          reset();
          canvas.setBeforeImage(before);       
          canvas.setAfterImage(after);             
       }
       else if (command.startsWith("Rotate"))
       {
          before = after;
          canvas.setBeforeImage(before);
          text = angleField.getText();          
          if (text != null) 
          {
             try
             {
                theta = Double.parseDouble(text);
             }
             catch (NumberFormatException nfe)
             {
                theta = 0.0;                
             }
          }
          after = rotate(theta, before);             
          canvas.setAfterImage(after);             
       }
    }


    /**
     * Add a JButton
     *
     * @param p     The JPanel to add it to
     * @param text  The text of the JButton
     * @param x     The x-position
     * @param y     The y-position
     * @param width The width
     */
    private void addButton(JPanel p, String text, 
                           int x, int y, int width)
    {
       JButton      button;
       
       button = new JButton(text);
       button.addActionListener(this);       
       button.setBounds(x, y, width, 30);
       button.setFont(DEFAULT_FONT);       
       p.add(button);       
    }


    /**
     * This method is called just before the main window
     * is first made visible
     */
    public void init()
    {
       Dimension                 size;       
       InputStream               is;       
       int                       x, y;       
       JPanel                    contentPane;       
       ResourceFinder            finder;
       String                    name;
       
       

       // Read the image
       original  = null;       
       finder    = ResourceFinder.createInstance();          
       name      = rootPaneContainer.getParameter("0");
       if (name == null) name = "/visual/statik/sampled/car.gif";

       try
       {
          is = finder.findInputStream(name);
          if (is != null)
          {
             original = ImageIO.read(is);
             is.close();
          }
          reset();          
       }
       catch (IOException io)
       {
          // original will be null
       }

       // Create the component that will render the image
       canvas = new BeforeAndAfterCanvas();
       canvas.setBeforeImage(before);
       canvas.setAfterImage(after);       
       size   = canvas.getSize();       
       canvas.setBounds(0,0,(int)size.getWidth(),(int)size.getHeight());

       // Add the ImageCanvas to the main window
       contentPane = (JPanel)rootPaneContainer.getContentPane();
       contentPane.add(canvas);

       // Add the buttons to the content pane
       y = (int)size.getHeight() + 10;       
       angleField = new JTextField();
       angleField.setBounds(                  0, y, 80, 30);       
       contentPane.add(angleField);       
       addButton(contentPane, "Rotate",      80, y, 75);

       addButton(contentPane, "Reset",      160, y, 75);       
    }


    /**
     * Reset both the before and after image to
     * the original
     */
    private void reset()
    {
       before       = imageFactory.createBufferedImage(original);          
       after        = before;          
    }
    


    /**
     * Rotate an image
     *
     * @param command    The command
     * @param before     The image to rotate
     */
    private BufferedImage rotate(double        theta,
                                 BufferedImage before)
    {
        //[rotate1.

        AffineTransform   rotate;

	rotate = AffineTransform.getRotateInstance(
                                    theta, 
                                    before.getWidth() /2.0,
                                    before.getHeight()/2.0);
        //]rotate1.
        //[rotate2.

	RenderingHints           hints;

	// Value can be BILINEAR or NEAREST_NEIGHBOR
	hints = new RenderingHints(
                  RenderingHints.KEY_INTERPOLATION,
                  RenderingHints.VALUE_INTERPOLATION_BILINEAR
	                          );
        //]rotate2.
        //[rotate3.

	AffineTransformOp        op;

	op = new AffineTransformOp(rotate, hints);
        //]rotate3.
        //[rotate4.

	BufferedImage            after;

	after = op.filter(before, null);
        //]rotate4.

       return after;
    }


}

