package View;

import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.Insets;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.io.File;
import java.util.Date;

import javax.swing.JButton;
import javax.swing.JFileChooser;
import javax.swing.JLabel;
import javax.swing.JSlider;
import javax.swing.JTextField;
import javax.swing.event.ChangeEvent;
import javax.swing.event.ChangeListener;
import javax.swing.event.DocumentEvent;
import javax.swing.event.DocumentListener;

import Controller.Controller;

/**
 * ParameterPanel.
 * 
 * @author Stefan Helfrich <stefan.helfrich@googlemail.com>
 */
public class ParameterPanel extends DataPanel {

	private static final long serialVersionUID = 1L;

	private JLabel utteranceLabel;
	private JTextField utteranceTextField;
	private JButton utteranceButton;
	private JFileChooser utteranceFileChooser;

	private JLabel imageDBLabel;
	private JTextField imageDBTextField;
	private JButton imageDBButton;
	private JFileChooser imageDBFileChooser;

	private JLabel additiveNoiseLabel;
	private JTextField additiveNoiseTextField;
	private JSlider additiveNoiseSlider;

	private JLabel subtractiveNoiseLabel;
	private JTextField subtractiveNoiseTextField;
	private JSlider subtractiveNoiseSlider;

	private JLabel learningThresholdLabel;
	private JTextField learningThresholdTextField;
	private JSlider learningThresholdSlider;
	
	private JLabel logLabel;
	private JTextField logTextField;
	private JButton logButton;
	private JFileChooser logFileChooser;

	private JButton preprocessButton;
	private JButton processButton;

	private JButton saveDefaultsButton;
	private JButton loadDefaultsButton;

	public ParameterPanel(Controller controller) {
		super(controller);
		initComponents();
	}

	public void updatePanel() {

	}

