/*
 * TrainingSetEditFrame.java
 *
 * Created on October 17, 2008, 9:16 PM
 */

package org.neuroph.easyneurons;

import java.awt.Component;
import java.util.Iterator;
import java.util.Vector;

import javax.swing.JTable;
import javax.swing.event.TableModelEvent;
import javax.swing.event.TableModelListener;
import javax.swing.table.DefaultTableCellRenderer;
import javax.swing.table.TableColumn;

import org.jdesktop.application.Action;
import org.neuroph.core.learning.SupervisedTrainingElement;
import org.neuroph.core.learning.TrainingElement;
import org.neuroph.core.learning.TrainingSet;
import org.neuroph.easyneurons.dialog.TrainingDataFileDialog;


/**
 * 
 * @author Zoran Sevarac <sevarac@gmail.com>
 */
public class TrainingSetEditFrame extends javax.swing.JInternalFrame {
	private TrainingSet trainingSet;
	private TrainingSetTableModel tableModel;
	private EasyNeuronsApplicationView mainFrame;
	private String trainingSetType;
	private int inputs, outputs;
    private String trainingSetLabel;

	public TrainingSetEditFrame(EasyNeuronsApplicationView mainFrame,
			TrainingSet trainingSet, String type, int inputs, int outputs) {
		this.mainFrame = mainFrame;
		this.trainingSetType = type;
		this.trainingSet = trainingSet;
		this.inputs = inputs;
		this.outputs = outputs;
		this.tableModel = new TrainingSetTableModel(inputs, outputs);
		tableModel.addTableModelListener(new TrainingSetEditFrame.InteractiveTableModelListener());

		initComponents();

		if (!tableModel.hasEmptyRow()) {
			tableModel.addEmptyRow();
		}		
	        trainingSetTable.setSurrendersFocusOnKeystroke(true);
			
		 TableColumn hidden = trainingSetTable.getColumnModel().getColumn(tableModel.HIDDEN_INDEX);
		 hidden.setMinWidth(2);
		 hidden.setPreferredWidth(2);
		 hidden.setMaxWidth(2);
		 hidden.setCellRenderer(new InteractiveRenderer(tableModel.HIDDEN_INDEX));	

        this.trainingSetLabel = trainingSet.getLabel();
		this.traningSetLabelTextField.setText(this.trainingSetLabel);
		this.trainingSetTable.getTableHeader().setReorderingAllowed(false);

	}

	public TrainingSetEditFrame(EasyNeuronsApplicationView mainFrame,
			TrainingSet trainingSet) {
		this.mainFrame = mainFrame;
		this.trainingSet = trainingSet;
		this.tableModel = new TrainingSetTableModel(trainingSet);
		tableModel.addTableModelListener(new TrainingSetEditFrame.InteractiveTableModelListener());
		
		initComponents();

		if (!tableModel.hasEmptyRow()) {
			tableModel.addEmptyRow();
		}		
		trainingSetTable.setSurrendersFocusOnKeystroke(true);
	
		 TableColumn hidden = trainingSetTable.getColumnModel().getColumn(tableModel.HIDDEN_INDEX);
		 hidden.setMinWidth(2);
		 hidden.setPreferredWidth(2);
		 hidden.setMaxWidth(2);
		 hidden.setCellRenderer(new InteractiveRenderer(tableModel.HIDDEN_INDEX));		

 		this.trainingSetLabel = trainingSet.getLabel();
		this.traningSetLabelTextField.setText(this.trainingSetLabel);

		if (trainingSet.trainingElements().size() > 0) {
			TrainingElement trainingElement = (TrainingElement) trainingSet
					.trainingElements().firstElement();
			if (trainingElement instanceof SupervisedTrainingElement) {
				this.trainingSetType = "Supervised";
				this.inputs = trainingElement.getInput().size();
				this.outputs = ((SupervisedTrainingElement) trainingElement)
						.getDesiredOutput().size();
			} else {
				this.trainingSetType = "Unsupervised";
				this.outputs = 0;
				this.inputs = trainingElement.getInput().size();
			}
		}

	}

