package mosaiccreator;

import java.awt.BorderLayout;
import java.awt.AWTEvent;
import java.awt.Dimension;
import java.awt.Toolkit;
import java.awt.event.ActionEvent;
import java.awt.event.WindowEvent;
import java.awt.event.ActionListener;
import java.awt.event.MouseListener;
import java.awt.event.MouseEvent;
import javax.swing.BorderFactory;
import javax.swing.UIManager;
import javax.swing.JPanel;
import javax.swing.JMenuBar;
import javax.swing.JMenu;
import javax.swing.JMenuItem;
import javax.swing.JFrame;
import javax.swing.JSlider;
import java.awt.Frame;
import java.awt.Point;

/**
 *
 * <p>Title: Interactive Viewer</p>
 * <p>Description: a interactive viewer for mosaic images</p>
 * @author Lance Finfrock
 * @version 1.0
 */
public class InteractiveViewer extends JFrame {

  private JPanel contentPane;
  private JMenuBar jMenuBar1 = new JMenuBar();
  private JMenu jMenuFile = new JMenu();
  private JMenuItem jMenuFileExit = new JMenuItem();
  private JMenu jMenuFileSave = new JMenu();
  private JMenuItem[] jMenuFileSaveSizes = new JMenuItem[4];
  private JMenuItem jMenuFilePrint = new JMenuItem();
  private JMenuItem jMenuFileSaveMoFormat = new JMenuItem();
  private JMenu jMenuHelp = new JMenu();
  private JMenu jMenuOptions = new JMenu();
  private JMenuItem jMenuOptionsOn_Off = new JMenuItem();
  private JMenuItem jMenuHelpAbout = new JMenuItem();
  private JMenuItem jMenuHelpManual = new JMenuItem();
  private JMenuItem[] jMenuOptionsScrollOverEnlargement = new JMenuItem[2];
  private JMenuItem jMenuOptionsScrollOver = new JMenu();
  private BorderLayout borderLayout1 = new BorderLayout();
  private Viewer MosaicView;
  private Frame cameFromWindow;
  private JSlider InvertedLevel = new JSlider();

  /**
   *
   * @param cameFrom Frame the window that the interactive window was started from
   */
  public InteractiveViewer(Frame cameFrom) {

    enableEvents(AWTEvent.WINDOW_EVENT_MASK);
    this.cameFromWindow = cameFrom;
    try {
      jbInit();
    }
    catch(Exception e) {
      e.printStackTrace();
    }
  }