	/**
	 * This method is called from within the constructor to initialize the form.
	 */
	private void initComponents() {
		/*
		 * Initialization is in the order of appearance on screen.
		 */
		
		/*
		 * Initialization of components related to utterance
		 */
		utteranceLabel = new JLabel("Utterance file");
		utteranceTextField = new JTextField();
		utteranceTextField.setColumns(20);
		utteranceTextField.setText("utr/Example1.txt");
		utteranceButton = new JButton("Browse");
		utteranceButton.addActionListener(new ActionListener() {

			@Override
			public void actionPerformed(ActionEvent e) {
				int returnVal = utteranceFileChooser
						.showOpenDialog(ParameterPanel.this);

				if (returnVal == JFileChooser.APPROVE_OPTION) {
					File file = utteranceFileChooser.getSelectedFile();
					utteranceTextField.setText(file.getAbsolutePath());
				}
			}
		});
		utteranceFileChooser = new JFileChooser();

		/*
		 * Initialization of components related to imageDB
		 */
		imageDBLabel = new JLabel("Image database");
		imageDBTextField = new JTextField();
		imageDBTextField.setColumns(20);
		imageDBTextField.setText("exp_pic");
		imageDBButton = new JButton("Browse");
		imageDBButton.addActionListener(new ActionListener() {

			@Override
			public void actionPerformed(ActionEvent e) {
				int returnVal = imageDBFileChooser
						.showOpenDialog(ParameterPanel.this);

				if (returnVal == JFileChooser.APPROVE_OPTION) {
					File file = imageDBFileChooser.getSelectedFile();
					imageDBTextField.setText(file.getAbsolutePath());
				}
			}
		});
		imageDBFileChooser = new JFileChooser();
		imageDBFileChooser.setFileSelectionMode(JFileChooser.DIRECTORIES_ONLY);
		
		/*
		 * Initialization of components related to additive noise
		 */
		additiveNoiseLabel = new JLabel("Additive noise [%]");
		additiveNoiseTextField = new JTextField();
		additiveNoiseTextField.setColumns(4);
		additiveNoiseTextField.setText("0");
		additiveNoiseTextField.getDocument().addDocumentListener(
				new DocumentListener() {

					@Override
					public void removeUpdate(DocumentEvent e) {
						try {
							if (additiveNoiseTextField.isFocusOwner()) {
								additiveNoiseSlider.setValue(Integer
										.valueOf(additiveNoiseTextField
												.getText()));
							}
						} catch (NumberFormatException ex) {
							additiveNoiseSlider.setValue(0);
						}
					}

					@Override
					public void insertUpdate(DocumentEvent e) {
						removeUpdate(e);
					}

					@Override
					public void changedUpdate(DocumentEvent e) {
					}
				});
		additiveNoiseSlider = new JSlider(0, 1000);
		additiveNoiseSlider.setValue(0);
		additiveNoiseSlider.setMajorTickSpacing(500);
		additiveNoiseSlider.setMinorTickSpacing(100);
		additiveNoiseSlider.setPaintTicks(true);
		additiveNoiseSlider.setPaintLabels(true);
		additiveNoiseSlider.addChangeListener(new ChangeListener() {

			@Override
			public void stateChanged(ChangeEvent e) {
				if (additiveNoiseSlider.isFocusOwner()) {
					additiveNoiseTextField.setText(Integer
							.toString(additiveNoiseSlider.getValue()));
				}
			}
		});
		
		/*
		 * Initialization of components related to subtractive noise
		 */
		subtractiveNoiseLabel = new JLabel("Subtractive noise [%]");
		subtractiveNoiseTextField = new JTextField();
		subtractiveNoiseTextField.setColumns(4);
		subtractiveNoiseTextField.setText("0");
		subtractiveNoiseTextField.getDocument().addDocumentListener(
				new DocumentListener() {

					@Override
					public void removeUpdate(DocumentEvent e) {
						try {
							if (subtractiveNoiseTextField.isFocusOwner()) {
								subtractiveNoiseSlider.setValue(Integer
										.valueOf(subtractiveNoiseTextField
												.getText()));
							}
						} catch (NumberFormatException ex) {
							subtractiveNoiseSlider.setValue(0);
						}
					}

					@Override
					public void insertUpdate(DocumentEvent e) {
						removeUpdate(e);
					}

					@Override
					public void changedUpdate(DocumentEvent e) {
					}
				});
		subtractiveNoiseSlider = new JSlider(0, 100);
		subtractiveNoiseSlider.setValue(0);
		subtractiveNoiseSlider.setMajorTickSpacing(50);
		subtractiveNoiseSlider.setMinorTickSpacing(10);
		subtractiveNoiseSlider.setPaintTicks(true);
		subtractiveNoiseSlider.setPaintLabels(true);
		subtractiveNoiseSlider.addChangeListener(new ChangeListener() {

			@Override
			public void stateChanged(ChangeEvent arg0) {
				if (subtractiveNoiseSlider.isFocusOwner()) {
					subtractiveNoiseTextField.setText(Integer
							.toString(subtractiveNoiseSlider.getValue()));
				}
			}
		});
		
		/*
		 * Initialization of components related to learning threshold
		 */
		learningThresholdLabel = new JLabel("Learning threshold [%]");
		learningThresholdTextField = new JTextField();
		learningThresholdTextField.setColumns(4);
		learningThresholdTextField.setText("70");
		learningThresholdTextField.getDocument().addDocumentListener(
				new DocumentListener() {

					@Override
					public void removeUpdate(DocumentEvent e) {
						try {
							if (learningThresholdTextField.isFocusOwner()) {
								learningThresholdSlider.setValue(Integer
										.valueOf(learningThresholdTextField
												.getText()));
							}
						} catch (NumberFormatException ex) {
							learningThresholdSlider.setValue(0);
						}
					}

					@Override
					public void insertUpdate(DocumentEvent e) {
						removeUpdate(e);
					}

					@Override
					public void changedUpdate(DocumentEvent e) {
					}
				});
		learningThresholdSlider = new JSlider(0, 100);
		learningThresholdSlider.setValue(70);
		learningThresholdSlider.setMajorTickSpacing(50);
		learningThresholdSlider.setMinorTickSpacing(10);
		learningThresholdSlider.setPaintTicks(true);
		learningThresholdSlider.setPaintLabels(true);
		learningThresholdSlider.addChangeListener(new ChangeListener() {

			@Override
			public void stateChanged(ChangeEvent arg0) {
				if (learningThresholdSlider.isFocusOwner()) {
					learningThresholdTextField.setText(Integer
							.toString(learningThresholdSlider.getValue()));
				}
			}
		});
		
		/*
		 * Initialization of components related to log file
		 */
		logLabel = new JLabel("Log file");
		logTextField = new JTextField();
		logTextField.setColumns(20);
		Date date= new Date();
		logTextField.setText("log_default.log");
		logButton = new JButton("Browse");
		logButton.addActionListener(new ActionListener() {

			@Override
			public void actionPerformed(ActionEvent e) {
				int returnVal = logFileChooser
						.showOpenDialog(ParameterPanel.this);

				if (returnVal == JFileChooser.APPROVE_OPTION) {
					File file = logFileChooser.getSelectedFile();
					logTextField.setText(file.getAbsolutePath());
				}
			}
		});
		logFileChooser = new JFileChooser();
		
		/*
		 * Initialization of components related to preprocess button
		 */
		preprocessButton = new JButton("Preprocess");
		preprocessButton.addActionListener(new ActionListener() {

			@Override
			public void actionPerformed(ActionEvent e) {
				try {
					cont.setParameters(new File(utteranceTextField.getText()),//utteranceFileChooser.getSelectedFile(),
							new File(imageDBTextField.getText()),//imageDBFileChooser.getSelectedFile(),
							new File(logTextField.getText()),//logFileChooser.getSelectedFile(),
							subtractiveNoiseSlider.getValue() / 100.0,
							additiveNoiseSlider.getValue() / 100.0,
							learningThresholdSlider.getValue() / 100.0);
					cont.preprocess();
					disablePanel();
					processButton.setEnabled(true);
				} catch (Exception ex) {
					ex.printStackTrace();
				}
			}
		});
		
		/*
		 * Initialization of components related to process button
		 */
		processButton = new JButton("Process");
		processButton.setEnabled(false);
		processButton.addActionListener(new ActionListener() {

			@Override
			public void actionPerformed(ActionEvent e) {
				cont.process();
				processButton.setEnabled(false);
				GUI.updatePanels();
			}
		});

		/*
		 * Initialization of components related to default buttons
		 */
		saveDefaultsButton = new JButton("Save as default parameters");
		saveDefaultsButton.setEnabled(false);

		loadDefaultsButton = new JButton("Load default parameters");
		loadDefaultsButton.setEnabled(false);

		/*
		 * GridBagLayout resulting the below shown layout
		 * 
		 * JLabel | JTextField      ....      | JButton
		 * JLabel | JTextField  |  JSlider    | 
		 * JLabel | JTextField  |  JSlider    | 
		 * JLabel | JTextField      ....      | JButton
		 * JLabel | JTextField      ....      | JButton
		 *        |             |             | JButton
		 *        |             |             | JButton 
		 */
		GridBagLayout gbl = new GridBagLayout();
		setLayout(gbl);

		GridBagConstraints gbc = new GridBagConstraints();
		gbc.gridy = 0;
		gbc.gridx = 0;
		gbl.setConstraints(utteranceLabel, gbc);
		add(utteranceLabel);

		gbc.gridx = 1;
		gbc.gridwidth = 2;
		gbl.setConstraints(utteranceTextField, gbc);
		add(utteranceTextField);
		gbc.gridwidth = 1;

		gbc.gridx = 3;
		gbl.setConstraints(utteranceButton, gbc);
		add(utteranceButton);

		gbc.gridy = 1;
		gbc.gridx = 0;
		gbl.setConstraints(imageDBLabel, gbc);
		add(imageDBLabel);

		gbc.gridx = 1;
		gbc.gridwidth = 2;
		gbl.setConstraints(imageDBTextField, gbc);
		add(imageDBTextField);
		gbc.gridwidth = 1;

		gbc.gridx = 3;
		gbl.setConstraints(imageDBButton, gbc);
		add(imageDBButton);

		gbc.gridy = 2;
		gbc.gridx = 0;
		gbl.setConstraints(additiveNoiseLabel, gbc);
		add(additiveNoiseLabel);

		gbc.gridx = 1;
		gbc.anchor = GridBagConstraints.LINE_START;
		gbl.setConstraints(additiveNoiseTextField, gbc);
		add(additiveNoiseTextField);
		gbc.anchor = GridBagConstraints.CENTER;

		gbc.gridx = 2;
		gbl.setConstraints(additiveNoiseSlider, gbc);
		add(additiveNoiseSlider);

		gbc.gridy = 3;
		gbc.gridx = 0;
		gbl.setConstraints(subtractiveNoiseLabel, gbc);
		add(subtractiveNoiseLabel);

		gbc.gridx = 1;
		gbc.anchor = GridBagConstraints.LINE_START;
		gbl.setConstraints(subtractiveNoiseTextField, gbc);
		add(subtractiveNoiseTextField);
		gbc.anchor = GridBagConstraints.CENTER;

		gbc.gridx = 2;
		gbl.setConstraints(subtractiveNoiseSlider, gbc);
		add(subtractiveNoiseSlider);

		gbc.gridy = 4;
		gbc.gridx = 0;
		gbl.setConstraints(learningThresholdLabel, gbc);
		add(learningThresholdLabel);

		gbc.gridx = 1;
		gbc.anchor = GridBagConstraints.LINE_START;
		gbl.setConstraints(learningThresholdTextField, gbc);
		add(learningThresholdTextField);
		gbc.anchor = GridBagConstraints.CENTER;

		gbc.gridx = 2;
		gbl.setConstraints(learningThresholdSlider, gbc);
		add(learningThresholdSlider);

		gbc.gridy = 5;
		gbc.gridx = 0;
		gbl.setConstraints(logLabel, gbc);
		add(logLabel);

		gbc.gridx = 1;
		gbc.gridwidth = 2;
		gbl.setConstraints(logTextField, gbc);
		add(logTextField);
		gbc.gridwidth = 1;

		gbc.gridx = 3;
		gbl.setConstraints(logButton, gbc);
		add(logButton);

		gbc.gridy = 6;
		gbc.gridx = 3;
		gbc.insets = new Insets(25, 0, 0, 0);
		gbl.setConstraints(preprocessButton, gbc);
		add(preprocessButton);

		gbc.gridy = 7;
		gbc.gridx = 3;
		gbc.insets = new Insets(0, 0, 0, 0);
		gbl.setConstraints(processButton, gbc);
		add(processButton);
	}

	/**
	 * Convenience method to disable all elements.
	 */
	private void disablePanel() {
		logButton.setEnabled(false);
		logTextField.setEnabled(false);

		preprocessButton.setEnabled(false);
		processButton.setEnabled(false);

		utteranceButton.setEnabled(false);
		utteranceTextField.setEnabled(false);

		additiveNoiseTextField.setEnabled(false);
		additiveNoiseSlider.setEnabled(false);

		subtractiveNoiseTextField.setEnabled(false);
		subtractiveNoiseSlider.setEnabled(false);

		imageDBTextField.setEnabled(false);
		imageDBButton.setEnabled(false);

		learningThresholdTextField.setEnabled(false);
		learningThresholdSlider.setEnabled(false);
	}
}