	/**
	 * This method is called from within the constructor to initialize the form.
	 * WARNING: Do NOT modify this code. The content of this method is always
	 * regenerated by the Form Editor.
	 */
	@SuppressWarnings("unchecked")
	// <editor-fold defaultstate="collapsed"
    // <editor-fold defaultstate="collapsed" desc="Generated Code">//GEN-BEGIN:initComponents
    private void initComponents() {
        java.awt.GridBagConstraints gridBagConstraints;

        tablePopupMenu = new javax.swing.JPopupMenu();
        addRowMenuItem = new javax.swing.JMenuItem();
        delRowMenuItem = new javax.swing.JMenuItem();
        namePanel = new javax.swing.JPanel();
        jLabel1 = new javax.swing.JLabel();
        traningSetLabelTextField = new javax.swing.JTextField();
        buttonPanel = new javax.swing.JPanel();
        okButton = new javax.swing.JButton();
        addRowButton = new javax.swing.JButton();
        loadButton = new javax.swing.JButton();
        cancelButton = new javax.swing.JButton();
        helpButton = new javax.swing.JButton();
        tableScrollPane = new javax.swing.JScrollPane();
        trainingSetTable = new javax.swing.JTable();

        tablePopupMenu.setName("tablePopupMenu"); // NOI18N

        javax.swing.ActionMap actionMap = org.jdesktop.application.Application.getInstance(org.neuroph.easyneurons.EasyNeuronsApplication.class).getContext().getActionMap(TrainingSetEditFrame.class, this);
        addRowMenuItem.setAction(actionMap.get("addtableRow")); // NOI18N
        addRowMenuItem.setName("addRowMenuItem"); // NOI18N
        tablePopupMenu.add(addRowMenuItem);

        delRowMenuItem.setAction(actionMap.get("deleteTableRow")); // NOI18N
        delRowMenuItem.setName("delRowMenuItem"); // NOI18N
        tablePopupMenu.add(delRowMenuItem);

        setClosable(true);
        setIconifiable(true);
        setMaximizable(true);
        org.jdesktop.application.ResourceMap resourceMap = org.jdesktop.application.Application.getInstance(org.neuroph.easyneurons.EasyNeuronsApplication.class).getContext().getResourceMap(TrainingSetEditFrame.class);
        setTitle(resourceMap.getString("Form.title")); // NOI18N
        setName("Form"); // NOI18N

        namePanel.setBackground(resourceMap.getColor("namePanel.background")); // NOI18N
        namePanel.setName("namePanel"); // NOI18N
        namePanel.setLayout(new java.awt.GridBagLayout());

        jLabel1.setText(resourceMap.getString("jLabel1.text")); // NOI18N
        jLabel1.setName("jLabel1"); // NOI18N
        gridBagConstraints = new java.awt.GridBagConstraints();
        gridBagConstraints.insets = new java.awt.Insets(10, 10, 10, 5);
        namePanel.add(jLabel1, gridBagConstraints);

        traningSetLabelTextField.setColumns(30);
        traningSetLabelTextField.setText(resourceMap.getString("traningSetLabelTextField.text")); // NOI18N
        traningSetLabelTextField.setName("traningSetLabelTextField"); // NOI18N
        gridBagConstraints = new java.awt.GridBagConstraints();
        gridBagConstraints.fill = java.awt.GridBagConstraints.HORIZONTAL;
        gridBagConstraints.anchor = java.awt.GridBagConstraints.WEST;
        gridBagConstraints.insets = new java.awt.Insets(10, 5, 10, 10);
        namePanel.add(traningSetLabelTextField, gridBagConstraints);

        getContentPane().add(namePanel, java.awt.BorderLayout.NORTH);

        buttonPanel.setName("buttonPanel"); // NOI18N

        okButton.setAction(actionMap.get("save")); // NOI18N
        okButton.setText(resourceMap.getString("okButton.text")); // NOI18N
        okButton.setName("okButton"); // NOI18N
        buttonPanel.add(okButton);

        addRowButton.setAction(actionMap.get("addtableRow")); // NOI18N
        addRowButton.setText(resourceMap.getString("addRowButton.text")); // NOI18N
        addRowButton.setName("addRowButton"); // NOI18N
        buttonPanel.add(addRowButton);

        loadButton.setAction(actionMap.get("showLoadTrainingSetDialog")); // NOI18N
        loadButton.setText(resourceMap.getString("loadButton.text")); // NOI18N
        loadButton.setName("loadButton"); // NOI18N
        buttonPanel.add(loadButton);

        cancelButton.setAction(actionMap.get("cancel")); // NOI18N
        cancelButton.setText(resourceMap.getString("cancelButton.text")); // NOI18N
        cancelButton.setName("cancelButton"); // NOI18N
        buttonPanel.add(cancelButton);

        helpButton.setText(resourceMap.getString("helpButton.text")); // NOI18N
        helpButton.setEnabled(false);
        helpButton.setName("helpButton"); // NOI18N
        buttonPanel.add(helpButton);

        getContentPane().add(buttonPanel, java.awt.BorderLayout.SOUTH);

        tableScrollPane.setName("tableScrollPane"); // NOI18N

        trainingSetTable.setModel(tableModel);
        trainingSetTable.setComponentPopupMenu(tablePopupMenu);
        trainingSetTable.setName("trainingSetTable"); // NOI18N
        tableScrollPane.setViewportView(trainingSetTable);

        getContentPane().add(tableScrollPane, java.awt.BorderLayout.CENTER);

        pack();
    }// </editor-fold>//GEN-END:initComponents

