/***
 * Neuroph  http://neuroph.sourceforge.net
 * Copyright by Neuroph Project (C) 2008
 *
 * This file is part of Neuroph framework.
 *
 * Neuroph is free software; you can redistribute it and/or modify
 * it under the terms of the GNU Lesser General Public License as published by
 * the Free Software Foundation; either version 3 of the License, or
 * (at your option) any later version.
 *
 * Neuroph is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public License
 * along with Neuroph. If not, see <http://www.gnu.org/licenses/>.
 */

package org.neuroph.easyneurons.imgrec;

import java.awt.Dimension;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.StringTokenizer;
import java.util.Vector;

import javax.imageio.ImageIO;
import javax.swing.ImageIcon;
import javax.swing.JFileChooser;
import javax.swing.JOptionPane;
import javax.swing.filechooser.FileFilter;

import org.jdesktop.application.Action;
import org.neuroph.contrib.imgrec.ColorMode;
import org.neuroph.contrib.imgrec.FractionRgbData;
import org.neuroph.contrib.imgrec.ImageRecognitionHelper;
import org.neuroph.contrib.imgrec.ImageRecognitionPlugin;
import org.neuroph.core.NeuralNetwork;
import org.neuroph.core.learning.TrainingElement;
import org.neuroph.core.learning.TrainingSet;
import org.neuroph.easyneurons.EasyNeuronsApplicationView;
import org.neuroph.easyneurons.dialog.ComboItem;
import org.neuroph.util.TransferFunctionType;
import org.neuroph.util.VectorParser;
import java.text.DecimalFormat;
import java.text.NumberFormat;


/**
 * This class is GUI for image recognition
 * @author Jon Tait
 * @author Zoran Sevarac <sevarac@gmail.com>
 */
public class ImageRecognitionFrame extends javax.swing.JInternalFrame {   
    int imageWidth=8, imageHeight=8;
    String networkLabel, trainingSetLabel;
    Vector<Integer> hiddenLayersNeuronsCount;
    TransferFunctionType transferFunctionType;
    double learningRate, momentum;
    String imageDir, junkDir;

    Dimension samplingResolution;
    ColorMode colorMode;
    // image data
    Map<String, FractionRgbData> rgbDataMap;
    List<String> imageLabels;

    NeuralNetwork activeNeuralNetwork;
    TrainingSet activeTrainingSet;

    EasyNeuronsApplicationView mainFrame;

    boolean imageDataLoaded = false;

    JFileChooser imageDirFileChooser = new JFileChooser(new File("."));
    JFileChooser junkDirFileChooser = new JFileChooser(new File("."));
    JFileChooser testImageFileChooser = new JFileChooser(new File("."));


    /** Creates new form ImageRecognitionFrame */
    public ImageRecognitionFrame(EasyNeuronsApplicationView mainFrame) {
        initComponents();
        imageDirFileChooser.setFileSelectionMode(JFileChooser.DIRECTORIES_ONLY);
        junkDirFileChooser.setFileSelectionMode(JFileChooser.DIRECTORIES_ONLY);
        testImageFileChooser.setFileSelectionMode(JFileChooser.FILES_ONLY);
        testImageFileChooser.setFileFilter(new FileFilter() {
                        @Override
			public boolean accept(File f) {
				if(f.isDirectory()) {
					return true;
				}
				String name = f.getName();
				if(name.endsWith(".png") || name.endsWith(".PNG") ||
						name.endsWith(".jpg") || name.endsWith(".JPG")) {
					return true;
				}
				return false;
			}
                        @Override
			public String getDescription() {
				// TODO Auto-generated method stub
				return null;
			}
		});
        
        fillTransferFunctionCombo();

        colorRadioButton.setActionCommand("FullColor");
        bwRadioButton.setActionCommand("BlackAndWhite");
        
        this.mainFrame = mainFrame;


    }

