/*
  ==============================================================================

  This is an automatically generated GUI class created by the Introjucer!

  Be careful when adding custom code to these files, as only the code within
  the "//[xyz]" and "//[/xyz]" sections will be retained when the file is loaded
  and re-saved.

  Created with Introjucer version: 3.1.0

  ------------------------------------------------------------------------------

  The Introjucer is part of the JUCE library - "Jules' Utility Class Extensions"
  Copyright 2004-13 by Raw Material Software Ltd.

  ==============================================================================
*/

//[Headers] You can add your own extra header files here...
#ifdef WIN32
#include <Windows.h>
#endif
#include <iostream>
#include <Eigen/Dense>
//[/Headers]

#include "MainComponent.h"


//[MiscUserDefs] You can add your own user definitions and misc code here...
#ifdef WIN32
void mylog(const char* format, ...)
{
	char log_buf[257];
    va_list argptr;
    va_start(argptr, format);
    vsprintf(log_buf, format, argptr);
    va_end(argptr);
	OutputDebugStringA (log_buf);
}
#else
void mylog(const char* format, ...)
{
	char log_buf[257];
    va_list argptr;
    va_start(argptr, format);
    vprintf(format, argptr);
    va_end(argptr);
}
#endif

//[/MiscUserDefs]

//==============================================================================
MainComponent::MainComponent ()
    : Thread("RBM"),
      m_layers(this),
      m_pRbm(nullptr),
      DrawTraining(nullptr),
      DrawReconstruction(nullptr),
      DrawWeights(nullptr),
      DrawHidden(nullptr)
{
    addAndMakeVisible (trainButton = new TextButton ("Train button"));
    trainButton->setButtonText (TRANS("Train"));
    trainButton->addListener (this);

    addAndMakeVisible (addButton = new TextButton ("Add button"));
    addButton->setButtonText (TRANS("Add"));
    addButton->addListener (this);

    addAndMakeVisible (patterSlider = new Slider ("Pattern slider"));
    patterSlider->setRange (0, 0, 1);
    patterSlider->setSliderStyle (Slider::LinearHorizontal);
    patterSlider->setTextBoxStyle (Slider::TextBoxLeft, false, 80, 20);
    patterSlider->addListener (this);

    addAndMakeVisible (reconstructButton = new TextButton ("Reconstruct button"));
    reconstructButton->setButtonText (TRANS("Reconstruct"));
    reconstructButton->addListener (this);

    addAndMakeVisible (ShakeButton = new TextButton ("Shake button"));
    ShakeButton->setButtonText (TRANS("Shake"));
    ShakeButton->addListener (this);

    addAndMakeVisible (WeightsSlider = new Slider ("Weights slider"));
    WeightsSlider->setRange (0, 0, 1);
    WeightsSlider->setSliderStyle (Slider::LinearHorizontal);
    WeightsSlider->setTextBoxStyle (Slider::TextBoxLeft, false, 80, 20);
    WeightsSlider->addListener (this);

    addAndMakeVisible (numEpochslabel = new Label ("Num Epochs label",
                                                   TRANS("100")));
    numEpochslabel->setFont (Font (15.00f, Font::plain));
    numEpochslabel->setJustificationType (Justification::centred);
    numEpochslabel->setEditable (true, true, false);
    numEpochslabel->setColour (TextEditor::textColourId, Colours::black);
    numEpochslabel->setColour (TextEditor::backgroundColourId, Colour (0x00000000));
    numEpochslabel->addListener (this);

    addAndMakeVisible (learningRateLabel = new Label ("Learning Rate label",
                                                      TRANS("0.03")));
    learningRateLabel->setFont (Font (15.00f, Font::plain));
    learningRateLabel->setJustificationType (Justification::centred);
    learningRateLabel->setEditable (true, true, false);
    learningRateLabel->setColour (TextEditor::textColourId, Colours::black);
    learningRateLabel->setColour (TextEditor::backgroundColourId, Colour (0x00000000));
    learningRateLabel->addListener (this);

    addAndMakeVisible (testButton = new TextButton ("Test button"));
    testButton->setButtonText (TRANS("Test"));
    testButton->addListener (this);

    addAndMakeVisible (numVisibleLabel = new Label ("Num Visible label",
                                                    TRANS("99999")));
    numVisibleLabel->setFont (Font (15.00f, Font::plain));
    numVisibleLabel->setJustificationType (Justification::centred);
    numVisibleLabel->setEditable (true, true, false);
    numVisibleLabel->setColour (TextEditor::textColourId, Colours::black);
    numVisibleLabel->setColour (TextEditor::backgroundColourId, Colour (0x00000000));
    numVisibleLabel->addListener (this);

    addAndMakeVisible (numHiddenLabel = new Label ("Num Hidden label",
                                                   TRANS("99999")));
    numHiddenLabel->setFont (Font (15.00f, Font::plain));
    numHiddenLabel->setJustificationType (Justification::centred);
    numHiddenLabel->setEditable (true, true, false);
    numHiddenLabel->setColour (TextEditor::textColourId, Colours::black);
    numHiddenLabel->setColour (TextEditor::backgroundColourId, Colour (0x00000000));
    numHiddenLabel->addListener (this);

    addAndMakeVisible (createButton = new TextButton ("Create button"));
    createButton->setButtonText (TRANS("Create"));
    createButton->addListener (this);

    addAndMakeVisible (projectNameLabel = new Label ("Project Name label",
                                                     TRANS("TestPrj")));
    projectNameLabel->setFont (Font (15.00f, Font::plain));
    projectNameLabel->setJustificationType (Justification::centred);
    projectNameLabel->setEditable (true, true, false);
    projectNameLabel->setColour (TextEditor::textColourId, Colours::black);
    projectNameLabel->setColour (TextEditor::backgroundColourId, Colour (0x00000000));
    projectNameLabel->addListener (this);

    addAndMakeVisible (loadButton = new TextButton ("Load button"));
    loadButton->setButtonText (TRANS("Load"));
    loadButton->addListener (this);

    addAndMakeVisible (saveButton = new TextButton ("Save button"));
    saveButton->setButtonText (TRANS("Save"));
    saveButton->addListener (this);

    addAndMakeVisible (numVisibleYLabel = new Label ("Num Visible Y label",
                                                     TRANS("99999")));
    numVisibleYLabel->setFont (Font (15.00f, Font::plain));
    numVisibleYLabel->setJustificationType (Justification::centred);
    numVisibleYLabel->setEditable (true, true, false);
    numVisibleYLabel->setColour (TextEditor::textColourId, Colours::black);
    numVisibleYLabel->setColour (TextEditor::backgroundColourId, Colour (0x00000000));
    numVisibleYLabel->addListener (this);

    addAndMakeVisible (loadTrainingButton = new TextButton ("Load Training button"));
    loadTrainingButton->setButtonText (TRANS("Load T"));
    loadTrainingButton->addListener (this);

    addAndMakeVisible (saveTrainingButton = new TextButton ("Save Training button"));
    saveTrainingButton->setButtonText (TRANS("Save T"));
    saveTrainingButton->addListener (this);

    addAndMakeVisible (clearTrainingButton = new TextButton ("Clear Training button"));
    clearTrainingButton->setButtonText (TRANS("Clear T"));
    clearTrainingButton->addListener (this);

    addAndMakeVisible (removeTrainingButton = new TextButton ("Remove Training button"));
    removeTrainingButton->setButtonText (TRANS("Remove T"));
    removeTrainingButton->addListener (this);

    addAndMakeVisible (numGibbsSlider = new Slider ("Num. Gibbs slider"));
    numGibbsSlider->setRange (1, 10, 1);
    numGibbsSlider->setSliderStyle (Slider::LinearHorizontal);
    numGibbsSlider->setTextBoxStyle (Slider::TextBoxLeft, false, 80, 20);
    numGibbsSlider->addListener (this);

    addAndMakeVisible (reconstructEquButton = new TextButton ("Reconstruct Equilibrium button"));
    reconstructEquButton->setButtonText (TRANS("Reconst Equ."));
    reconstructEquButton->addListener (this);

    addAndMakeVisible (rbmUseExpectationsToggleButton = new ToggleButton ("rbmUseExpectations toggle button"));
    rbmUseExpectationsToggleButton->setButtonText (TRANS("Use Expectations"));
    rbmUseExpectationsToggleButton->addListener (this);

    addAndMakeVisible (rbmDoRaoBlackwellToggleButton = new ToggleButton ("rbmDoRaoBlackwell toggle button"));
    rbmDoRaoBlackwellToggleButton->setButtonText (TRANS("Rao-Blackwell"));
    rbmDoRaoBlackwellToggleButton->addListener (this);

    addAndMakeVisible (rbmDoRobbinsMonroToggleButton = new ToggleButton ("rbmDoRobbinsMonro toggle button"));
    rbmDoRobbinsMonroToggleButton->setButtonText (TRANS("Robbins-Monro"));
    rbmDoRobbinsMonroToggleButton->addListener (this);

    addAndMakeVisible (rbmReduceVarianceToggleButton = new ToggleButton ("rbmReduceVariance toggle button"));
    rbmReduceVarianceToggleButton->setButtonText (TRANS("Reduce Variance"));
    rbmReduceVarianceToggleButton->addListener (this);

    addAndMakeVisible (lambdaLabel = new Label ("Lambda label",
                                                TRANS("1.0")));
    lambdaLabel->setFont (Font (15.00f, Font::plain));
    lambdaLabel->setJustificationType (Justification::centred);
    lambdaLabel->setEditable (true, true, false);
    lambdaLabel->setColour (TextEditor::textColourId, Colours::black);
    lambdaLabel->setColour (TextEditor::backgroundColourId, Colour (0x00000000));
    lambdaLabel->addListener (this);

    addAndMakeVisible (sigmaLabel = new Label ("Sigma label",
                                               TRANS("0.5")));
    sigmaLabel->setFont (Font (15.00f, Font::plain));
    sigmaLabel->setJustificationType (Justification::centred);
    sigmaLabel->setEditable (true, true, false);
    sigmaLabel->setColour (TextEditor::textColourId, Colours::black);
    sigmaLabel->setColour (TextEditor::backgroundColourId, Colour (0x00000000));
    sigmaLabel->addListener (this);

    addAndMakeVisible (rbmUseVisibleGaussianToggleButton = new ToggleButton ("rbmUseVisibleGaussian toggle button"));
    rbmUseVisibleGaussianToggleButton->setButtonText (TRANS("Use gaussian visible"));
    rbmUseVisibleGaussianToggleButton->addListener (this);

    addAndMakeVisible (rbmDoSparseToggleButton = new ToggleButton ("rbmDoSparse toggle button"));
    rbmDoSparseToggleButton->setButtonText (TRANS("Do sparse"));
    rbmDoSparseToggleButton->addListener (this);

    addAndMakeVisible (sparsityLabel = new Label ("Sparsity label",
                                                  TRANS("0.05")));
    sparsityLabel->setFont (Font (15.00f, Font::plain));
    sparsityLabel->setJustificationType (Justification::centred);
    sparsityLabel->setEditable (true, true, false);
    sparsityLabel->setColour (TextEditor::textColourId, Colours::black);
    sparsityLabel->setColour (TextEditor::backgroundColourId, Colour (0x00000000));
    sparsityLabel->addListener (this);

    addAndMakeVisible (sigmaDecayLabel = new Label ("SigmaDecay label",
                                                    TRANS("1.0")));
    sigmaDecayLabel->setFont (Font (15.00f, Font::plain));
    sigmaDecayLabel->setJustificationType (Justification::centred);
    sigmaDecayLabel->setEditable (true, true, false);
    sigmaDecayLabel->setColour (TextEditor::textColourId, Colours::black);
    sigmaDecayLabel->setColour (TextEditor::backgroundColourId, Colour (0x00000000));
    sigmaDecayLabel->addListener (this);

    addAndMakeVisible (m_progressBar = new ProgressBar (m_trainingProgress));
    m_progressBar->setName ("Progress Bar");


    //[UserPreSize]
	m_vNumX = 16;
	m_vNumY = 16;
	m_hNum = 64;
	m_vNumX_next = 16;
	m_vNumY_next = 16;
	m_hNum_next = 64;
	m_numGibbs = 1;
	m_weights.setUnits(m_vNumX*m_vNumY, m_hNum);
	create();

    //[/UserPreSize]

    setSize (800, 600);


    //[Constructor] You can add your own custom stuff here..
    m_trainingProgress = 0;
    m_progressBar->setTextToDisplay("Finished");
    //[/Constructor]
}