  //Component initialization
  private void jbInit() throws Exception  {

    //don't allow the user to use the window that started this window while this one is running
    this.cameFromWindow.setEnabled(false);

    this.setIconImage(PictureTools.readImage("mosaicImage.gif", this));

    contentPane = (JPanel) this.getContentPane();
    contentPane.setLayout(borderLayout1);

    //start the mosaci image creator to create an image of the stored mosaic
    new MosaicImageCreater(this, InvertedLevel.getValue()/100.0);

    //create the mosaic viewer
    this.MosaicView = new Viewer();
    this.MosaicView.setVisible(false);


    this.jMenuFileSaveMoFormat.setText("Save as Mosaic");
    this.jMenuFileSave.setText("Save as JPEG");
    this.jMenuFilePrint.setText("Print");

    //get the three different dimentions for the save option
    this.findJPEGSizes();

    for(int i = 0; i < jMenuFileSaveSizes.length; i++)
      jMenuFileSave.add(jMenuFileSaveSizes[i]);

    jMenuFile.add(jMenuFileSave);
    jMenuFilePrint.addActionListener(new InteractiveViewer_jMenuFileSave_ActionAdapter(this));
    jMenuFileSaveMoFormat.addActionListener(new InteractiveViewer_jMenuFileSave_ActionAdapter(this));
    jMenuFile.add(jMenuFileSaveMoFormat);
    jMenuFile.add(jMenuFilePrint);
    this.setTitle("Picture Mosaic");
    for(int OptionsEnlargementIndex = 0; OptionsEnlargementIndex < jMenuOptionsScrollOverEnlargement.length; OptionsEnlargementIndex++){
      jMenuOptionsScrollOverEnlargement[OptionsEnlargementIndex] = new JMenuItem();
    }
    int Zoomsize = (int)Math.log(MainWindow.currentMosaic.DivionsHigh * MainWindow.currentMosaic.DivionsWide);// figureing the size of the zoom
    jMenuOptionsScrollOverEnlargement[0].setText((int)(Zoomsize/1.5) + " x");
    jMenuOptionsScrollOverEnlargement[1].setText(Zoomsize + " x");
    jMenuFile.setText("File");
    jMenuFileExit.setText("Exit");
    jMenuFileExit.addActionListener(new InteractiveViewer_jMenuFileExit_ActionAdapter(this));
    jMenuHelp.setText("Help");
    jMenuHelpAbout.setText("About");
    jMenuHelpManual.setText("Manual");
    jMenuOptions.setText("Options");
    jMenuOptionsOn_Off.setText("Off");
    jMenuOptionsOn_Off.addActionListener(new InteractiveViewer_jMenuOptionsOn_Off_ActionAdapter(this));
    for(int i = 0; i < jMenuOptionsScrollOverEnlargement.length ; i++)
      jMenuOptionsScrollOverEnlargement[i].addActionListener(new InteractiveViewer_jMenuOptionsScrollOverEnlargement_ActionAdapter(this));

    jMenuOptionsScrollOver.setText("Scroll Over");
    jMenuHelpAbout.addActionListener(new InteractiveViewer_jMenuHelpAbout_ActionAdapter(this));
    jMenuHelpManual.addActionListener(new InteractiveViewer_jMenuHelpManual_ActionAdapter(this));
    jMenuFile.add(jMenuFileExit);
    jMenuOptions.add(jMenuOptionsScrollOver);
    jMenuOptionsScrollOver.add(jMenuOptionsOn_Off);
    for(int i = 0; i < jMenuOptionsScrollOverEnlargement.length; i++)
      jMenuOptionsScrollOver.add(jMenuOptionsScrollOverEnlargement[i]);

    jMenuHelp.add(jMenuHelpAbout);
    jMenuHelp.add(jMenuHelpManual);
    jMenuBar1.add(jMenuFile);
    jMenuBar1.add(jMenuOptions);
    jMenuBar1.add(jMenuHelp);

    InvertedLevel.addMouseListener(new MouseClickListenerForSlider());
    InvertedLevel.setInverted(true);
    InvertedLevel.setMaximum(100);
    InvertedLevel.setMinimum(0);
    InvertedLevel.setBackground(UIManager.getColor("FormattedTextField.inactiveForeground"));
    InvertedLevel.setBorder(BorderFactory.createLoweredBevelBorder());
    InvertedLevel.setValue(50);
    InvertedLevel.setPreferredSize(new Dimension(100, 24));
    contentPane.add(MosaicView, BorderLayout.CENTER);
    contentPane.add(InvertedLevel, BorderLayout.SOUTH);
    this.setJMenuBar(jMenuBar1);
    Dimension screenSize = Toolkit.getDefaultToolkit().getScreenSize();

    //create the window half the size of the current window size
    this.setSize((int) screenSize.getWidth() / 2, (int) screenSize.getHeight() / 2);
    this.validate();

    //Center the window
    Dimension frameSize = this.getSize();
    if (frameSize.height > screenSize.height) {
      frameSize.height = screenSize.height;
    }
    if (frameSize.width > screenSize.width) {
      frameSize.width = screenSize.width;
    }
    this.setLocation( (screenSize.width - frameSize.width) / 2,
                     (screenSize.height - frameSize.height) / 2);

    this.setVisible(true);

  }


  /**
   * File | Exit action performed
   * @param e ActionEvent
   */
  public void jMenuFileExit_actionPerformed(ActionEvent e) {

    //allow the user to use the main window
    this.cameFromWindow.setEnabled(true);

    //bring the main window to the front of the screen
    this.cameFromWindow.toFront();

    //get rid of this window
    this.dispose();

  }