    /** 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" desc="Generated Code">//GEN-BEGIN:initComponents
    private void initComponents() {
        java.awt.GridBagConstraints gridBagConstraints;

        colorModeButtonGroup = new javax.swing.ButtonGroup();
        jTabbedPane1 = new javax.swing.JTabbedPane();
        imageTrainingSetPanel = new javax.swing.JPanel();
        chooseImagesPanel = new javax.swing.JPanel();
        jLabel1 = new javax.swing.JLabel();
        jLabel2 = new javax.swing.JLabel();
        imageDirField = new javax.swing.JTextField();
        junkDirField = new javax.swing.JTextField();
        chooseImageDirButton = new javax.swing.JButton();
        chooseJunkDirButton = new javax.swing.JButton();
        samplingResolutionPanel = new javax.swing.JPanel();
        jLabel6 = new javax.swing.JLabel();
        jLabel7 = new javax.swing.JLabel();
        imageWidthField = new javax.swing.JTextField();
        imageHeightField = new javax.swing.JTextField();
        trainingSetPanel = new javax.swing.JPanel();
        jLabel3 = new javax.swing.JLabel();
        trainingSetLabelField = new javax.swing.JTextField();
        buttonPanel1 = new javax.swing.JPanel();
        applyImagesButton = new javax.swing.JButton();
        nextButton = new javax.swing.JButton();
        resetButton = new javax.swing.JButton();
        colorModePanel = new javax.swing.JPanel();
        colorRadioButton = new javax.swing.JRadioButton();
        bwRadioButton = new javax.swing.JRadioButton();
        networkPanel = new javax.swing.JPanel();
        networkSettingsPanel = new javax.swing.JPanel();
        layerNeuronCounts = new javax.swing.JTextField();
        jLabel8 = new javax.swing.JLabel();
        jLabel9 = new javax.swing.JLabel();
        transferFunctionCombo = new javax.swing.JComboBox();
        jLabel11 = new javax.swing.JLabel();
        networkLabelField = new javax.swing.JTextField();
        createNetworkButton = new javax.swing.JButton();
        testPanel = new javax.swing.JPanel();
        imagePanel = new javax.swing.JPanel();
        testImageLabel = new javax.swing.JLabel();
        selectImageButton = new javax.swing.JButton();
        testAllButton = new javax.swing.JButton();
        clearButton = new javax.swing.JButton();
        jScrollPane1 = new javax.swing.JScrollPane();
        testResultsTextArea = new javax.swing.JTextArea();

        setClosable(true);
        setIconifiable(true);
        setMaximizable(true);
        setResizable(true);
        org.jdesktop.application.ResourceMap resourceMap = org.jdesktop.application.Application.getInstance(org.neuroph.easyneurons.EasyNeuronsApplication.class).getContext().getResourceMap(ImageRecognitionFrame.class);
        setTitle(resourceMap.getString("Form.title")); // NOI18N
        setName("Form"); // NOI18N
        setPreferredSize(new java.awt.Dimension(480, 311));

        jTabbedPane1.setDoubleBuffered(true);
        jTabbedPane1.setName("jTabbedPane1"); // NOI18N

        imageTrainingSetPanel.setName("imageTrainingSetPanel"); // NOI18N
        imageTrainingSetPanel.setLayout(null);

        chooseImagesPanel.setBorder(javax.swing.BorderFactory.createTitledBorder(resourceMap.getString("chooseImagesPanel.border.title"))); // NOI18N
        chooseImagesPanel.setName("chooseImagesPanel"); // NOI18N
        chooseImagesPanel.setLayout(new java.awt.GridBagLayout());

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

        jLabel2.setText(resourceMap.getString("jLabel2.text")); // NOI18N
        jLabel2.setName("jLabel2"); // NOI18N
        gridBagConstraints = new java.awt.GridBagConstraints();
        gridBagConstraints.gridx = 0;
        gridBagConstraints.gridy = 1;
        gridBagConstraints.anchor = java.awt.GridBagConstraints.WEST;
        gridBagConstraints.insets = new java.awt.Insets(2, 5, 5, 2);
        chooseImagesPanel.add(jLabel2, gridBagConstraints);

        imageDirField.setColumns(35);
        imageDirField.setEditable(false);
        imageDirField.setText(resourceMap.getString("imageDirField.text")); // NOI18N
        imageDirField.setName("imageDirField"); // NOI18N
        gridBagConstraints = new java.awt.GridBagConstraints();
        gridBagConstraints.fill = java.awt.GridBagConstraints.BOTH;
        gridBagConstraints.anchor = java.awt.GridBagConstraints.WEST;
        gridBagConstraints.insets = new java.awt.Insets(5, 2, 2, 2);
        chooseImagesPanel.add(imageDirField, gridBagConstraints);

        junkDirField.setColumns(35);
        junkDirField.setEditable(false);
        junkDirField.setText(resourceMap.getString("junkDirField.text")); // NOI18N
        junkDirField.setName("junkDirField"); // NOI18N
        gridBagConstraints = new java.awt.GridBagConstraints();
        gridBagConstraints.gridx = 1;
        gridBagConstraints.gridy = 1;
        gridBagConstraints.fill = java.awt.GridBagConstraints.BOTH;
        gridBagConstraints.anchor = java.awt.GridBagConstraints.WEST;
        gridBagConstraints.insets = new java.awt.Insets(2, 2, 5, 2);
        chooseImagesPanel.add(junkDirField, gridBagConstraints);

        javax.swing.ActionMap actionMap = org.jdesktop.application.Application.getInstance(org.neuroph.easyneurons.EasyNeuronsApplication.class).getContext().getActionMap(ImageRecognitionFrame.class, this);
        chooseImageDirButton.setAction(actionMap.get("chooseImageDir")); // NOI18N
        chooseImageDirButton.setText(resourceMap.getString("chooseImageDirButton.text")); // NOI18N
        chooseImageDirButton.setName("chooseImageDirButton"); // NOI18N
        gridBagConstraints = new java.awt.GridBagConstraints();
        gridBagConstraints.anchor = java.awt.GridBagConstraints.WEST;
        gridBagConstraints.insets = new java.awt.Insets(5, 2, 2, 5);
        chooseImagesPanel.add(chooseImageDirButton, gridBagConstraints);

        chooseJunkDirButton.setAction(actionMap.get("chooseJunkDir")); // NOI18N
        chooseJunkDirButton.setText(resourceMap.getString("chooseJunkDirButton.text")); // NOI18N
        chooseJunkDirButton.setName("chooseJunkDirButton"); // NOI18N
        gridBagConstraints = new java.awt.GridBagConstraints();
        gridBagConstraints.gridx = 2;
        gridBagConstraints.gridy = 1;
        gridBagConstraints.anchor = java.awt.GridBagConstraints.WEST;
        gridBagConstraints.insets = new java.awt.Insets(2, 2, 5, 5);
        chooseImagesPanel.add(chooseJunkDirButton, gridBagConstraints);

        imageTrainingSetPanel.add(chooseImagesPanel);
        chooseImagesPanel.setBounds(0, 2, 460, 90);

        samplingResolutionPanel.setBorder(javax.swing.BorderFactory.createTitledBorder(resourceMap.getString("samplingResolutionPanel.border.title"))); // NOI18N
        samplingResolutionPanel.setName("samplingResolutionPanel"); // NOI18N

        jLabel6.setText(resourceMap.getString("jLabel6.text")); // NOI18N
        jLabel6.setName("jLabel6"); // NOI18N

        jLabel7.setText(resourceMap.getString("jLabel7.text")); // NOI18N
        jLabel7.setName("jLabel7"); // NOI18N

        imageWidthField.setText(resourceMap.getString("imageWidthField.text")); // NOI18N
        imageWidthField.setName("imageWidthField"); // NOI18N

        imageHeightField.setText(resourceMap.getString("imageHeightField.text")); // NOI18N
        imageHeightField.setName("imageHeightField"); // NOI18N

        javax.swing.GroupLayout samplingResolutionPanelLayout = new javax.swing.GroupLayout(samplingResolutionPanel);
        samplingResolutionPanel.setLayout(samplingResolutionPanelLayout);
        samplingResolutionPanelLayout.setHorizontalGroup(
            samplingResolutionPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGroup(samplingResolutionPanelLayout.createSequentialGroup()
                .addContainerGap()
                .addGroup(samplingResolutionPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
                    .addComponent(jLabel6)
                    .addComponent(jLabel7))
                .addGap(25, 25, 25)
                .addGroup(samplingResolutionPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING, false)
                    .addComponent(imageHeightField)
                    .addComponent(imageWidthField, javax.swing.GroupLayout.DEFAULT_SIZE, 52, Short.MAX_VALUE))
                .addContainerGap(javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))
        );
        samplingResolutionPanelLayout.setVerticalGroup(
            samplingResolutionPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGroup(samplingResolutionPanelLayout.createSequentialGroup()
                .addContainerGap()
                .addGroup(samplingResolutionPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
                    .addComponent(jLabel6)
                    .addComponent(imageWidthField, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE))
                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
                .addGroup(samplingResolutionPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
                    .addComponent(jLabel7)
                    .addComponent(imageHeightField, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE))
                .addContainerGap(javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))
        );

        imageTrainingSetPanel.add(samplingResolutionPanel);
        samplingResolutionPanel.setBounds(0, 90, 144, 100);

        trainingSetPanel.setBorder(javax.swing.BorderFactory.createTitledBorder(resourceMap.getString("trainingSetPanel.border.title"))); // NOI18N
        trainingSetPanel.setName("trainingSetPanel"); // NOI18N

        jLabel3.setText(resourceMap.getString("jLabel3.text")); // NOI18N
        jLabel3.setName("jLabel3"); // NOI18N

        trainingSetLabelField.setText(resourceMap.getString("trainingSetLabelField.text")); // NOI18N
        trainingSetLabelField.setName("trainingSetLabelField"); // NOI18N

        javax.swing.GroupLayout trainingSetPanelLayout = new javax.swing.GroupLayout(trainingSetPanel);
        trainingSetPanel.setLayout(trainingSetPanelLayout);
        trainingSetPanelLayout.setHorizontalGroup(
            trainingSetPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGroup(trainingSetPanelLayout.createSequentialGroup()
                .addContainerGap()
                .addGroup(trainingSetPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
                    .addComponent(trainingSetLabelField, javax.swing.GroupLayout.PREFERRED_SIZE, 154, javax.swing.GroupLayout.PREFERRED_SIZE)
                    .addComponent(jLabel3))
                .addContainerGap(javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))
        );
        trainingSetPanelLayout.setVerticalGroup(
            trainingSetPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGroup(trainingSetPanelLayout.createSequentialGroup()
                .addContainerGap()
                .addComponent(jLabel3)
                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                .addComponent(trainingSetLabelField, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
                .addContainerGap(19, Short.MAX_VALUE))
        );

        imageTrainingSetPanel.add(trainingSetPanel);
        trainingSetPanel.setBounds(270, 90, 190, 100);

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

        applyImagesButton.setAction(actionMap.get("applyImageSettings")); // NOI18N
        applyImagesButton.setText(resourceMap.getString("applyImagesButton.text")); // NOI18N
        applyImagesButton.setName("applyImagesButton"); // NOI18N
        buttonPanel1.add(applyImagesButton);

        nextButton.setAction(actionMap.get("nextButton")); // NOI18N
        nextButton.setText(resourceMap.getString("nextButton.text")); // NOI18N
        nextButton.setEnabled(false);
        nextButton.setName("nextButton"); // NOI18N
        buttonPanel1.add(nextButton);

        resetButton.setAction(actionMap.get("resetImageSettings")); // NOI18N
        resetButton.setText(resourceMap.getString("resetButton.text")); // NOI18N
        resetButton.setName("resetButton"); // NOI18N
        buttonPanel1.add(resetButton);

        imageTrainingSetPanel.add(buttonPanel1);
        buttonPanel1.setBounds(159, 201, 273, 33);

        colorModePanel.setBorder(javax.swing.BorderFactory.createTitledBorder(resourceMap.getString("colorModePanel.border.title"))); // NOI18N
        colorModePanel.setName("colorModePanel"); // NOI18N

        colorModeButtonGroup.add(colorRadioButton);
        colorRadioButton.setSelected(true);
        colorRadioButton.setText(resourceMap.getString("colorRadioButton.text")); // NOI18N
        colorRadioButton.setName("colorRadioButton"); // NOI18N

        colorModeButtonGroup.add(bwRadioButton);
        bwRadioButton.setText(resourceMap.getString("bwRadioButton.text")); // NOI18N
        bwRadioButton.setName("bwRadioButton"); // NOI18N

        javax.swing.GroupLayout colorModePanelLayout = new javax.swing.GroupLayout(colorModePanel);
        colorModePanel.setLayout(colorModePanelLayout);
        colorModePanelLayout.setHorizontalGroup(
            colorModePanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGroup(colorModePanelLayout.createSequentialGroup()
                .addGroup(colorModePanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
                    .addComponent(colorRadioButton)
                    .addComponent(bwRadioButton))
                .addContainerGap(javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))
        );
        colorModePanelLayout.setVerticalGroup(
            colorModePanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGroup(colorModePanelLayout.createSequentialGroup()
                .addContainerGap()
                .addComponent(colorRadioButton)
                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED, 10, Short.MAX_VALUE)
                .addComponent(bwRadioButton)
                .addContainerGap())
        );

        imageTrainingSetPanel.add(colorModePanel);
        colorModePanel.setBounds(150, 90, 120, 100);

        jTabbedPane1.addTab(resourceMap.getString("imageTrainingSetPanel.TabConstraints.tabTitle"), imageTrainingSetPanel); // NOI18N

        networkPanel.setName("networkPanel"); // NOI18N
        networkPanel.setLayout(null);

        networkSettingsPanel.setBorder(javax.swing.BorderFactory.createTitledBorder(resourceMap.getString("networkSettingsPanel.border.title"))); // NOI18N
        networkSettingsPanel.setName("networkSettingsPanel"); // NOI18N
        networkSettingsPanel.setLayout(new java.awt.GridBagLayout());

        layerNeuronCounts.setText(resourceMap.getString("layerNeuronCounts.text")); // NOI18N
        layerNeuronCounts.setName("layerNeuronCounts"); // NOI18N
        gridBagConstraints = new java.awt.GridBagConstraints();
        gridBagConstraints.gridx = 0;
        gridBagConstraints.gridy = 5;
        gridBagConstraints.fill = java.awt.GridBagConstraints.HORIZONTAL;
        gridBagConstraints.insets = new java.awt.Insets(0, 0, 5, 0);
        networkSettingsPanel.add(layerNeuronCounts, gridBagConstraints);

        jLabel8.setText(resourceMap.getString("jLabel8.text")); // NOI18N
        jLabel8.setName("jLabel8"); // NOI18N
        gridBagConstraints = new java.awt.GridBagConstraints();
        gridBagConstraints.gridx = 0;
        gridBagConstraints.gridy = 4;
        gridBagConstraints.insets = new java.awt.Insets(8, 0, 2, 0);
        networkSettingsPanel.add(jLabel8, gridBagConstraints);

        jLabel9.setText(resourceMap.getString("jLabel9.text")); // NOI18N
        jLabel9.setName("jLabel9"); // NOI18N
        gridBagConstraints = new java.awt.GridBagConstraints();
        gridBagConstraints.gridx = 0;
        gridBagConstraints.gridy = 2;
        gridBagConstraints.anchor = java.awt.GridBagConstraints.WEST;
        gridBagConstraints.insets = new java.awt.Insets(8, 0, 2, 0);
        networkSettingsPanel.add(jLabel9, gridBagConstraints);

        transferFunctionCombo.setModel(new javax.swing.DefaultComboBoxModel(new String[] { "Tanh", "Sigmoid" }));
        transferFunctionCombo.setName("transferFunctionCombo"); // NOI18N
        gridBagConstraints = new java.awt.GridBagConstraints();
        gridBagConstraints.gridx = 0;
        gridBagConstraints.gridy = 3;
        gridBagConstraints.anchor = java.awt.GridBagConstraints.WEST;
        gridBagConstraints.insets = new java.awt.Insets(0, 0, 5, 0);
        networkSettingsPanel.add(transferFunctionCombo, gridBagConstraints);

        jLabel11.setText(resourceMap.getString("jLabel11.text")); // NOI18N
        jLabel11.setName("jLabel11"); // NOI18N
        gridBagConstraints = new java.awt.GridBagConstraints();
        gridBagConstraints.gridx = 0;
        gridBagConstraints.gridy = 0;
        gridBagConstraints.anchor = java.awt.GridBagConstraints.WEST;
        gridBagConstraints.insets = new java.awt.Insets(2, 0, 2, 0);
        networkSettingsPanel.add(jLabel11, gridBagConstraints);

        networkLabelField.setText(resourceMap.getString("networkLabelField.text")); // NOI18N
        networkLabelField.setName("networkLabelField"); // NOI18N
        gridBagConstraints = new java.awt.GridBagConstraints();
        gridBagConstraints.gridx = 0;
        gridBagConstraints.gridy = 1;
        gridBagConstraints.fill = java.awt.GridBagConstraints.HORIZONTAL;
        gridBagConstraints.anchor = java.awt.GridBagConstraints.WEST;
        gridBagConstraints.insets = new java.awt.Insets(0, 0, 5, 0);
        networkSettingsPanel.add(networkLabelField, gridBagConstraints);

        networkPanel.add(networkSettingsPanel);
        networkSettingsPanel.setBounds(0, 0, 180, 180);

        createNetworkButton.setAction(actionMap.get("createNewNetwork")); // NOI18N
        createNetworkButton.setText(resourceMap.getString("createNetworkButton.text")); // NOI18N
        createNetworkButton.setName("createNetworkButton"); // NOI18N
        networkPanel.add(createNetworkButton);
        createNetworkButton.setBounds(10, 190, 160, 23);

        jTabbedPane1.addTab(resourceMap.getString("networkPanel.TabConstraints.tabTitle"), networkPanel); // NOI18N

        testPanel.setName("testPanel"); // NOI18N
        testPanel.setLayout(new java.awt.BorderLayout());

        imagePanel.setName("imagePanel"); // NOI18N
        imagePanel.setPreferredSize(new java.awt.Dimension(128, 128));
        imagePanel.setLayout(new org.netbeans.lib.awtextra.AbsoluteLayout());

        testImageLabel.setBackground(resourceMap.getColor("testImageLabel.background")); // NOI18N
        testImageLabel.setText(resourceMap.getString("testImageLabel.text")); // NOI18N
        testImageLabel.setName("testImageLabel"); // NOI18N
        testImageLabel.setPreferredSize(new java.awt.Dimension(64, 64));
        imagePanel.add(testImageLabel, new org.netbeans.lib.awtextra.AbsoluteConstraints(30, 20, -1, -1));

        selectImageButton.setAction(actionMap.get("testImage")); // NOI18N
        selectImageButton.setText(resourceMap.getString("selectImageButton.text")); // NOI18N
        selectImageButton.setName("selectImageButton"); // NOI18N
        imagePanel.add(selectImageButton, new org.netbeans.lib.awtextra.AbsoluteConstraints(0, 120, 120, -1));

        testAllButton.setAction(actionMap.get("testWholeDataSet")); // NOI18N
        testAllButton.setText(resourceMap.getString("testAllButton.text")); // NOI18N
        testAllButton.setName("testAllButton"); // NOI18N
        imagePanel.add(testAllButton, new org.netbeans.lib.awtextra.AbsoluteConstraints(0, 160, 120, -1));

        clearButton.setAction(actionMap.get("clearTestArea")); // NOI18N
        clearButton.setText(resourceMap.getString("clearButton.text")); // NOI18N
        clearButton.setName("clearButton"); // NOI18N
        imagePanel.add(clearButton, new org.netbeans.lib.awtextra.AbsoluteConstraints(0, 190, 120, -1));

        testPanel.add(imagePanel, java.awt.BorderLayout.WEST);

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

        testResultsTextArea.setColumns(20);
        testResultsTextArea.setRows(5);
        testResultsTextArea.setName("testResultsTextArea"); // NOI18N
        jScrollPane1.setViewportView(testResultsTextArea);

        testPanel.add(jScrollPane1, java.awt.BorderLayout.CENTER);

        jTabbedPane1.addTab(resourceMap.getString("testPanel.TabConstraints.tabTitle"), testPanel); // NOI18N

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

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

    @Action
    public void chooseImageDir() {
		int returnVal = imageDirFileChooser.showDialog(null, "Select Directory");
		if(returnVal == JFileChooser.APPROVE_OPTION) {
			imageDirField.setText(imageDirFileChooser.getSelectedFile().getAbsolutePath());

            trainingSetLabelField.setText(imageDirFileChooser.getSelectedFile().getName()+"_data");
        }
    }

    @Action
    public void chooseJunkDir() {
		int returnVal = junkDirFileChooser.showDialog(null, "Select Directory");
		if(returnVal == JFileChooser.APPROVE_OPTION) {
			junkDirField.setText(junkDirFileChooser.getSelectedFile().getAbsolutePath());
        }
    }

    // loads image labels and rgb data
    private void loadImagedata() {
		rgbDataMap = new HashMap<String, FractionRgbData>();
		imageLabels = new ArrayList<String>();
 
		try {
			File labeledImagesDir = new File(imageDir);
			rgbDataMap.putAll(ImagesLoader.getFractionRgbDataForDirectory(labeledImagesDir, samplingResolution));

			for(String imgName : rgbDataMap.keySet()) {
				StringTokenizer st = new StringTokenizer(imgName, "._");
				String imageLabel = st.nextToken();
				if(!imageLabels.contains(imageLabel)) {
					imageLabels.add(imageLabel);
				}
			}
			Collections.sort(imageLabels);
		} catch(IOException ioe) {
			System.err.println("Unable to load images from labeled images dir: '" + imageDir + "'");
			System.err.println(ioe.toString());
		}

        if  ((junkDir!=null)&& (!junkDir.equals("")) ) {
            try {
                File junkImagesDir = new File(junkDir);
                rgbDataMap.putAll(ImagesLoader.getFractionRgbDataForDirectory(junkImagesDir, samplingResolution));
            } catch(IOException ioe) {
                System.err.println("Unable to load images from junk images dir: '" + junkDir + "'");
                System.err.println(ioe.toString());
            }
        }
        
        onImageDataLoad();
    }

    @Action
    public void createNewNetwork() {
        networkLabel = networkLabelField.getText().trim();

        if (networkLabel.equals("")) {
                JOptionPane.showConfirmDialog(  null,
						"Invalid input! Network label must be entered.",
						"Error", JOptionPane.DEFAULT_OPTION);
                return;
        }

        transferFunctionType = TransferFunctionType.valueOf( ((ComboItem)transferFunctionCombo.getSelectedItem()).getValue().toString());
        
        String hiddenLayersStr = layerNeuronCounts.getText().trim();
        if (hiddenLayersStr.equals("")) {
                JOptionPane.showConfirmDialog(  null,
						"Invalid input! Hidden Layers Neuron Counts must be entered.",
						"Error", JOptionPane.DEFAULT_OPTION);
                return;
        }

        try {
               hiddenLayersNeuronsCount = VectorParser.parseInteger(hiddenLayersStr);
        } catch(Exception ex) {
                JOptionPane.showConfirmDialog(  null,
						"Invalid input! Hidden Layers Neuron Counts must be entered as space separated integers.",
						"Error", JOptionPane.DEFAULT_OPTION);
                return;
        }
        
        // create neural network
        activeNeuralNetwork = ImageRecognitionHelper.createNewNeuralNetwork(networkLabel, samplingResolution, colorMode, imageLabels, hiddenLayersNeuronsCount, transferFunctionType);

        mainFrame.addNewNetworkToProject(activeNeuralNetwork);
    }

	private void fillTransferFunctionCombo() {
		transferFunctionCombo.removeAllItems();
		transferFunctionCombo.addItem(new ComboItem("Sigmoid", TransferFunctionType.SIGMOID.toString()));
		transferFunctionCombo.addItem(new ComboItem("Tanh", TransferFunctionType.TANH.toString()));
	}

    private void onImageDataLoad()  {
        imageDataLoaded = true;
        createNetworkButton.setEnabled(true);
        nextButton.setEnabled(true);

        int neurons=0;
        if (imageLabels.size()<12) neurons = 12;
            else neurons = imageLabels.size();

        layerNeuronCounts.setText(Integer.toString(neurons));
        networkLabelField.setText(imageDirFileChooser.getSelectedFile().getName() + "_net");
    }

    @Action
    public void applyImageSettings() {
        imageDir = imageDirField.getText().trim();
        junkDir = junkDirField.getText().trim();

        if (imageDir.equals("")) {
                JOptionPane.showConfirmDialog(  null,
						"Invalid input! Image directory must be selected.",
						"Error", JOptionPane.DEFAULT_OPTION);
                return;
        }

        try {
            imageWidth = Integer.parseInt(imageWidthField.getText().trim());
            imageHeight = Integer.parseInt(imageHeightField.getText().trim());
	} catch (NumberFormatException e) {
        	JOptionPane.showConfirmDialog(  null,
						"Invalid input! Sampling resolution width and height must be integer values.",
						"Error", JOptionPane.DEFAULT_OPTION);
                return;
	}

        
        trainingSetLabel = trainingSetLabelField.getText().trim();
        if (trainingSetLabel.equals("")) {
                JOptionPane.showConfirmDialog(  null,
						"Invalid input! Training set label must be entered.",
						"Error", JOptionPane.DEFAULT_OPTION);
                return;
        }

        String selectedColorMode  = colorModeButtonGroup.getSelection().getActionCommand();
        if (selectedColorMode.equalsIgnoreCase("FullColor")) colorMode = ColorMode.FULL_COLOR;
            else colorMode = ColorMode.BLACK_AND_WHITE;

        samplingResolution = new Dimension(imageWidth, imageHeight);
        
        loadImagedata();

        if (colorMode == ColorMode.FULL_COLOR)
            activeTrainingSet = ImageRecognitionHelper.createTrainingSet(imageLabels, rgbDataMap);
        else
            activeTrainingSet = ImageRecognitionHelper.createBlackAndWhiteTrainingSet(imageLabels, rgbDataMap);

        activeTrainingSet.setLabel(trainingSetLabel);

        mainFrame.updateTrainingSets(activeTrainingSet);
    }

    @Action
    public void resetImageSettings() {
        imageDirField.setText("");
        junkDirField.setText("");
        imageDir = "";
        junkDir = "";
        imageWidth = 8;
        imageHeight = 8;
        imageWidthField.setText("8");
        imageHeightField.setText("8");
        trainingSetLabel = "";
        trainingSetLabelField.setText("");
        networkLabelField.setText("");
        colorMode=null;

        imageDataLoaded = false;
        createNetworkButton.setEnabled(false);
        nextButton.setEnabled(false);
        colorModeButtonGroup.setSelected(colorRadioButton.getModel(), true);

    }

    @Action
    public void testWholeDataSet() {
        testResultsTextArea.setText("");
        Iterator<TrainingElement> iterator = activeTrainingSet.iterator();
        while(iterator.hasNext()) {
            TrainingElement trainingElement = iterator.next();
            activeNeuralNetwork.setInput(trainingElement.getInput());
            activeNeuralNetwork.calculate();
            Vector networkOutput = activeNeuralNetwork.getOutput();
            testResultsTextArea.append(networkOutput.toString() + "\r\n");
        }

    }

    @Action
    public void nextButton() {
        jTabbedPane1.setSelectedIndex(1);
    }

    @Action
    public void testImage() {
            int returnVal = testImageFileChooser.showDialog(null, "Select Image");
            if(returnVal == JFileChooser.APPROVE_OPTION) {
			// ovde uzmi fajl i prikazi rezultat testa
            File imgFile = testImageFileChooser.getSelectedFile();
            try {
                BufferedImage img = ImageIO.read(imgFile);
                testImageLabel.setIcon(new ImageIcon(img));

                ImageRecognitionPlugin imageRecognition = (ImageRecognitionPlugin)activeNeuralNetwork.getPlugin(ImageRecognitionPlugin.IMG_REC_PLUGIN_NAME);
                HashMap<String, Double> output = imageRecognition.recognizeImage(img);

                String outputString = "";
                NumberFormat numberFormat = DecimalFormat.getNumberInstance();
		numberFormat.setMaximumFractionDigits(4);
                Iterator keys = output.keySet().iterator();
                while(keys.hasNext()) {
                    String key = (String)keys.next();
                    outputString += key + " : " + numberFormat.format( output.get(key) ) + "\n";
                }

                testResultsTextArea.setText(outputString);

            } catch (IOException ioe) {
                System.err.println(ioe.getStackTrace());
            }
        }
    }

    @Action
    public void clearTestArea() {
        testResultsTextArea.setText("");
    }


    // Variables declaration - do not modify//GEN-BEGIN:variables
    private javax.swing.JButton applyImagesButton;
    private javax.swing.JPanel buttonPanel1;
    private javax.swing.JRadioButton bwRadioButton;
    private javax.swing.JButton chooseImageDirButton;
    private javax.swing.JPanel chooseImagesPanel;
    private javax.swing.JButton chooseJunkDirButton;
    private javax.swing.JButton clearButton;
    private javax.swing.ButtonGroup colorModeButtonGroup;
    private javax.swing.JPanel colorModePanel;
    private javax.swing.JRadioButton colorRadioButton;
    private javax.swing.JButton createNetworkButton;
    private javax.swing.JTextField imageDirField;
    private javax.swing.JTextField imageHeightField;
    private javax.swing.JPanel imagePanel;
    private javax.swing.JPanel imageTrainingSetPanel;
    private javax.swing.JTextField imageWidthField;
    private javax.swing.JLabel jLabel1;
    private javax.swing.JLabel jLabel11;
    private javax.swing.JLabel jLabel2;
    private javax.swing.JLabel jLabel3;
    private javax.swing.JLabel jLabel6;
    private javax.swing.JLabel jLabel7;
    private javax.swing.JLabel jLabel8;
    private javax.swing.JLabel jLabel9;
    private javax.swing.JScrollPane jScrollPane1;
    private javax.swing.JTabbedPane jTabbedPane1;
    private javax.swing.JTextField junkDirField;
    private javax.swing.JTextField layerNeuronCounts;
    private javax.swing.JTextField networkLabelField;
    private javax.swing.JPanel networkPanel;
    private javax.swing.JPanel networkSettingsPanel;
    private javax.swing.JButton nextButton;
    private javax.swing.JButton resetButton;
    private javax.swing.JPanel samplingResolutionPanel;
    private javax.swing.JButton selectImageButton;
    private javax.swing.JButton testAllButton;
    private javax.swing.JLabel testImageLabel;
    private javax.swing.JPanel testPanel;
    private javax.swing.JTextArea testResultsTextArea;
    private javax.swing.JTextField trainingSetLabelField;
    private javax.swing.JPanel trainingSetPanel;
    private javax.swing.JComboBox transferFunctionCombo;
    // End of variables declaration//GEN-END:variables

}