MainComponent::~MainComponent()
{
    //[Destructor_pre]. You can add your own custom destruction code here..
    //[/Destructor_pre]

    trainButton = nullptr;
    addButton = nullptr;
    patterSlider = nullptr;
    reconstructButton = nullptr;
    ShakeButton = nullptr;
    WeightsSlider = nullptr;
    numEpochslabel = nullptr;
    learningRateLabel = nullptr;
    testButton = nullptr;
    numVisibleLabel = nullptr;
    numHiddenLabel = nullptr;
    createButton = nullptr;
    projectNameLabel = nullptr;
    loadButton = nullptr;
    saveButton = nullptr;
    numVisibleYLabel = nullptr;
    loadTrainingButton = nullptr;
    saveTrainingButton = nullptr;
    clearTrainingButton = nullptr;
    removeTrainingButton = nullptr;
    numGibbsSlider = nullptr;
    reconstructEquButton = nullptr;
    rbmUseExpectationsToggleButton = nullptr;
    rbmDoRaoBlackwellToggleButton = nullptr;
    rbmDoRobbinsMonroToggleButton = nullptr;
    rbmReduceVarianceToggleButton = nullptr;
    lambdaLabel = nullptr;
    sigmaLabel = nullptr;
    rbmUseVisibleGaussianToggleButton = nullptr;
    rbmDoSparseToggleButton = nullptr;
    sparsityLabel = nullptr;
    sigmaDecayLabel = nullptr;
    m_progressBar = nullptr;


    //[Destructor]. You can add your own custom destruction code here..
    DrawTraining = nullptr;
    DrawReconstruction = nullptr;
    DrawWeights = nullptr;
    DrawHidden = nullptr;
    m_pRbm = nullptr;

    //[/Destructor]
}

