import javax.swing.*;
import java.awt.event.*;
import java.awt.*;
import javax.swing.border.EtchedBorder;
import javax.swing.border.TitledBorder;
import java.lang.*;
import java.util.*;
import java.io.*;
import javax.imageio.*;
import java.awt.image.BufferedImage;

public class EvoMain
{
	public static void main(String[] args)
	{

		mainFrame myframe = new mainFrame();
		myframe.show();
	}
}

class mainFrame extends JFrame
{
	 int HEIGHT = 850;
	 int WIDTH = 650;
	 Frame handleOnThisFrame;
	 int nodeSize = 20; // system node size

	 // A handle on this frame
	 JFrame mFrame = this;

	 GeneticOperators geneticOperators = new GeneticOperators(new Random());
	 ChromozomeParser parser = new ChromozomeParser();

	 ArtPanel artPanel = new ArtPanel();
	 ControlPanel controlPanel = new ControlPanel(geneticOperators, artPanel);


    protected void processWindowEvent( WindowEvent event ) {
        super.processWindowEvent( event ) ;
        if ( event.getID() == WindowEvent.WINDOW_CLOSING ) {
			//saveProfiles();
            System.exit( 0 ) ;
        }
    }


	public mainFrame()
	{
		artPanel.setControlPanel(controlPanel);

		handleOnThisFrame = this;

		setTitle("Evolutionary Art");
		setSize(WIDTH, HEIGHT);

        this.setLocation( ( int ) ( Toolkit.getDefaultToolkit().getScreenSize().getWidth() / 2 - getWidth() / 2 ) ,
                          ( int ) ( Toolkit.getDefaultToolkit().getScreenSize().getHeight() / 2 - getHeight() / 2 ) ) ;

// Menu bar creation
		JMenuBar menuBar = new JMenuBar();
		setJMenuBar(menuBar);

		JMenu fileMenu = new JMenu("File");
		menuBar.add(fileMenu);

		JMenuItem inputItem = new JMenuItem("Start New Generation");
		fileMenu.add(inputItem);
		NewGenerationListener genListener = new NewGenerationListener();
		inputItem.addActionListener(genListener);

		JMenuItem savePNGItem = new JMenuItem("Save Image as PNG");
		fileMenu.add(savePNGItem);
		SavePNGListener savePNGListener = new SavePNGListener();
		savePNGItem.addActionListener(savePNGListener);

		JMenuItem saveChromosomeItem = new JMenuItem("Save Image as Chromosome");
		fileMenu.add(saveChromosomeItem);
		SaveChromosomeListener saveChromosomeListener = new SaveChromosomeListener();
		saveChromosomeItem.addActionListener(saveChromosomeListener);

		JMenuItem importChromosomeItem = new JMenuItem("Import Chromosome");
		fileMenu.add(importChromosomeItem);
		ImportChromosomeListener importChromosomeListener = new ImportChromosomeListener();
		importChromosomeItem.addActionListener(importChromosomeListener);

		fileMenu.addSeparator();

		JMenuItem exit = new JMenuItem("Exit");
		fileMenu.add(exit);
		ExitListener exitListener = new ExitListener();
		exit.addActionListener(exitListener);

	/*
		Resize listener

	*/
		  addComponentListener( new ComponentAdapter() {
            public void componentResized( ComponentEvent e ) {
					 Dimension oTemp = new Dimension() ;

					 // Prevent any resize changes
					 oTemp.width = WIDTH;
					 oTemp.height = HEIGHT;
					 handleOnThisFrame.setSize( oTemp ) ;
				}
		  } ) ;

	/*
		Panels and layout here

	*/
		Container contentPane = getContentPane();
		contentPane.setLayout(new GridBagLayout());
		GridBagConstraints c = new GridBagConstraints();

		//this is the place holder for the top panel (probably gona be used for stats)
		//c.fill = GridBagConstraints.VERTICAL;

		//c.ipady = 40;
		//c.ipadx = 50;
		c.gridwidth = GridBagConstraints.REMAINDER;
		c.fill = GridBagConstraints.BOTH;
	    c.weightx = 1;
	    c.weighty = 0.8125;
	    c.ipady = 20;
		c.gridx = 0;
		c.gridy = 0;
		c.gridheight = 1;
		/* the upper 82% of screen */
		artPanel.setBackground(new Color(0, 0, 0));
		contentPane.add(artPanel, c);

	    c.weighty = 0.1875;
		c.ipady = 0;
		c.gridx = 0;
		c.gridy = 1;
		c.gridheight = 4;
		/* the lower 18% of screen */
		contentPane.add(controlPanel, c);

	}