  /**
   * Help | About action performed
   * @param e ActionEvent
   */
  public void jMenuHelpAbout_actionPerformed(ActionEvent e) {
    //creat the about window
    MainWindow_AboutBox dlg = new MainWindow_AboutBox(this);

    //get the preferred size
    Dimension dlgSize = dlg.getPreferredSize();
    Dimension frmSize = getSize();
    Point loc = getLocation();

    //center the window
    dlg.setLocation((frmSize.width - dlgSize.width) / 2 + loc.x, (frmSize.height - dlgSize.height) / 2 + loc.y);
    dlg.setModal(true);
    dlg.pack();
    dlg.show();

  }

  /**
   * opens the users manual
   * @param e ActionEvent
   */
  public void jMenuHelpManual_actionPerformed(ActionEvent e) {
    new UserManualFrame();
  }

  /**
   * set the zoom of the viewer
   * @param e ActionEvent
   */
  public void jMenuOptionsScrollOverEnlargement_actionPerformed(ActionEvent e){
    MosaicView.setZoom(Integer.parseInt(e.getActionCommand().substring(0,2).trim()));
  }

  /**
   * turning the mouse over viewer on and off
   * @param e ActionEvent
   */
  public void jMenuOptionsOn_Off_actionPerformed(ActionEvent e) {

    //if the mouse over view is on
    if(MosaicView.isMouseOverViewOn){

      //set the mouse over view off
      MosaicView.isMouseOverViewOn = false;

      //allow the user to turn the mouse over view back on
      jMenuOptionsOn_Off.setText("On");

      //turn the options of sizes of the views off
      for(int i = 0; i < jMenuOptionsScrollOverEnlargement.length; i++)
        jMenuOptionsScrollOverEnlargement[i].setVisible(false);

    }
    else{//if the mouse over view is off

      //turn the mouse over view on
      MosaicView.isMouseOverViewOn = true;

      //allow the user to turn the mouse over back on
      jMenuOptionsOn_Off.setText("Off");

      //turn the options of sizes of the views on
      for(int i = 0; i < jMenuOptionsScrollOverEnlargement.length; i++)
        jMenuOptionsScrollOverEnlargement[i].setVisible(true);

    }

  }

  /**
   * catches the save options clicked
   * @param e ActionEvent
   */
  public void jMenuFileSave_actionPerformed(ActionEvent e) {

      if(e.getActionCommand().equalsIgnoreCase("Save as Mosaic")) {

        //start the mosaic saver
        new MosaicSaver(this);

      }
      else if(e.getActionCommand().equalsIgnoreCase("Print")){

        //start the mosaic printer
        new MosaicPrinter(this, this.InvertedLevel.getValue()/100.0);

      }
      else{

        //get the diementions of the picture to save
        String[] numbers = e.getActionCommand().split(" X ");

        //start the jpeg saver
        new MosaicJPEGSaver(this, this.InvertedLevel.getValue()/100.0, Integer.parseInt(numbers[0]), Integer.parseInt( numbers[1]));
      }

  }

  /**
   * finds the sizes for saving a mosaic with the correct portoins
   */
  public void findJPEGSizes(){

    int width = MainWindow.currentMosaic.getWidth();
    int height = MainWindow.currentMosaic.getHeight();

    //these are just comman size for pictures
    int[] sizes = {850, 1100, 1500, 2000};
    int newWidth, newHeight;

    if (width > height) {
      for(int i = 0; i < sizes.length; i++){
        newWidth = sizes[i];
        newHeight = (newWidth * height) / width;
        jMenuFileSaveSizes[i] = new JMenuItem();
        jMenuFileSaveSizes[i].setText(newWidth + " X " + newHeight);
        jMenuFileSaveSizes[i].addActionListener(new InteractiveViewer_jMenuFileSave_ActionAdapter(this));
      }
    }
    else {
      for(int i = 0; i < sizes.length; i++){
        newHeight = sizes[i];
        newWidth = (newHeight * width) / height;
        jMenuFileSaveSizes[i] = new JMenuItem();
        jMenuFileSaveSizes[i].setText(newWidth + " X " + newHeight);
        jMenuFileSaveSizes[i].addActionListener(new InteractiveViewer_jMenuFileSave_ActionAdapter(this));
      }
    }
  }

  /**
   * create the mosaic to be displayed
   */
  public void createMosaicImage() {
    new MosaicImageCreater(this, InvertedLevel.getValue()/100.0);
  }