//==============================================================================
void MainComponent::paint (Graphics& g)
{
    //[UserPrePaint] Add your own custom painting code here..
    //[/UserPrePaint]

    g.fillAll (Colours::white);

    g.setColour (Colours::black);
    g.setFont (Font (15.00f, Font::plain));
    g.drawText (TRANS("Sigma"),
                32, 306, 80, 14,
                Justification::centred, true);

    g.setColour (Colours::black);
    g.setFont (Font (15.00f, Font::plain));
    g.drawText (TRANS("Lambda"),
                120, 306, 80, 14,
                Justification::centred, true);

    g.setColour (Colours::black);
    g.setFont (Font (15.00f, Font::plain));
    g.drawText (TRANS("Num. epochs"),
                32, 354, 80, 14,
                Justification::centred, true);

    g.setColour (Colours::black);
    g.setFont (Font (15.00f, Font::plain));
    g.drawText (TRANS("Alpha"),
                120, 354, 80, 14,
                Justification::centred, true);

    g.setColour (Colours::black);
    g.setFont (Font (15.00f, Font::plain));
    g.drawText (TRANS("Sparsity"),
                208, 306, 80, 14,
                Justification::centred, true);

    g.setColour (Colours::black);
    g.setFont (Font (15.00f, Font::plain));
    g.drawText (TRANS("Sigma decay"),
                296, 306, 96, 14,
                Justification::centred, true);

    //[UserPaint] Add your own custom painting code here..
    //[/UserPaint]
}

void MainComponent::resized()
{
    trainButton->setBounds (120, 408, 72, 24);
    addButton->setBounds (24, 160, 72, 24);
    patterSlider->setBounds (224, 408, 184, 24);
    reconstructButton->setBounds (24, 408, 72, 24);
    ShakeButton->setBounds (120, 448, 72, 24);
    WeightsSlider->setBounds (224, 448, 184, 24);
    numEpochslabel->setBounds (32, 368, 72, 24);
    learningRateLabel->setBounds (120, 368, 72, 24);
    testButton->setBounds (120, 160, 72, 24);
    numVisibleLabel->setBounds (456, 328, 72, 24);
    numHiddenLabel->setBounds (504, 360, 72, 24);
    createButton->setBounds (504, 392, 72, 24);
    projectNameLabel->setBounds (488, 296, 96, 24);
    loadButton->setBounds (456, 264, 72, 24);
    saveButton->setBounds (536, 264, 72, 24);
    numVisibleYLabel->setBounds (528, 328, 72, 24);
    loadTrainingButton->setBounds (440, 48, 72, 24);
    saveTrainingButton->setBounds (520, 48, 72, 24);
    clearTrainingButton->setBounds (520, 88, 72, 24);
    removeTrainingButton->setBounds (440, 88, 72, 24);
    numGibbsSlider->setBounds (224, 368, 184, 24);
    reconstructEquButton->setBounds (24, 448, 72, 24);
    rbmUseExpectationsToggleButton->setBounds (24, 232, 128, 24);
    rbmDoRaoBlackwellToggleButton->setBounds (24, 200, 112, 24);
    rbmDoRobbinsMonroToggleButton->setBounds (168, 232, 120, 24);
    rbmReduceVarianceToggleButton->setBounds (168, 200, 128, 24);
    lambdaLabel->setBounds (120, 320, 72, 24);
    sigmaLabel->setBounds (32, 320, 72, 24);
    rbmUseVisibleGaussianToggleButton->setBounds (168, 264, 160, 24);
    rbmDoSparseToggleButton->setBounds (24, 264, 128, 24);
    sparsityLabel->setBounds (208, 320, 72, 24);
    sigmaDecayLabel->setBounds (304, 320, 72, 24);
    m_progressBar->setBounds (224, 160, 168, 24);
    //[UserResized] Add your own custom resize handling here..
    DrawTraining->setBounds (16, 16, 100, 100);
    DrawReconstruction->setBounds (110+16, 16, 100, 100);
    DrawWeights->setBounds (220+16, 16, 100, 100);
    DrawHidden->setBounds (16, 16+110, 320, 20);
    //[/UserResized]
}