	private class ExitListener implements ActionListener
	{
		public void actionPerformed(ActionEvent event)
		{

            		System.exit( 0 ) ;
		}
	}

	private class NewGenerationListener implements ActionListener
	{
		public void actionPerformed(ActionEvent event)
		{
			// make new generation if method returns true
			if(artPanel.hasCompletedComputation())
			{
				boolean test = true;
				nodeSize = 0;

				 while(test)
				 {
				 	 String inputString = JOptionPane.showInputDialog( "Enter Node Size of Chromozomes:" , "20" ) ;

				 	 try
				 	 {
						 nodeSize = Integer.parseInt(inputString);
						 test = false;
					 }
					 catch(NumberFormatException e)
					 {
						 test = true;
					 }

					 if(nodeSize < 1) test = true;
				 }

				artPanel.createNewGeneration(nodeSize);
				controlPanel.repaint();
			}
			else // do nothing because there is a thread computing images active
			{

			}
		}
	}

	private class SavePNGListener implements ActionListener
	{
		public void actionPerformed(ActionEvent event)
		{
			int numSelect = artPanel.getNumberOfSelections();

			if(numSelect == 0)
			{ // need to select something
				JOptionPane.showMessageDialog( null , "An Image needs to be selected." , "Warning!" , JOptionPane.ERROR_MESSAGE ) ;
			}
			else if(numSelect > 1)
			{ // to many things selected
				JOptionPane.showMessageDialog( null , "Only one(1) image may be selected." , "Warning!" , JOptionPane.ERROR_MESSAGE ) ;
			}
			else // num select == 1
			{ // Ok to save
				JFileChooser chooser = new JFileChooser();
				ExampleFileFilter filter = new ExampleFileFilter();
				filter.addExtension("PNG");
				filter.setDescription("PNG Images");
				chooser.setFileFilter(filter);

				// set current directory to the location of the code
				File dirFile = new File(System.getProperty("user.dir")+"\\PNG Images");
				chooser.setCurrentDirectory(dirFile);

				int returnVal = chooser.showSaveDialog(mFrame);

				// if user hit save, save file to directory.
				if(returnVal == JFileChooser.APPROVE_OPTION)
				{
            		 BufferedImage image = artPanel.getSelectedImage();

					 if(image == null)
					 {
						JOptionPane.showMessageDialog( null , "An error has occured, image was not saved." , "Warning!" , JOptionPane.ERROR_MESSAGE ) ;
					 }
					 else
					 {
						 String name = chooser.getSelectedFile().getName();
						 // if the name doesn't have .png, add it
						 if( !name.endsWith(".png") )
						 	name = name + ".png";

						 name = "\\"+name;

						 try {
								ImageIO.write(image, "png", new File(chooser.getCurrentDirectory() + "" + name));
							}
						 catch (IOException e)
						 {
							 System.out.println("Exception caught.  Was attempting to save PNG.");
						 }
					 }
				}
			}
		}
	}


	private class SaveChromosomeListener implements ActionListener
	{
		public void actionPerformed(ActionEvent event)
		{
			int numSelect = artPanel.getNumberOfSelections();

			if(numSelect == 0)
			{ // need to select something
				JOptionPane.showMessageDialog( null , "An Image needs to be selected." , "Warning!" , JOptionPane.ERROR_MESSAGE ) ;
			}
			else if(numSelect > 1)
			{ // to many things selected
				JOptionPane.showMessageDialog( null , "Only one(1) image may be selected." , "Warning!" , JOptionPane.ERROR_MESSAGE ) ;
			}
			else // num select == 1
			{ // Ok to save
				JFileChooser chooser = new JFileChooser();
				ExampleFileFilter filter = new ExampleFileFilter();
				filter.addExtension("TXT");
				filter.setDescription("Chromosomes");
				chooser.setFileFilter(filter);

				// set current directory to the location of the code
				File dirFile = new File(System.getProperty("user.dir")+"\\Chromosomes");
				chooser.setCurrentDirectory(dirFile);

				int returnVal = chooser.showSaveDialog(mFrame);

				// if user hit save, save file to directory.
				if(returnVal == JFileChooser.APPROVE_OPTION)
				{
            		 Chromozome chromosome = artPanel.getSelectedChromosome();

					 if(chromosome == null)
					 {
						JOptionPane.showMessageDialog( null , "An error has occured, image was not saved." , "Warning!" , JOptionPane.ERROR_MESSAGE ) ;
					 }
					 else
					 {
						 String name = chooser.getSelectedFile().getName();
						 // if the name doesn't have .txt, add it
						 if( !name.endsWith(".txt") )
						 	name = name + ".txt";

						 name = "\\"+name;

						 try {
							   FileOutputStream file = new FileOutputStream(chooser.getCurrentDirectory() + "" + name);


							   String dataString = chromosome.toString();
							   byte data[] = dataString.getBytes();
        					   file.write(data);

        					   file.close();
							}
						 catch (IOException e)
						 {
							 System.out.println("Exception caught.  Was attempting to save Chromosome.");
						 }
					 }
				}
			}
		}
	}



