/**
 * Starting Point Code for Image Processing Project
 * @author Richard Wicentowski and Tia Newhall (2005)
 * Modified by Kuzman Ganchev and Fernando Pereira
 */

import java.io.*;
import java.awt.*;
import java.awt.image.*;
import java.awt.event.*;
import javax.swing.*;

public class ImageBase {
  
  private JFrame menuFrame;
  private PictureFrame pictureFrame;
  private SimpleButton[] buttons;
  private JLabel photo;
  private Picture picture;
  private int counter = 0;
  private boolean closing = false;
 
  private boolean hasGui;
  /** create an ImageBase instance with gui only if the argument is
   * true.
   * @param filename the name of the file containing the initial image
   * @param makeGui whether to create a gui
   */
  public ImageBase(String filename, boolean makeGui) {
    hasGui = makeGui;
    if (makeGui) {
      setupMenuFrame();
      setupImageFrame(filename);
      addButton(new RestoreImage(this));
    } else {
      /* Read a color picture from a file and create an empty list of
       * buttons. */
      picture = new Picture(filename);
      buttons = new SimpleButton[0];
    }
  }

  public boolean pressButton(int button){
    if (buttons.length <= button) return false;
    buttons[button].actionPerformed(null);
    return true;
  }


  /** create an ImageBase instance, reading the image from the file
   * with the given name. 
   * @param filename the name of the file containing the initial
   * image. */
  ImageBase(String filename) {
    this(filename, true);
  }
  private void shutdown() {
    if (!closing) {
      closing = true;
      if (menuFrame != null) {
        menuFrame.dispose();
        menuFrame = null;
      }
      if (pictureFrame != null) {
        pictureFrame.dispose();
        pictureFrame = null;
      }
    }
  }
  private void checkOpen() {
    if (closing)
      throw new UnsupportedOperationException("This ImageBase has been closed");
  }
  /** create the menu frame.  This is empty to begin with */
  private void setupMenuFrame() {
    
    /* Create the buttons */
    buttons = new SimpleButton[0];
    
    /* Create the menu JFrame which will hold the menu JPanel */
    menuFrame = new JFrame("Image Manipulation Menu");
    
    /* If the user closes the window, our program should exit */
    menuFrame.addWindowListener(new WindowAdapter() {
      public void windowClosing(WindowEvent e) {
        shutdown();
      }
    });
    
    /* Optimally size the menuFrame */
    menuFrame.pack();
    
    /* Place the menuFrame near the top-left of the screen */
    menuFrame.setLocation(20,20);
    
  }

 /** gets a reference to the current picture.  If you modify this
  * directly, then you need to call the refresh method to have the
  * results displayed. */ 
  public Picture getPicture() {
    checkOpen();
    return picture;
  } 

  /** sets the current picture the the one provided and refreshes the
   * display. 
    * @param newPic the new picture
    */
  public void setPicture(Picture newPic) {
    checkOpen();
    picture=newPic;
    refresh();
  }
   
 /** refreshes the display with the current picture */ 
  public void refresh () {
    if (hasGui) {
      checkOpen();
      pictureFrame.refresh(picture);
    }
  }
 
  /** add a button to the menu.  */
  public void addButton(Manipulator action) {
    checkOpen();
    if (counter>=buttons.length){
      SimpleButton[] newButtons = new SimpleButton[buttons.length+2];
      for (int i = 0; i < newButtons.length; i++){
        if(i<buttons.length) {
          newButtons[i] = buttons[i];
        } else {
          newButtons[i] = new SimpleButton(this, new NoOperation());
        }
      }
      buttons = newButtons;
    }

    buttons[counter++]=new SimpleButton(this, action);

    if (hasGui) {
      /* Create a JPanel to put the buttons on */
      JPanel menuPanel = new JPanel();

      /* Make the menu background black */
      menuPanel.setBackground(Color.black);

      /* Make sure the buttons line up nicely */
      menuPanel.setLayout(new GridLayout(buttons.length/2,2));

      /* Add buttons to the menu, skipping the Restore and Quit buttons */
      for (int i = 0; i < buttons.length; i++) {
        menuPanel.add(buttons[i]);
      }

      /* The JPanel is now added to the menu JFrame */
      menuFrame.getContentPane().removeAll();
      menuFrame.getContentPane().add(menuPanel, BorderLayout.CENTER);


      /* Optimally size the menuFrame */
      menuFrame.pack();

      /* Place the menuFrame near the top-left of the screen */
      menuFrame.setLocation(20,20);

      /* Make the menuFrame visible */
      menuFrame.setVisible(true);
    }
  }


  /** sets up the image frame. */
  private void setupImageFrame(String filename) {
    
    /* Read a color picture from a file */
    picture = new Picture(filename);
    
    /* Put the picture in a PictureFrame called "Image" */
    pictureFrame = new PictureFrame("Image", picture);
    
    /* Quit the program if the user closes the PictureFrame */
    pictureFrame.addWindowListener(new WindowAdapter() {
      public void windowClosing(WindowEvent e) {
        shutdown();
      }
    });
    
    /* Make the PictureFrame the optimal size for this picture */
    pictureFrame.pack();
    
    /* Place the PictureFrame 25 pixels to right of the MenuFrame */
    Point p = menuFrame.getLocation();
    pictureFrame.setLocation(p.x+menuFrame.getSize().width+25, p.y);
    
    /* Make the PictureFrame visible */
    pictureFrame.setVisible(true);
    
  }
 
 /** main method (for using this as a standalone application.  Creates
  * an ImageBase object and adds a FlipHorizontal button to it.  
  * @param args Should be a single-element array.  The value of the
  * element is the name of the file to read. */
  public static void main (String[] args) {
    ImageBase app;
    
    if (args.length == 1) {
      File f = new File (args[0]);
      if (f.exists()) {
        app = new ImageBase(args[0]);
        app.addButton(new FlipHorizontal());
//        app.addButton(new FlipVertical());
//        app.addButton(new EdgeDetect());
//        app.addButton(new ToGray());
//        app.addButton(new Negate());
//        app.addButton(new GreenScreen());
//        app.addButton(new Convolve());
//        app.addButton(new GaussianBlur());
//        app.addButton(new ColorRotate());
        app.addButton(new Save());
      } else {
        System.err.println(args[0] + ": File not found.");
      }
    } else {
      System.err.println("Image file required.");
    }
  }
  
}
