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.tools.JavaCompiler;
import javax.tools.ToolProvider;

import ui.controller.Control;
import ui.model.Model;
import java.util.HashMap;
import java.awt.GridBagLayout;
import java.awt.Dimension;
import java.awt.GridBagConstraints;
import java.awt.Insets;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.io.BufferedReader;
import java.io.File;
import java.io.FileReader;
import java.net.URL;
import java.net.URLClassLoader;

/**
 * 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();
	JRadioButton simButton = new JRadioButton(Languages.getLanguage()[83]);
	JLabel simSpeedLabel = new JLabel(Languages.getLanguage()[84]);
	private JTextField simSpeedText = new JTextField("1000");
	private JComboBox<Object> algoCombo = new JComboBox<>();
	JButton algoFolderButton = new JButton(Languages.getLanguage()[85]);
	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;

		// Algorithm ComboBox Action
		algoCombo.addActionListener(new ActionListener() {
			@Override
			public void actionPerformed(ActionEvent e) {
				setAlgorithm(algosHash.get(algoCombo.getSelectedItem()), algoCombo.getSelectedItem() + "");
			}
		});

		// 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();
					// Set Root Folder Path
					root = new File(fileChooser.getCurrentDirectory().getPath());

					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);

						}
					}

				}
			}

		});

		// 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.addActionListener(new ActionListener() {

			@Override
			public void actionPerformed(ActionEvent e) {
				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.setMinimumSize(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(Languages.getLanguage()[86]);

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

	public void setAlgorithm(File file, String name) {
		try {
			BufferedReader br = new BufferedReader(new FileReader(file.getPath()));
			String line = br.readLine();
			// Package Name
			String packageName = "";

			while (line != null) {
				line = line.trim();
				if (!line.isEmpty()) {
					if (line.length() >= 7 && line.substring(0, 7).equals("package")) {
						packageName = line.substring(8, line.length() - 1);
					}
				}
				if (packageName.isEmpty()) {
					line = br.readLine();
				} else {
					line = null;
				}

			}

			// Compile source file.
			JavaCompiler compiler = ToolProvider.getSystemJavaCompiler();

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

			// Load and instantiate compiled class.
			URLClassLoader classLoader = URLClassLoader.newInstance(new URL[] { root.toURI().toURL() });

			Class<?> cls;
			if (packageName.isEmpty()) {
				cls = Class.forName(name, true, classLoader);
			} else {
				cls = Class.forName(packageName + "." + name, true, classLoader);
			}

			Object t = cls.newInstance();

			controller.setAlgorithm(t);

		} catch (Exception e) {
			controller.addTextToConsole(e.toString());
		}
	}
}