void MainComponent::buttonClicked (Button* buttonThatWasClicked)
{
    //[UserbuttonClicked_Pre]
    //[/UserbuttonClicked_Pre]

    if (buttonThatWasClicked == trainButton)
    {
        //[UserButtonCode_trainButton] -- add your button handler code here..
//    	m_pRbm->train(m_layers, numEpochslabel->getText().getIntValue(), learningRateLabel->getText().getFloatValue(), m_numGibbs);
    	startThread();
    	redrawReconstruction();
    	redrawWeights((int)WeightsSlider->getValue());
        //[/UserButtonCode_trainButton]
    }
    else if (buttonThatWasClicked == addButton)
    {
        //[UserButtonCode_addButton] -- add your button handler code here..
		DrawReconstruction->setData(DrawTraining->getData());
		m_layers.add(&DrawTraining->getData(), m_vNumX*m_vNumY);
		patterSlider->setRange (0, m_layers.getSize()-1, 1);
        //[/UserButtonCode_addButton]
    }
    else if (buttonThatWasClicked == reconstructButton)
    {
        //[UserButtonCode_reconstructButton] -- add your button handler code here..
    	redrawReconstruction();
        //[/UserButtonCode_reconstructButton]
    }
    else if (buttonThatWasClicked == ShakeButton)
    {
        //[UserButtonCode_ShakeButton] -- add your button handler code here..
    	m_weights.shuffle(0.01);
    	redrawReconstruction();
    	redrawWeights((int)WeightsSlider->getValue());
        //[/UserButtonCode_ShakeButton]
    }
    else if (buttonThatWasClicked == testButton)
    {
        //[UserButtonCode_testButton] -- add your button handler code here..
		DrawTraining->setData(DrawReconstruction->getData());
		redrawReconstruction();
        //[/UserButtonCode_testButton]
    }
    else if (buttonThatWasClicked == createButton)
    {
        //[UserButtonCode_createButton] -- add your button handler code here..
		m_vNumX = m_vNumX_next;
		m_vNumY = m_vNumY_next;
		m_hNum = m_hNum_next;
		m_weights.setUnits(m_vNumX*m_vNumY, m_hNum);
		create();
        //[/UserButtonCode_createButton]
    }
    else if (buttonThatWasClicked == loadButton)
    {
        //[UserButtonCode_loadButton] -- add your button handler code here..
		load();
		redrawReconstruction();
    	redrawWeights((int)WeightsSlider->getValue());
        //[/UserButtonCode_loadButton]
    }
    else if (buttonThatWasClicked == saveButton)
    {
        //[UserButtonCode_saveButton] -- add your button handler code here..
		save();
        //[/UserButtonCode_saveButton]
    }
    else if (buttonThatWasClicked == loadTrainingButton)
    {
        //[UserButtonCode_loadTrainingButton] -- add your button handler code here..
		m_layers.clear();
		m_layers.load((String(getBaseDir() + String(".trainingStates.dat"))).toUTF8());
		redrawReconstruction();
        //[/UserButtonCode_loadTrainingButton]
    }
    else if (buttonThatWasClicked == saveTrainingButton)
    {
        //[UserButtonCode_saveTrainingButton] -- add your button handler code here..
		m_layers.save((String(getBaseDir() + String(".trainingStates.dat"))).toUTF8());
        //[/UserButtonCode_saveTrainingButton]
    }
    else if (buttonThatWasClicked == clearTrainingButton)
    {
        //[UserButtonCode_clearTrainingButton] -- add your button handler code here..
		m_layers.clear();
        //[/UserButtonCode_clearTrainingButton]
    }
    else if (buttonThatWasClicked == removeTrainingButton)
    {
        //[UserButtonCode_removeTrainingButton] -- add your button handler code here..
		m_layers.removeAt((int)patterSlider->getValue());
        //[/UserButtonCode_removeTrainingButton]
    }
    else if (buttonThatWasClicked == reconstructEquButton)
    {
        //[UserButtonCode_reconstructEquButton] -- add your button handler code here..
    	uint32_t i;
    	VectorXd V, H;

    	V = DrawTraining->getData();
    	for (i=0; i < 100; i++)
    	{
        	H = m_pRbm->toHidden(V);
        	DrawHidden->setData(H);
        	V = m_pRbm->toVisible(H);
    		DrawReconstruction->setData(V);
    	}
        //[/UserButtonCode_reconstructEquButton]
    }
    else if (buttonThatWasClicked == rbmUseExpectationsToggleButton)
    {
        //[UserButtonCode_rbmUseExpectationsToggleButton] -- add your button handler code here..
    	m_pRbm->setUseExpectations(buttonThatWasClicked->getToggleState());
        //[/UserButtonCode_rbmUseExpectationsToggleButton]
    }
    else if (buttonThatWasClicked == rbmDoRaoBlackwellToggleButton)
    {
        //[UserButtonCode_rbmDoRaoBlackwellToggleButton] -- add your button handler code here..
    	m_pRbm->setDoRaoBlackwell(buttonThatWasClicked->getToggleState());
        //[/UserButtonCode_rbmDoRaoBlackwellToggleButton]
    }
    else if (buttonThatWasClicked == rbmDoRobbinsMonroToggleButton)
    {
        //[UserButtonCode_rbmDoRobbinsMonroToggleButton] -- add your button handler code here..
    	m_pRbm->setDoRobbinsMonro(buttonThatWasClicked->getToggleState());
        //[/UserButtonCode_rbmDoRobbinsMonroToggleButton]
    }
    else if (buttonThatWasClicked == rbmReduceVarianceToggleButton)
    {
        //[UserButtonCode_rbmReduceVarianceToggleButton] -- add your button handler code here..
    	m_pRbm->setUseProbsForHiddenReconstruction(buttonThatWasClicked->getToggleState());
        //[/UserButtonCode_rbmReduceVarianceToggleButton]
    }
    else if (buttonThatWasClicked == rbmUseVisibleGaussianToggleButton)
    {
        //[UserButtonCode_rbmUseVisibleGaussianToggleButton] -- add your button handler code here..
    	m_pRbm->setUseVisibleGaussian(buttonThatWasClicked->getToggleState());
    	redrawReconstruction();
        //[/UserButtonCode_rbmUseVisibleGaussianToggleButton]
    }
    else if (buttonThatWasClicked == rbmDoSparseToggleButton)
    {
        //[UserButtonCode_rbmDoSparseToggleButton] -- add your button handler code here..
    	m_pRbm->setDoSparse(buttonThatWasClicked->getToggleState());
        //[/UserButtonCode_rbmDoSparseToggleButton]
    }

    //[UserbuttonClicked_Post]
    //[/UserbuttonClicked_Post]
}

