/***
 * 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/>.
 */

/*
`* This sample is based on demos at Java Neural Index  http://lcn.epfl.ch/tutorial/english/index.html
 * and it is implemented on top of Neuroph neural networks
 */

package org.neuroph.easyneurons.samples.perceptron;

import java.awt.Graphics2D;
import java.awt.Image;
import java.util.Observable;
import java.util.Observer;
import java.util.Vector;
import java.util.concurrent.ConcurrentLinkedQueue;
import org.neuroph.core.Layer;
import org.neuroph.core.Neuron;
import org.neuroph.core.Weight;
import org.neuroph.core.learning.SupervisedTrainingElement;
import org.neuroph.core.learning.TrainingSet;
import org.neuroph.easyneurons.NeuralNetworkTraining;
import org.neuroph.nnet.Perceptron;
import org.neuroph.nnet.comp.ThresholdNeuron;

/**
`* This sample is based on demos at Java Neural Index  http://lcn.epfl.ch/tutorial/english/index.html
 * and it is implemented on top of Neuroph neural networks
 *
 * @author Marko Koprivica
 * @author Zoran Sevarac
 */
public class PerceptronSampleFrame extends javax.swing.JInternalFrame implements Observer {

    protected TruthTablePanel ttPanel;
    protected PatternSpacePanel psPanel;
    protected TrainingPanel tPanel;
    protected ImagePanel iPanel;
    public static final double[][] AND_INPUTS = {{0, 0, 0}, {1, 0, 0}, {0, 1, 0}, {1, 1, 1}};
    Image imageBuffer;
    Graphics2D drawingBuffer;
    Perceptron neuralNetwork;
    NeuralNetworkTraining controller;
    TrainingSet trainingSet = new TrainingSet();
    PerceptronSampleTrainingSet ts = new PerceptronSampleTrainingSet();
    private ConcurrentLinkedQueue<Vector> displayDataBuffer;
    private Thread drawingThread = null;
    private boolean isDrawing = false;

    public PerceptronSampleFrame(NeuralNetworkTraining controler, PerceptronSampleTrainingSet pts) {
        initComponents();
        setTitle("Perceptron Learning Sample");
        setIconifiable(true);
        setClosable(true);

        this.controller = controler;
        this.neuralNetwork = (Perceptron) controller.getNetwork();
        this.displayDataBuffer = new ConcurrentLinkedQueue<Vector>();

        this.ts = pts;
        linkAllToOne();
    }

    public void linkAllToOne() {
        ttPanel = new TruthTablePanel(this, 200, 200);
        psPanel = new PatternSpacePanel(this, 200, 200);
        tPanel = new TrainingPanel(this);
        iPanel = new ImagePanel();

        this.setSize(750, 440);

        ttPanel.setSize(200, 200);
        psPanel.setSize(200, 200);
        tPanel.setSize(350, 240);
        iPanel.setSize(350, 350);


        add(ttPanel);
        add(psPanel);
        add(tPanel);
        add(iPanel);

        iPanel.setLocation(0, 40);
        tPanel.setLocation(350, 200);
        psPanel.setLocation(550, 0);
        ttPanel.setLocation(350, 0);

    }

    @SuppressWarnings("unchecked")
    // <editor-fold defaultstate="collapsed" desc="Generated Code">//GEN-BEGIN:initComponents
    private void initComponents() {

        setDefaultCloseOperation(javax.swing.WindowConstants.DISPOSE_ON_CLOSE);
        setDoubleBuffered(true);
        setMinimumSize(new java.awt.Dimension(750, 400));
        setName("Form"); // NOI18N
        setPreferredSize(new java.awt.Dimension(750, 400));

        javax.swing.GroupLayout layout = new javax.swing.GroupLayout(getContentPane());
        getContentPane().setLayout(layout);
        layout.setHorizontalGroup(
            layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGap(0, 740, Short.MAX_VALUE)
        );
        layout.setVerticalGroup(
            layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGap(0, 365, Short.MAX_VALUE)
        );

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

    public void setTrainingSet() { // ovde treba dodati kod koji cita grafiku
    }
    int q = 0;

    public void update(Observable o, Object arg) {

        Layer l = neuralNetwork.getLayerAt(1);
        Vector<Neuron> v = l.getNeurons();
        Vector<Weight> w = v.get(0).getWeightsVector();

        double ll = ((ThresholdNeuron) neuralNetwork.getLayerAt(1).getNeuronAt(0)).getThresh();
        double w1 = w.get(0).getValue();
        double w2 = w.get(1).getValue();

        double sum = -ll + w1 + w2;
        q++;

        psPanel.updateLine(ll, w1, w2);
        tPanel.updateJProgresBar(q);

        neuralNetwork.getLayerAt(1).getNeurons().get(0).getWeightsVector().get(0).getValue();

        iPanel.setNeuronFields(0, sum, ll, w.get(0).getValue(), w.get(1).getValue());
    }

    // Variables declaration - do not modify//GEN-BEGIN:variables
    // End of variables declaration//GEN-END:variables
    public void buttonHasChanged(int index, double value) {
        outputs[index][0] = value;
        psPanel.updatePoints();
    }

    //TrainingPanel button pressed tran
    public void train(double learningRate, double maxError, int maxIterations) {
        if (!trainingSet.isEmpty()) {
            trainingSet.clear();
        }

        trainingSet.addElement(new SupervisedTrainingElement(new double[]{0, 0}, outputs[0]));
        trainingSet.addElement(new SupervisedTrainingElement(new double[]{1, 0}, outputs[1]));
        trainingSet.addElement(new SupervisedTrainingElement(new double[]{0, 1}, outputs[2]));
        trainingSet.addElement(new SupervisedTrainingElement(new double[]{1, 1}, outputs[3]));

        controller.setTrainingSet(trainingSet);

        ts.setTrainingSet(trainingSet, null, null);
        controller.setStepDRParams(learningRate, maxError, maxIterations);

        controller.train();

        q = tPanel.setJProgresBar();
        z = 0;
    }

    public void step() {
    }

    public void stopTraining() {
        controller.stopTraining();
    }

    public void randomize() {
        controller.randomize();
        tPanel.setJProgresBar();
    }
    int z = 0;

    public void test() {
        if (z > 3) {
            z = 0;
        }
        switch (z) {
            case 0:
                controller.setInput("0 0");
                iPanel.setInputFields(new double[]{0, 0});
                break;
            case 1:
                controller.setInput("1 0");
                iPanel.setInputFields(new double[]{1, 0});
                break;
            case 2:
                controller.setInput("0 1");
                iPanel.setInputFields(new double[]{0, 1});
                break;
            case 3:
                controller.setInput("1 1");
                iPanel.setInputFields(new double[]{1, 1});
                break;
        }

        double sum = neuralNetwork.getOutput().firstElement();

        iPanel.setOutputField(sum);

        z++;
    }
    public double[][] outputs = {{0}, {0}, {0}, {0}};
}






