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

  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...
//[/Headers]

#include "MainComponent.h"


//[MiscUserDefs] You can add your own user definitions and misc code here...
//[/MiscUserDefs]

//==============================================================================
MainComponent::MainComponent ()
    : m_TextEditor(new TextEditor),
      m_sharedAudioDeviceManager(nullptr),
      m_AudioDeviceSelectorComponent(new AudioDeviceSelectorComponent (getSharedAudioDeviceManager(), 0, 256, 0, 256, true, true, true, false)),
      m_pReceiver(new Receiver(this)),
      m_pTransmitter(new Transmitter()),
      m_ControlComponent(new ControlComponent(m_pReceiver, m_pTransmitter)), m_log(this),
      m_pReceiverControl(m_pReceiver)
	  , Thread("Receiver")

{
    addAndMakeVisible (tabbedComponent = new TabbedComponent (TabbedButtonBar::TabsAtTop));
    tabbedComponent->setTabBarDepth (38);
    tabbedComponent->setCurrentTabIndex (-1);

    addAndMakeVisible (m_pIQPlaneComponent = new IQPlaneComponent (256));
    m_pIQPlaneComponent->setName ("IQPlaneComponent");

    addAndMakeVisible (m_pGraphComponent = new GraphComponent());
    m_pGraphComponent->setName ("GraphComponent");


    //[UserPreSize]
    //[/UserPreSize]

    setSize (1280, 1024);


    //[Constructor] You can add your own custom stuff here..
	m_samplerate = 48000;
	m_pTransmitterControl = m_pTransmitter;

	m_TextEditor->setMultiLine (true);
    m_TextEditor->setReturnKeyStartsNewLine (true);
    m_TextEditor->setReadOnly (true);
    m_TextEditor->setScrollbarsShown (true);
    m_TextEditor->setCaretVisible (false);
    m_TextEditor->setPopupMenuEnabled (true);
	m_TextEditor->setFont(juce::Font(juce::Font::getDefaultMonospacedFontName(), 12, juce::Font::plain));

	tabbedComponent->addTab (TRANS("Control"), Colours::lightgrey, m_ControlComponent, false);
	tabbedComponent->addTab (TRANS("Messages"), Colours::lightgrey, m_TextEditor, false);
    tabbedComponent->addTab (TRANS("Audio-Settings"), Colours::lightgrey, m_AudioDeviceSelectorComponent, false);
	m_pReceiver->addDataListener(this);
	m_pReceiver->addStatusListener(m_ControlComponent);
	m_pReceiver->addStatusListener(m_pIQPlaneComponent);
	m_pReceiver->addStatusListener(m_pGraphComponent);

	getSharedAudioDeviceManager().addChangeListener (this);
	getSharedAudioDeviceManager().addAudioCallback (this);
	startTimer (1000 / 20);
    //[/Constructor]
}

MainComponent::~MainComponent()
{
    //[Destructor_pre]. You can add your own custom destruction code here..
	stopThread(1000);
	stopTimer();
	getSharedAudioDeviceManager().removeAudioCallback (this);
	getSharedAudioDeviceManager().removeChangeListener (this);
	m_AudioDeviceSelectorComponent = nullptr;
    //[/Destructor_pre]

    tabbedComponent = nullptr;
    m_pIQPlaneComponent = nullptr;
    m_pGraphComponent = nullptr;


    //[Destructor]. You can add your own custom destruction code here..
	m_sharedAudioDeviceManager = nullptr;
    //[/Destructor]
}

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

    g.fillAll (Colours::white);

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

void MainComponent::resized()
{
    tabbedComponent->setBounds (8, 8, 800, 1000);
    m_pIQPlaneComponent->setBounds (848, 48, 400, 400);
    m_pGraphComponent->setBounds (848, 544, 400, 400);
    //[UserResized] Add your own custom resize handling here..
    //[/UserResized]
}