void MainComponent::sliderValueChanged (Slider* sliderThatWasMoved)
{
    //[UsersliderValueChanged_Pre]
    //[/UsersliderValueChanged_Pre]

    if (sliderThatWasMoved == patterSlider)
    {
        //[UserSliderCode_patterSlider] -- add your slider handling code here..
		if (m_layers.getSize() > 0)
		{
			VisibleLayer &p = (VisibleLayer&)m_layers.getAt((int)sliderThatWasMoved->getValue());
			DrawReconstruction->setData(p.states());
		}
        //[/UserSliderCode_patterSlider]
    }
    else if (sliderThatWasMoved == WeightsSlider)
    {
        //[UserSliderCode_WeightsSlider] -- add your slider handling code here..
    	redrawWeights((int)sliderThatWasMoved->getValue());
        //[/UserSliderCode_WeightsSlider]
    }
    else if (sliderThatWasMoved == numGibbsSlider)
    {
        //[UserSliderCode_numGibbsSlider] -- add your slider handling code here..
    	m_numGibbs = (uint32_t)sliderThatWasMoved->getValue();
        //[/UserSliderCode_numGibbsSlider]
    }

    //[UsersliderValueChanged_Post]
    //[/UsersliderValueChanged_Post]
}

void MainComponent::labelTextChanged (Label* labelThatHasChanged)
{
    //[UserlabelTextChanged_Pre]
    //[/UserlabelTextChanged_Pre]

    if (labelThatHasChanged == numEpochslabel)
    {
        //[UserLabelCode_numEpochslabel] -- add your label text handling code here..
        //[/UserLabelCode_numEpochslabel]
    }
    else if (labelThatHasChanged == learningRateLabel)
    {
        //[UserLabelCode_learningRateLabel] -- add your label text handling code here..
        //[/UserLabelCode_learningRateLabel]
    }
    else if (labelThatHasChanged == numVisibleLabel)
    {
        //[UserLabelCode_numVisibleLabel] -- add your label text handling code here..
        m_vNumX_next = labelThatHasChanged->getText().getIntValue();
        //[/UserLabelCode_numVisibleLabel]
    }
    else if (labelThatHasChanged == numHiddenLabel)
    {
        //[UserLabelCode_numHiddenLabel] -- add your label text handling code here..
        m_hNum_next = labelThatHasChanged->getText().getIntValue();
        //[/UserLabelCode_numHiddenLabel]
    }
    else if (labelThatHasChanged == projectNameLabel)
    {
        //[UserLabelCode_projectNameLabel] -- add your label text handling code here..
        //[/UserLabelCode_projectNameLabel]
    }
    else if (labelThatHasChanged == numVisibleYLabel)
    {
        //[UserLabelCode_numVisibleYLabel] -- add your label text handling code here..
        m_vNumY_next = labelThatHasChanged->getText().getIntValue();
        //[/UserLabelCode_numVisibleYLabel]
    }
    else if (labelThatHasChanged == lambdaLabel)
    {
        //[UserLabelCode_lambdaLabel] -- add your label text handling code here..
    	m_pRbm->setLambda(labelThatHasChanged->getText().getFloatValue());
    	redrawReconstruction();
        //[/UserLabelCode_lambdaLabel]
    }
    else if (labelThatHasChanged == sigmaLabel)
    {
        //[UserLabelCode_sigmaLabel] -- add your label text handling code here..
    	m_pRbm->setSigma(labelThatHasChanged->getText().getFloatValue());
    	redrawReconstruction();
        //[/UserLabelCode_sigmaLabel]
    }
    else if (labelThatHasChanged == sparsityLabel)
    {
        //[UserLabelCode_sparsityLabel] -- add your label text handling code here..
    	m_pRbm->setSparsity(labelThatHasChanged->getText().getFloatValue());
        //[/UserLabelCode_sparsityLabel]
    }
    else if (labelThatHasChanged == sigmaDecayLabel)
    {
        //[UserLabelCode_sigmaDecayLabel] -- add your label text handling code here..
    	m_pRbm->setSigmaDecay(labelThatHasChanged->getText().getFloatValue());
        //[/UserLabelCode_sigmaDecayLabel]
    }

    //[UserlabelTextChanged_Post]
    //[/UserlabelTextChanged_Post]
}



//[MiscUserCode] You can add your own definitions of your custom methods or any other code here...
void MainComponent::load ()
{
	m_weights.load((String(getBaseDir() + String(".weights.dat"))).toUTF8());

	m_vNumX = m_vNumY = (int)sqrt((float)m_weights.getNumVisible());
	m_hNum = m_weights.getNumHidden();
	create();
}

void MainComponent::save ()
{
	m_weights.save((String(getBaseDir() + String(".weights.dat"))).toUTF8());
}