	@Action
	public void cancel() {
		this.dispose();
	}

	@Action
	public void addtableRow() {
		((TrainingSetTableModel) trainingSetTable.getModel()).addEmptyRow();
	}

	@Action
	public void deleteTableRow() {
		//int selected_row = trainingSetTable.getSelectedRow();
		((TrainingSetTableModel) trainingSetTable.getModel())
				.removeRow(trainingSetTable.getSelectedRow());
		
	}

	@Action
	public void save() {
		if (trainingSetTable.isEditing())
		{
			trainingSetTable.getCellEditor().stopCellEditing();
		}

        if (this.traningSetLabelTextField.getText().trim().isEmpty()) {
            javax.swing.JOptionPane.showMessageDialog(this, "Please enter the training set name!");
            return;
        }

		this.trainingSet.setLabel(this.traningSetLabelTextField.getText()
				.trim());
		Vector<Vector> dataVector = this.tableModel.getDataVector();
		Iterator<Vector> iterator = dataVector.iterator();
		this.trainingSet.clear();

		if (this.trainingSetType.equals("Unsupervised")) {
			while (iterator.hasNext()) {
				Vector rowVector = iterator.next();
				Vector<Double> doubleRowVector = new Vector<Double>();
				try {
					for (int i = 0; i < this.inputs; i++) {
						double doubleVal = Double.parseDouble(rowVector
								.elementAt(i).toString());
						doubleRowVector.add(new Double(doubleVal));
					}
				} catch (Exception ex) {
					continue;
				}

				TrainingElement trainingElement = new TrainingElement(
						doubleRowVector);
				this.trainingSet.addElement(trainingElement);
			}
		} else if (this.trainingSetType.equals("Supervised")) {
			while (iterator.hasNext()) {
				Vector rowVector = iterator.next();
				Vector<Double> inputVector = new Vector<Double>();
				Vector<Double> outputVector = new Vector<Double>();

				try {
					for (int i = 0; i < this.inputs; i++) {
						double doubleVal = Double.parseDouble(rowVector
								.elementAt(i).toString());
						inputVector.add(new Double(doubleVal));
					}

					for (int i = 0; i < this.outputs; i++) {
						double doubleVal = Double.parseDouble(rowVector.elementAt(
								this.inputs + i).toString());
						outputVector.add(new Double(doubleVal));
					}
				} catch (Exception ex) {
					continue;
				}

				SupervisedTrainingElement trainingElement = new SupervisedTrainingElement(
						inputVector, outputVector);
				this.trainingSet.addElement(trainingElement);
			}
		}

		this.mainFrame.updateTrainingSets(this.trainingSet);
		this.dispose();

	}
	
