package ui.view;

import javax.swing.JButton;
import javax.swing.JComboBox;
import javax.swing.JFileChooser;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JMenuBar;
import javax.swing.JPanel;
import javax.swing.JRadioButton;
import javax.swing.JTextField;
import javax.swing.event.CaretEvent;
import javax.swing.event.CaretListener;
import javax.swing.event.ChangeEvent;
import javax.swing.event.ChangeListener;
import javax.tools.Diagnostic;
import javax.tools.DiagnosticCollector;
import javax.tools.JavaCompiler;
import javax.tools.JavaFileObject;
import javax.tools.StandardJavaFileManager;
import javax.tools.StandardLocation;
import javax.tools.ToolProvider;

import com.sun.crypto.provider.JceKeyStore;

import classes.AbstractCpsObject;
import classes.HolonObject;
import classes.HolonSwitch;
import classes.HolonTransformer;
import jdk.nashorn.api.scripting.URLReader;
import ui.controller.Control;
import ui.model.Model;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.awt.GridBagLayout;
import java.awt.Color;
import java.awt.Cursor;
import java.awt.Dimension;
import java.awt.GridBagConstraints;
import java.awt.Insets;
import java.awt.event.ActionListener;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.net.MalformedURLException;
import java.net.URL;
import java.net.URLClassLoader;
import java.nio.file.Files;
import java.awt.FlowLayout;
import com.scarekroow.exampleapi.*;

/**
 * This Class represents the Menu, where you can edit stuff about the
 * Simulation.
 * 
 * @author Gruppe14
 */
public class SimulationMenu extends JMenuBar {

	private static final long serialVersionUID = 1L;

	private JPanel menuPanel = new JPanel();
	private JRadioButton simButton = new JRadioButton("Simulate");
	private JLabel simSpeedLabel = new JLabel("Simulation Speed:");
	private JTextField simSpeedText = new JTextField("1000");
	private JComboBox algoCombo = new JComboBox<>();
	private JButton algoFolderButton = new JButton("Algorithm:");
	private HashMap<String, File> algosHash = new HashMap<>();

	// root Directory
	File root = null;

	Model model;
	Control controller;

	/**
	 * Constructor.
	 * 
	 * @param mod
	 *            the Model
	 * @param cont
	 *            the Controller
	 */
	public SimulationMenu(Model mod, Control cont) {
		super();
		// Init Stuff
		this.model = mod;
		this.controller = cont;

		// algoFolderButton Action
		algoFolderButton.addActionListener(new ActionListener() {

			@Override
			public void actionPerformed(java.awt.event.ActionEvent evt) {
				menuSetFolderActionPerformed(evt);
			}

			private void menuSetFolderActionPerformed(java.awt.event.ActionEvent evt) {
				JFileChooser fileChooser = new JFileChooser();
				JFrame test = new JFrame();
				fileChooser.setFileSelectionMode(JFileChooser.DIRECTORIES_ONLY);
				fileChooser.setAcceptAllFileFilterUsed(false);

				if (fileChooser.showOpenDialog(test) == JFileChooser.APPROVE_OPTION) {
					algoCombo.removeAllItems();
					File[] files = fileChooser.getSelectedFile().listFiles();
					for (int i = 0; i < files.length; i++) {
						if (files[i].toString()
								.endsWith(".java") /*
													 * || files[i].toString().
													 * endsWith(".class")
													 */) {
							String name = files[i].getName();
							int tmpB = name.lastIndexOf('.');
							name = name.substring(0, tmpB);
							algosHash.put(name, files[i]);
							algoCombo.addItem(name);
							root = new File(fileChooser.getCurrentDirectory().getPath());
							setAlgorithm(files[i]);
						}
					}
				}
			}

		});

		// Add to Panel
		GridBagLayout gblmenuPanel = new GridBagLayout();
		gblmenuPanel.columnWidths = new int[] { 79, 105, 34, 60, 31, 151, 0 };
		gblmenuPanel.rowHeights = new int[] { 25, 0 };
		gblmenuPanel.columnWeights = new double[] { 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, Double.MIN_VALUE };
		gblmenuPanel.rowWeights = new double[] { 0.0, Double.MIN_VALUE };
		menuPanel.setLayout(gblmenuPanel);

		// isSimulation
		simButton.addPropertyChangeListener(new PropertyChangeListener() {

			@Override
			public void propertyChange(PropertyChangeEvent evt) {
				controller.setIsSimulation(simButton.isSelected());
				controller.calculateStateForCurrentTimeStep();
			}
		});
		GridBagConstraints gbcsimButton = new GridBagConstraints();
		gbcsimButton.anchor = GridBagConstraints.NORTHWEST;
		gbcsimButton.insets = new Insets(0, 0, 0, 5);
		gbcsimButton.gridx = 0;
		gbcsimButton.gridy = 0;
		menuPanel.add(simButton, gbcsimButton);
		GridBagConstraints gbcsimSpeedLabel = new GridBagConstraints();
		gbcsimSpeedLabel.anchor = GridBagConstraints.WEST;
		gbcsimSpeedLabel.insets = new Insets(0, 0, 0, 5);
		gbcsimSpeedLabel.gridx = 1;
		gbcsimSpeedLabel.gridy = 0;
		menuPanel.add(simSpeedLabel, gbcsimSpeedLabel);

		// timerSpeed
		simSpeedText.setMaximumSize(new Dimension(300, 300));
		simSpeedText.addCaretListener(new CaretListener() {
			@Override
			public void caretUpdate(CaretEvent e) {
				try {
					controller.setTimerSpeed(Integer.parseInt(simSpeedText.getText()));
				} catch (Exception ex) {
					// TODO: handle exception
				}

			}
		});
		GridBagConstraints gbcSimSpeedText = new GridBagConstraints();
		gbcSimSpeedText.anchor = GridBagConstraints.WEST;
		gbcSimSpeedText.insets = new Insets(0, 0, 0, 5);
		gbcSimSpeedText.gridx = 2;
		gbcSimSpeedText.gridy = 0;
		menuPanel.add(simSpeedText, gbcSimSpeedText);
		GridBagConstraints gbcAlgoFolderButton = new GridBagConstraints();
		gbcAlgoFolderButton.anchor = GridBagConstraints.WEST;
		gbcAlgoFolderButton.insets = new Insets(0, 0, 0, 5);
		gbcAlgoFolderButton.gridx = 3;
		gbcAlgoFolderButton.gridy = 0;
		menuPanel.add(algoFolderButton, gbcAlgoFolderButton);

		GridBagConstraints gbcAlgoCombo = new GridBagConstraints();
		gbcAlgoCombo.anchor = GridBagConstraints.WEST;
		gbcAlgoCombo.insets = new Insets(0, 0, 0, 5);
		gbcAlgoCombo.gridx = 4;
		gbcAlgoCombo.gridy = 0;
		menuPanel.add(algoCombo, gbcAlgoCombo);
		algoCombo.addItem("choose folder");

		// Add Panel to SimulationMenu
		this.add(menuPanel);
	}

	public void setAlgorithm(File file) {
		try {

			// Compile source file.

			JavaCompiler compiler = ToolProvider.getSystemJavaCompiler();

			compiler.run(null, null, null, file.getPath());

			// Load and instantiate compiled class.
			controller.addTextToConsole(root.toString());
			URLClassLoader classLoader = URLClassLoader.newInstance(new URL[] { root.toURI().toURL() });
			Class<?> cls = Class.forName("projectPackage.APITest", true, classLoader);

			Object t = cls.newInstance();

			controller.addTextToConsole("success");

			controller.setAlgorithm(t);

		} catch (Exception e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}
}