void MainComponent::create()
{
	DrawTraining = nullptr;
	DrawReconstruction = nullptr;
	DrawWeights = nullptr;
	DrawHidden = nullptr;
	m_pRbm = nullptr;

	WeightsSlider->setRange(0, m_hNum-1, 1);

	addAndMakeVisible (DrawTraining = new DrawComponent (m_vNumX, m_vNumY));
	DrawTraining->setListener(this);
    addAndMakeVisible (DrawReconstruction = new DrawComponent (m_vNumX, m_vNumY));
    addAndMakeVisible (DrawWeights = new DrawComponent (m_vNumX, m_vNumY));
    addAndMakeVisible (DrawHidden = new DrawComponent (m_hNum, 1));
	DrawHidden->setListener(this);
	numVisibleLabel->setText(String(m_vNumX), dontSendNotification );
	numVisibleYLabel->setText(String(m_vNumY), dontSendNotification );
	numHiddenLabel->setText(String(m_hNum), dontSendNotification );

	m_pRbm = new Rbm(m_weights, this);
	m_pRbm->setUseExpectations(rbmUseExpectationsToggleButton->getToggleState());
	m_pRbm->setDoRaoBlackwell(rbmDoRaoBlackwellToggleButton->getToggleState());
	m_pRbm->setDoRobbinsMonro(rbmDoRobbinsMonroToggleButton->getToggleState());
	m_pRbm->setUseProbsForHiddenReconstruction(rbmReduceVarianceToggleButton->getToggleState());
	m_pRbm->setUseVisibleGaussian(rbmUseVisibleGaussianToggleButton->getToggleState());
	m_pRbm->setDoSparse(rbmDoSparseToggleButton->getToggleState());

	m_pRbm->setLambda(lambdaLabel->getText().getFloatValue());
	m_pRbm->setSigma(sigmaLabel->getText().getFloatValue());
	m_pRbm->setSigmaDecay(sigmaDecayLabel->getText().getFloatValue());
	m_pRbm->setSparsity(sparsityLabel->getText().getFloatValue());

	resized();
}

void MainComponent::destroy()
{
}

const juce::String& MainComponent::getBaseDir()
{
	m_baseDir = String("./") + projectNameLabel->getText();

	return m_baseDir;

}

void MainComponent::onChanged(const LayerArray<VisibleLayer> &obj)
{
	patterSlider->setRange(0, std::max(0,(int)m_layers.getSize()-1), 1);
}

void MainComponent::onEpochTrained(const Rbm &obj)
{
	m_trainingProgress = obj.getProgress();
//	mylog("Training %f %%\n", m_trainingProgress*100);
	redrawReconstruction();
	redrawWeights((int)WeightsSlider->getValue());
}

void MainComponent::onDraw(DrawComponent &obj)
{
	if (&obj == DrawHidden)
	{
		DrawReconstruction->setData(m_pRbm->toVisible(obj.getData()));
	}
	if (&obj == DrawTraining)
	{
		DrawReconstruction->setData(m_pRbm->toVisible(m_pRbm->toHidden(obj.getData())));
    	DrawHidden->setData(m_pRbm->toHidden(obj.getData()));
	}
}

void MainComponent::redrawReconstruction()
{
	DrawHidden->setData(m_pRbm->toHidden(DrawTraining->getData()));
	DrawReconstruction->setData(m_pRbm->toVisible(DrawHidden->getData()));
}

void MainComponent::redrawWeights(int index)
{
	VectorXd w = m_weights.weights().col(index);
	VectorXd temp = w;
	double min = +1E12;
	double max = -1E12;

	for (int i=0; i < m_vNumX*m_vNumY; i++)
	{
		min = std::min<double>(min, (double)temp[i]);
		max = std::max<double>(max, (double)temp[i]);
	}
	for (int i=0; i < m_vNumX*m_vNumY; i++)
	{
		temp[i] -= min;
	}
	for (int i=0; i < m_vNumX*m_vNumY; i++)
	{
		temp[i] /= (max-min);
	}

	DrawWeights->setData(temp);
}

void MainComponent::run()
{
	trainButton->setEnabled(false);
	m_progressBar->setPercentageDisplay(true);
	m_pRbm->train(m_layers, numEpochslabel->getText().getIntValue(), learningRateLabel->getText().getFloatValue(), m_numGibbs);
	trainButton->setEnabled(true);
	m_trainingProgress = 0.0;
	m_progressBar->setTextToDisplay("Finished");
}

//[/MiscUserCode]