//[MiscUserCode] You can add your own definitions of your custom methods or any other code here...
void MainComponent::changeListenerCallback (ChangeBroadcaster*)
{
//    dumpDeviceInfo();
}

// Thread
void MainComponent::run()
{
	while(!threadShouldExit())
	{
		const RVec &data = m_rxBuf.read();

		m_pReceiver->processPassband(data, data.size());
	}
}

void MainComponent::audioDeviceIOCallback (const float** inputChannelData,
                                int numInputChannels,
                                float** outputChannelData,
                                int numOutputChannels,
                                int numSamples)
{
	const ScopedLock sl (m_lock);
	(void) numInputChannels;
	(void) numOutputChannels;

	Map<RVec> rf((RealScalar*)inputChannelData[0], numSamples);
	m_pTransmitterControl->getData(outputChannelData[0], numSamples);
//	m_pReceiver->processPassband(rf, numSamples);
	m_rxBuf.write(rf, numSamples);

}

void MainComponent::audioDeviceAboutToStart (AudioIODevice* device)
{
	int bufferSize = device->getCurrentBufferSizeSamples();
	m_rxBuf.resize(bufferSize);
	m_samplerate = (float)device->getCurrentSampleRate();

	m_pTransmitterControl->setBuffersize(bufferSize);
	m_pTransmitterControl->setSamplerate(m_samplerate);

	m_pReceiver->setBufSize(bufferSize);
	m_pReceiverControl->setSamplerate(m_samplerate);
	startThread();
}

void MainComponent::audioDeviceStopped()
{
}

AudioDeviceManager& MainComponent::getSharedAudioDeviceManager()
{
    if (m_sharedAudioDeviceManager == nullptr)
    {
        m_sharedAudioDeviceManager = new AudioDeviceManager();
        m_sharedAudioDeviceManager->initialise (2, 2, 0, true, String::empty, 0);
    }

    return *m_sharedAudioDeviceManager;
}

void MainComponent::timerCallback()
{
	if (m_pIQPlaneComponent == nullptr)
		return;

	m_pIQPlaneComponent->repaint();
	m_pGraphComponent->repaint();
}
//[/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 ChangeListener, public AudioIODeviceCallback, public ReceiverDataListener, public LogHandler, public Timer"
                 constructorParams="" variableInitialisers="m_TextEditor(new TextEditor),&#10;m_sharedAudioDeviceManager(nullptr),&#10;m_AudioDeviceSelectorComponent(new AudioDeviceSelectorComponent (getSharedAudioDeviceManager(), 0, 256, 0, 256, true, true, true, false)),&#10;m_pReceiver(new Receiver(this)),&#10;m_pTransmitter(new Transmitter()),&#10;m_ControlComponent(new ControlComponent(m_pReceiver, m_pTransmitter)), m_log(this),&#10;m_pReceiverControl(m_pReceiver)&#10;"
                 snapPixels="8" snapActive="1" snapShown="1" overlayOpacity="0.330"
                 fixedSize="1" initialWidth="1280" initialHeight="1024">
  <BACKGROUND backgroundColour="ffffffff"/>
  <TABBEDCOMPONENT name="new tabbed component" id="4c02ba4e5ea4fa59" memberName="tabbedComponent"
                   virtualName="" explicitFocusOrder="0" pos="8 8 800 1000" orientation="top"
                   tabBarDepth="38" initialTab="-1"/>
  <GENERICCOMPONENT name="IQPlaneComponent" id="d61ada3176fcc62a" memberName="m_pIQPlaneComponent"
                    virtualName="" explicitFocusOrder="0" pos="848 48 400 400" class="IQPlaneComponent"
                    params="256"/>
  <GENERICCOMPONENT name="GraphComponent" id="c729f8c175157e1e" memberName="m_pGraphComponent"
                    virtualName="" explicitFocusOrder="0" pos="848 544 400 400" class="GraphComponent"
                    params=""/>
</JUCER_COMPONENT>

END_JUCER_METADATA
*/
#endif


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