  /**
   * return method for creating a mosaic
   */
  public void creatingMosaicDone(){
    if(!MosaicView.isVisible())
      MosaicView.setVisible(true);

    MosaicView.redrawPictuer();
  }

  /**
   *
   * <p>Title: Mouse Listener for the slider</p>
   * <p>Description: mouse listener for the blending slider bar</p>
   * @author Lance Finfrock
   * @version 1.0
   */
  private class MouseClickListenerForSlider implements MouseListener {

    public void mouseClicked(MouseEvent mouseEvent) {}

    public void mousePressed(MouseEvent mouseEvent) {}

    /**
     * when the slider is reseased redraw the mosaic
     * @param mouseEvent MouseEvent
     */
    public void mouseReleased(MouseEvent mouseEvent) {
      createMosaicImage();
    }

    public void mouseEntered(MouseEvent mouseEvent) {}

    public void mouseExited(MouseEvent mouseEvent) {}
  }

  /**
   * catches closing, minizing, and unminizing of the window
   * @param e WindowEvent
   */
  protected void processWindowEvent(WindowEvent e) {
    super.processWindowEvent(e);

    if (e.getID() == WindowEvent.WINDOW_CLOSING) {
      jMenuFileExit_actionPerformed(null);
    }
    else if(e.getID() == WindowEvent.WINDOW_ICONIFIED){
      this.cameFromWindow.setVisible(false);
    }
    else if(e.getID() == WindowEvent.WINDOW_DEICONIFIED){
      this.cameFromWindow.setVisible(true);
          this.toFront();
    }
  }
}

class InteractiveViewer_jMenuFileExit_ActionAdapter implements ActionListener {
  InteractiveViewer adaptee;

  InteractiveViewer_jMenuFileExit_ActionAdapter(InteractiveViewer adaptee) {
    this.adaptee = adaptee;
  }
  public void actionPerformed(ActionEvent e) {
    adaptee.jMenuFileExit_actionPerformed(e);
  }
}

class InteractiveViewer_jMenuFileSave_ActionAdapter implements ActionListener {
  InteractiveViewer adaptee;

  InteractiveViewer_jMenuFileSave_ActionAdapter(InteractiveViewer adaptee) {
    this.adaptee = adaptee;
  }
  public void actionPerformed(ActionEvent e) {
    adaptee.jMenuFileSave_actionPerformed(e);
  }
}

class InteractiveViewer_jMenuOptionsOn_Off_ActionAdapter implements ActionListener {
  InteractiveViewer adaptee;

  InteractiveViewer_jMenuOptionsOn_Off_ActionAdapter(InteractiveViewer adaptee) {
    this.adaptee = adaptee;
  }
  public void actionPerformed(ActionEvent e) {
    adaptee.jMenuOptionsOn_Off_actionPerformed(e);
  }

}

class InteractiveViewer_jMenuHelpAbout_ActionAdapter implements ActionListener {
  InteractiveViewer adaptee;

  InteractiveViewer_jMenuHelpAbout_ActionAdapter(InteractiveViewer adaptee) {
    this.adaptee = adaptee;
  }
  public void actionPerformed(ActionEvent e) {
    adaptee.jMenuHelpAbout_actionPerformed(e);
  }
}

class InteractiveViewer_jMenuHelpManual_ActionAdapter implements ActionListener {
  InteractiveViewer adaptee;

  InteractiveViewer_jMenuHelpManual_ActionAdapter(InteractiveViewer adaptee) {
    this.adaptee = adaptee;
  }
  public void actionPerformed(ActionEvent e) {
    adaptee.jMenuHelpManual_actionPerformed(e);
  }
}

class InteractiveViewer_jMenuOptionsScrollOverEnlargement_ActionAdapter implements ActionListener{
  InteractiveViewer adaptee;

  InteractiveViewer_jMenuOptionsScrollOverEnlargement_ActionAdapter(InteractiveViewer adaptee) {
    this.adaptee = adaptee;
  }
  public void actionPerformed(ActionEvent e) {
    adaptee.jMenuOptionsScrollOverEnlargement_actionPerformed(e);
  }
}