//==============================================================================
#if 0
/*  -- Introjucer information section --

    This is where the Introjucer stores the metadata that describe this GUI layout, so
    make changes in here at your peril!

BEGIN_JUCER_METADATA

<JUCER_COMPONENT documentType="Component" className="MainComponent" componentName=""
                 parentClasses="public Component, public LayerArrayListener&lt;VisibleLayer&gt;, public RbmListener, public DrawListener, public Thread"
                 constructorParams="" variableInitialisers="Thread(&quot;RBM&quot;),&#10;m_layers(this),&#10;m_pRbm(nullptr)&#10;DrawTraining(nullptr),&#10;DrawReconstruction(nullptr),&#10;DrawWeights(nullptr),&#10;DrawHidden(nullptr)"
                 snapPixels="8" snapActive="1" snapShown="1" overlayOpacity="0.330"
                 fixedSize="1" initialWidth="800" initialHeight="600">
  <BACKGROUND backgroundColour="ffffffff">
    <TEXT pos="32 306 80 14" fill="solid: ff000000" hasStroke="0" text="Sigma"
          fontname="Default font" fontsize="15" bold="0" italic="0" justification="36"/>
    <TEXT pos="120 306 80 14" fill="solid: ff000000" hasStroke="0" text="Lambda"
          fontname="Default font" fontsize="15" bold="0" italic="0" justification="36"/>
    <TEXT pos="32 354 80 14" fill="solid: ff000000" hasStroke="0" text="Num. epochs"
          fontname="Default font" fontsize="15" bold="0" italic="0" justification="36"/>
    <TEXT pos="120 354 80 14" fill="solid: ff000000" hasStroke="0" text="Alpha"
          fontname="Default font" fontsize="15" bold="0" italic="0" justification="36"/>
    <TEXT pos="208 306 80 14" fill="solid: ff000000" hasStroke="0" text="Sparsity"
          fontname="Default font" fontsize="15" bold="0" italic="0" justification="36"/>
    <TEXT pos="296 306 96 14" fill="solid: ff000000" hasStroke="0" text="Sigma decay"
          fontname="Default font" fontsize="15" bold="0" italic="0" justification="36"/>
  </BACKGROUND>
  <TEXTBUTTON name="Train button" id="7909d74b5522987c" memberName="trainButton"
              virtualName="" explicitFocusOrder="0" pos="120 408 72 24" buttonText="Train"
              connectedEdges="0" needsCallback="1" radioGroupId="0"/>
  <TEXTBUTTON name="Add button" id="4609f7b526ec1aef" memberName="addButton"
              virtualName="" explicitFocusOrder="0" pos="24 160 72 24" buttonText="Add"
              connectedEdges="0" needsCallback="1" radioGroupId="0"/>
  <SLIDER name="Pattern slider" id="c3e0a2c816db81d1" memberName="patterSlider"
          virtualName="" explicitFocusOrder="0" pos="224 408 184 24" min="0"
          max="0" int="1" style="LinearHorizontal" textBoxPos="TextBoxLeft"
          textBoxEditable="1" textBoxWidth="80" textBoxHeight="20" skewFactor="1"/>
  <TEXTBUTTON name="Reconstruct button" id="c1901d121a5819d6" memberName="reconstructButton"
              virtualName="" explicitFocusOrder="0" pos="24 408 72 24" buttonText="Reconstruct"
              connectedEdges="0" needsCallback="1" radioGroupId="0"/>
  <TEXTBUTTON name="Shake button" id="7fa4964a9a9ed199" memberName="ShakeButton"
              virtualName="" explicitFocusOrder="0" pos="120 448 72 24" buttonText="Shake"
              connectedEdges="0" needsCallback="1" radioGroupId="0"/>
  <SLIDER name="Weights slider" id="699075a1fc01458a" memberName="WeightsSlider"
          virtualName="" explicitFocusOrder="0" pos="224 448 184 24" min="0"
          max="0" int="1" style="LinearHorizontal" textBoxPos="TextBoxLeft"
          textBoxEditable="1" textBoxWidth="80" textBoxHeight="20" skewFactor="1"/>
  <LABEL name="Num Epochs label" id="b23ae372ee931474" memberName="numEpochslabel"
         virtualName="" explicitFocusOrder="0" pos="32 368 72 24" edTextCol="ff000000"
         edBkgCol="0" labelText="100" editableSingleClick="1" editableDoubleClick="1"
         focusDiscardsChanges="0" fontname="Default font" fontsize="15"
         bold="0" italic="0" justification="36"/>
  <LABEL name="Learning Rate label" id="49611a27914e910d" memberName="learningRateLabel"
         virtualName="" explicitFocusOrder="0" pos="120 368 72 24" edTextCol="ff000000"
         edBkgCol="0" labelText="0.03" editableSingleClick="1" editableDoubleClick="1"
         focusDiscardsChanges="0" fontname="Default font" fontsize="15"
         bold="0" italic="0" justification="36"/>
  <TEXTBUTTON name="Test button" id="a1e6fed732ae7ee1" memberName="testButton"
              virtualName="" explicitFocusOrder="0" pos="120 160 72 24" buttonText="Test"
              connectedEdges="0" needsCallback="1" radioGroupId="0"/>
  <LABEL name="Num Visible label" id="60acd702770b77dd" memberName="numVisibleLabel"
         virtualName="" explicitFocusOrder="0" pos="456 328 72 24" edTextCol="ff000000"
         edBkgCol="0" labelText="99999" editableSingleClick="1" editableDoubleClick="1"
         focusDiscardsChanges="0" fontname="Default font" fontsize="15"
         bold="0" italic="0" justification="36"/>
  <LABEL name="Num Hidden label" id="8a56c0419bd3ce86" memberName="numHiddenLabel"
         virtualName="" explicitFocusOrder="0" pos="504 360 72 24" edTextCol="ff000000"
         edBkgCol="0" labelText="99999" editableSingleClick="1" editableDoubleClick="1"
         focusDiscardsChanges="0" fontname="Default font" fontsize="15"
         bold="0" italic="0" justification="36"/>
  <TEXTBUTTON name="Create button" id="6c71593a581844eb" memberName="createButton"
              virtualName="" explicitFocusOrder="0" pos="504 392 72 24" buttonText="Create"
              connectedEdges="0" needsCallback="1" radioGroupId="0"/>
  <LABEL name="Project Name label" id="b4e855167abdac6b" memberName="projectNameLabel"
         virtualName="" explicitFocusOrder="0" pos="488 296 96 24" edTextCol="ff000000"
         edBkgCol="0" labelText="TestPrj" editableSingleClick="1" editableDoubleClick="1"
         focusDiscardsChanges="0" fontname="Default font" fontsize="15"
         bold="0" italic="0" justification="36"/>
  <TEXTBUTTON name="Load button" id="4e606c77b12e7d11" memberName="loadButton"
              virtualName="" explicitFocusOrder="0" pos="456 264 72 24" buttonText="Load"
              connectedEdges="0" needsCallback="1" radioGroupId="0"/>
  <TEXTBUTTON name="Save button" id="c435e774a51e39bf" memberName="saveButton"
              virtualName="" explicitFocusOrder="0" pos="536 264 72 24" buttonText="Save"
              connectedEdges="0" needsCallback="1" radioGroupId="0"/>
  <LABEL name="Num Visible Y label" id="101a4f77ca2445ba" memberName="numVisibleYLabel"
         virtualName="" explicitFocusOrder="0" pos="528 328 72 24" edTextCol="ff000000"
         edBkgCol="0" labelText="99999" editableSingleClick="1" editableDoubleClick="1"
         focusDiscardsChanges="0" fontname="Default font" fontsize="15"
         bold="0" italic="0" justification="36"/>
  <TEXTBUTTON name="Load Training button" id="c603a32c128de05d" memberName="loadTrainingButton"
              virtualName="" explicitFocusOrder="0" pos="440 48 72 24" buttonText="Load T"
              connectedEdges="0" needsCallback="1" radioGroupId="0"/>
  <TEXTBUTTON name="Save Training button" id="8e665b97490357c4" memberName="saveTrainingButton"
              virtualName="" explicitFocusOrder="0" pos="520 48 72 24" buttonText="Save T"
              connectedEdges="0" needsCallback="1" radioGroupId="0"/>
  <TEXTBUTTON name="Clear Training button" id="b4c148828519c013" memberName="clearTrainingButton"
              virtualName="" explicitFocusOrder="0" pos="520 88 72 24" buttonText="Clear T"
              connectedEdges="0" needsCallback="1" radioGroupId="0"/>
  <TEXTBUTTON name="Remove Training button" id="f0e1d068c39986f3" memberName="removeTrainingButton"
              virtualName="" explicitFocusOrder="0" pos="440 88 72 24" buttonText="Remove T"
              connectedEdges="0" needsCallback="1" radioGroupId="0"/>
  <SLIDER name="Num. Gibbs slider" id="fdd9d5ca4e05e18c" memberName="numGibbsSlider"
          virtualName="" explicitFocusOrder="0" pos="224 368 184 24" min="1"
          max="10" int="1" style="LinearHorizontal" textBoxPos="TextBoxLeft"
          textBoxEditable="1" textBoxWidth="80" textBoxHeight="20" skewFactor="1"/>
  <TEXTBUTTON name="Reconstruct Equilibrium button" id="208a587f5556207" memberName="reconstructEquButton"
              virtualName="" explicitFocusOrder="0" pos="24 448 72 24" buttonText="Reconst Equ."
              connectedEdges="0" needsCallback="1" radioGroupId="0"/>
  <TOGGLEBUTTON name="rbmUseExpectations toggle button" id="62884e37cd027719"
                memberName="rbmUseExpectationsToggleButton" virtualName="" explicitFocusOrder="0"
                pos="24 232 128 24" buttonText="Use Expectations" connectedEdges="0"
                needsCallback="1" radioGroupId="0" state="0"/>
  <TOGGLEBUTTON name="rbmDoRaoBlackwell toggle button" id="7f585de46e182418"
                memberName="rbmDoRaoBlackwellToggleButton" virtualName="" explicitFocusOrder="0"
                pos="24 200 112 24" buttonText="Rao-Blackwell" connectedEdges="0"
                needsCallback="1" radioGroupId="0" state="0"/>
  <TOGGLEBUTTON name="rbmDoRobbinsMonro toggle button" id="21974def5fe90b46"
                memberName="rbmDoRobbinsMonroToggleButton" virtualName="" explicitFocusOrder="0"
                pos="168 232 120 24" buttonText="Robbins-Monro" connectedEdges="0"
                needsCallback="1" radioGroupId="0" state="0"/>
  <TOGGLEBUTTON name="rbmReduceVariance toggle button" id="1636f6389abe9225"
                memberName="rbmReduceVarianceToggleButton" virtualName="" explicitFocusOrder="0"
                pos="168 200 128 24" buttonText="Reduce Variance" connectedEdges="0"
                needsCallback="1" radioGroupId="0" state="0"/>
  <LABEL name="Lambda label" id="c51a5dfb587390b4" memberName="lambdaLabel"
         virtualName="" explicitFocusOrder="0" pos="120 320 72 24" edTextCol="ff000000"
         edBkgCol="0" labelText="1.0" editableSingleClick="1" editableDoubleClick="1"
         focusDiscardsChanges="0" fontname="Default font" fontsize="15"
         bold="0" italic="0" justification="36"/>
  <LABEL name="Sigma label" id="68d7dad32ed357f8" memberName="sigmaLabel"
         virtualName="" explicitFocusOrder="0" pos="32 320 72 24" edTextCol="ff000000"
         edBkgCol="0" labelText="0.5" editableSingleClick="1" editableDoubleClick="1"
         focusDiscardsChanges="0" fontname="Default font" fontsize="15"
         bold="0" italic="0" justification="36"/>
  <TOGGLEBUTTON name="rbmUseVisibleGaussian toggle button" id="c89b32a4deaa7f19"
                memberName="rbmUseVisibleGaussianToggleButton" virtualName=""
                explicitFocusOrder="0" pos="168 264 160 24" buttonText="Use gaussian visible"
                connectedEdges="0" needsCallback="1" radioGroupId="0" state="0"/>
  <TOGGLEBUTTON name="rbmDoSparse toggle button" id="ed3f2602ab35b5f2" memberName="rbmDoSparseToggleButton"
                virtualName="" explicitFocusOrder="0" pos="24 264 128 24" buttonText="Do sparse"
                connectedEdges="0" needsCallback="1" radioGroupId="0" state="0"/>
  <LABEL name="Sparsity label" id="f4efe44dc0ca4894" memberName="sparsityLabel"
         virtualName="" explicitFocusOrder="0" pos="208 320 72 24" edTextCol="ff000000"
         edBkgCol="0" labelText="0.05" editableSingleClick="1" editableDoubleClick="1"
         focusDiscardsChanges="0" fontname="Default font" fontsize="15"
         bold="0" italic="0" justification="36"/>
  <LABEL name="SigmaDecay label" id="d5f2f5fffdafd926" memberName="sigmaDecayLabel"
         virtualName="" explicitFocusOrder="0" pos="304 320 72 24" edTextCol="ff000000"
         edBkgCol="0" labelText="1.0" editableSingleClick="1" editableDoubleClick="1"
         focusDiscardsChanges="0" fontname="Default font" fontsize="15"
         bold="0" italic="0" justification="36"/>
  <GENERICCOMPONENT name="Progress Bar" id="548820d4a30574c7" memberName="m_progressBar"
                    virtualName="" explicitFocusOrder="0" pos="224 160 168 24" class="ProgressBar"
                    params="m_trainingProgress"/>
</JUCER_COMPONENT>

END_JUCER_METADATA
*/
#endif


//[EndFile] You can add extra defines here...
//[/EndFile]