     public void highlightLastRow(int row) {
         int lastrow = tableModel.getRowCount();
         if (row == lastrow - 1) {
             trainingSetTable.setRowSelectionInterval(lastrow - 1, lastrow - 1);
         } else {
             trainingSetTable.setRowSelectionInterval(row + 1, row + 1);
         }

         trainingSetTable.setColumnSelectionInterval(0, 0);
     }	
	
     class InteractiveRenderer extends DefaultTableCellRenderer {
         protected int interactiveColumn;

         public InteractiveRenderer(int interactiveColumn) {
             this.interactiveColumn = interactiveColumn;
         }

	 @Override
         public Component getTableCellRendererComponent(JTable table,
            Object value, boolean isSelected, boolean hasFocus, int row,
            int column)
         {
             Component c = super.getTableCellRendererComponent(table, value, isSelected, hasFocus, row, column);
             if (column == interactiveColumn && hasFocus) {
                 if ((TrainingSetEditFrame.this.tableModel.getRowCount() - 1) == row &&
                    !TrainingSetEditFrame.this.tableModel.hasEmptyRow())
                 {
                     TrainingSetEditFrame.this.tableModel.addEmptyRow();
                 }

                 highlightLastRow(row);
             }

             return c;
         }
     }

	public class InteractiveTableModelListener implements TableModelListener {

		public void tableChanged(TableModelEvent evt) {
			if (evt.getType() == TableModelEvent.UPDATE) {
				int column = evt.getColumn();
				int row = evt.getFirstRow();
				// System.out.println("row: " + row + " column: " + column);
				trainingSetTable.setColumnSelectionInterval(column + 1, column + 1);
				trainingSetTable.setRowSelectionInterval(row, row);
			}
		}
	}

    @Action
    public void showLoadTrainingSetDialog() {
        TrainingDataFileDialog dialog = new TrainingDataFileDialog(inputs, outputs, this);
        EasyNeuronsApplication.getApplication().show(dialog);
    }

  public void setTrainingSet(TrainingSet trainingSet)
  {
    this.trainingSet = trainingSet;

    this.tableModel = new TrainingSetTableModel(this.trainingSet);
    this.trainingSetTable.setModel(this.tableModel);
	trainingSetTable.setSurrendersFocusOnKeystroke(true);

	TableColumn hidden = trainingSetTable.getColumnModel().getColumn(tableModel.HIDDEN_INDEX);
	hidden.setMinWidth(2);
	hidden.setPreferredWidth(2);
	hidden.setMaxWidth(2);
	hidden.setCellRenderer(new InteractiveRenderer(tableModel.HIDDEN_INDEX));

    this.tableModel.fireTableDataChanged();

  }

  private void setTableModel() {
 			if (trainingSet.trainingElements().size() > 0) {
			TrainingElement trainingElement = (TrainingElement) trainingSet
					.trainingElements().firstElement();
			if (trainingElement instanceof SupervisedTrainingElement) {
				this.trainingSetType = "Supervised";
				this.inputs = trainingElement.getInput().size();
				this.outputs = ((SupervisedTrainingElement) trainingElement)
						.getDesiredOutput().size();
			} else {
				this.trainingSetType = "Unsupervised";
				this.outputs = 0;
				this.inputs = trainingElement.getInput().size();
			}
		}
  }
     

    // Variables declaration - do not modify//GEN-BEGIN:variables
    private javax.swing.JButton addRowButton;
    private javax.swing.JMenuItem addRowMenuItem;
    private javax.swing.JPanel buttonPanel;
    private javax.swing.JButton cancelButton;
    private javax.swing.JMenuItem delRowMenuItem;
    private javax.swing.JButton helpButton;
    private javax.swing.JLabel jLabel1;
    private javax.swing.JButton loadButton;
    private javax.swing.JPanel namePanel;
    private javax.swing.JButton okButton;
    private javax.swing.JPopupMenu tablePopupMenu;
    private javax.swing.JScrollPane tableScrollPane;
    private javax.swing.JTable trainingSetTable;
    private javax.swing.JTextField traningSetLabelTextField;
    // End of variables declaration//GEN-END:variables

}