	private class ImportChromosomeListener implements ActionListener
	{
		public void actionPerformed(ActionEvent event)
		{
			int numSelect = artPanel.getNumberOfSelections();

			if(numSelect == 0)
			{ // need to select something
				JOptionPane.showMessageDialog( null , "An Image needs to be selected." , "Warning!" , JOptionPane.ERROR_MESSAGE ) ;
			}
			else if(numSelect > 1)
			{ // to many things selected
				JOptionPane.showMessageDialog( null , "Only one(1) image may be selected." , "Warning!" , JOptionPane.ERROR_MESSAGE ) ;
			}
			else // num select == 1
			{ // Ok to save
				JFileChooser chooser = new JFileChooser();
				ExampleFileFilter filter = new ExampleFileFilter();
				filter.addExtension("TXT");
				filter.setDescription("Chromosomes");
				chooser.setFileFilter(filter);

				// set current directory to the location of the code
				File dirFile = new File(System.getProperty("user.dir")+"\\Chromosomes");
				chooser.setCurrentDirectory(dirFile);

				int returnVal = chooser.showOpenDialog(mFrame);

				// if user hit save, save file to directory.
				if(returnVal == JFileChooser.APPROVE_OPTION)
				{

					String name = chooser.getSelectedFile().getName();
					name = "\\"+name;

					String file = chooser.getCurrentDirectory() + "" + name;

					Chromozome importedCromosome = ChromozomeParser.parseFile(file);

					 if(importedCromosome == null)
					 {
						JOptionPane.showMessageDialog( null , "An error has occured, Chromosome could not be parsed." , "Warning!" , JOptionPane.ERROR_MESSAGE ) ;
					 }
					 else
					 {
						 // need to verify that node size is compatable with
						 // system node size

						 // if node sizes are equal, don't have to fix anything
						 if(importedCromosome.getNodeSize() == nodeSize)
						 {
							 artPanel.ImportChromosome(importedCromosome);
						 }
						 else if(importedCromosome.getNodeSize() < nodeSize)
						 {
							 Chromozome extended = GeneticOperators.generateChromozome(nodeSize);

							 //copy in smaller chromosome into larger, skip RGB pointers
							 for(int i = 0; i < importedCromosome.getNodeSize() * 4; i++)
							 {
								 extended.setValueAtIndex(i, importedCromosome.getValueAtIndex(i));
							 }

							 // replace RGB pointers of bigger chromosome with smaller
							 int importedNodeSize = importedCromosome.getNodeSize();
							 extended.setValueAtIndex(nodeSize*4, importedCromosome.getValueAtIndex(importedNodeSize*4));
							 extended.setValueAtIndex(nodeSize*4+1, importedCromosome.getValueAtIndex(importedNodeSize*4+1));
							 extended.setValueAtIndex(nodeSize*4+2, importedCromosome.getValueAtIndex(importedNodeSize*4+2));

							 // add the new larger chromosome into the art panel
							 artPanel.ImportChromosome(extended);
						 }
						 else // else imported chromosome is to big, can't import
						 {
							JOptionPane.showMessageDialog( null , "Unable to import.  Chromosome is to large.  Imported NodeSize = "
							+importedCromosome.getNodeSize() +
							    "   System NodeSize = "+nodeSize , "Warning!" , JOptionPane.ERROR_MESSAGE ) ;
						 }
					 }
				}
			}
		}
	}
}