/////////////////////////////////////////////////////////////////////////////
// Name:        test_mod_midi_config_gui.cpp
// Author:      Cesar Mauri Loba
// Copyright:   (C) 2011 Cesar Mauri Loba - CREA Software Systems
//
//  This program is free software: you can redistribute it and/or modify
//  it under the terms of the GNU General Public License as published by
//  the Free Software Foundation, either version 3 of the License, or
//  (at your option) any later version.
//
//  This program 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 General Public License for more details.
//
//  You should have received a copy of the GNU General Public License
//  along with this program.  If not, see <http://www.gnu.org/licenses/>.
/////////////////////////////////////////////////////////////////////////////

#include "spcore/coreruntime.h"
#include "testcommon/testcommon.h"
#include "3rdparty/nvwa/debug_new.h"
#include "spcore/basictypes.h"
#include "mod_midi/midi_types.h"

#if defined(__WXGTK__) || defined(__WXMOTIF__) || defined(__WXX11__)
	// Include Xlib for latter use on main
	#include <X11/Xlib.h>
#endif

//#include <wx/msgdlg.h>
#include <wx/frame.h>
#include <wx/panel.h>
#include <wx/sizer.h>
#include <stdio.h>
//#include <wx/init.h>
#include <wx/button.h>
#include <wx/dialog.h>

using namespace spcore;
using namespace mod_midi;

/*
	Check threads enabled
*/
#if !wxUSE_THREADS
     #error "This program requires thread support."
#endif // wxUSE_THREADS


/*
	dialogue to held the config dialogue
*/
class ConfigDialog : public wxDialog
{
public:
	ConfigDialog(wxWindow* parent) {
		Create (parent, wxID_ANY, _T(""));
		m_midi_gui= getSpCoreRuntime()->CreateComponent("midi_config_gui","mcg", 0, NULL);
		if (m_midi_gui.get()== NULL) ExitErr("cannot create midi_config_gui");

		// Request panel
		wxWindow* panel= m_midi_gui->GetGUI(this);

		wxBoxSizer* sizer= new wxBoxSizer(wxVERTICAL);
		SetSizer(sizer);
		sizer->Add (panel, 0, wxALIGN_CENTER_HORIZONTAL|wxALL, 0);
		GetSizer()->SetSizeHints(this);
		SetTitle (panel->GetName());
		Layout();
		Fit();
	}
private:
	SmartPtr<IComponent> m_midi_gui;

	//DECLARE_EVENT_TABLE()
};

/*
	ConfigFrame event table

BEGIN_EVENT_TABLE(ConfigDialog, wxDialog)
//	EVT_CLOSE	( ConfigDialog::OnCloseWindow )
//	EVT_SIZE	( ConfigDialog::OnSize )
END_EVENT_TABLE()
*/

/*
	main frame class
*/
class MyFrame : public wxFrame
{
public:
    MyFrame();
	~MyFrame() {
	}

private:
	void OnTestButton( wxCommandEvent& event );
	void OnConfigButton( wxCommandEvent& event );

    // any class wishing to process wxWidgets events must use this macro
    DECLARE_EVENT_TABLE()
};

#define ID_TEST_BUTTON 10020
#define ID_CONFIG_BUTTON 10021

/*
	myframe event table
*/
BEGIN_EVENT_TABLE(MyFrame, wxFrame)
	EVT_BUTTON	( ID_TEST_BUTTON, MyFrame::OnTestButton )
	EVT_BUTTON	( ID_CONFIG_BUTTON, MyFrame::OnConfigButton )
END_EVENT_TABLE()


// ----------------------------------------------------------------------------
// main frame
// ----------------------------------------------------------------------------
MyFrame::MyFrame()
: wxFrame(NULL, wxID_ANY, _T(""), wxDefaultPosition, wxDefaultSize, wxCAPTION|wxSYSTEM_MENU|wxCLOSE_BOX)
{
	wxBoxSizer* sizer= new wxBoxSizer(wxHORIZONTAL);
	SetSizer(sizer);
	wxButton* itemButtonTest= new wxButton( this, ID_TEST_BUTTON , _T("Test"), wxDefaultPosition, wxDefaultSize, 0 );
	sizer->Add(itemButtonTest, 0, wxALIGN_CENTER_VERTICAL|wxALL, 0);
	wxButton* itemButtonConfig= new wxButton( this, ID_CONFIG_BUTTON , _T("Config"), wxDefaultPosition, wxDefaultSize, 0 );
	sizer->Add(itemButtonConfig, 0, wxALIGN_CENTER_VERTICAL|wxALL, 0);
	GetSizer()->SetSizeHints(this);
}

void MyFrame::OnTestButton( wxCommandEvent& )
{
	SmartPtr<IComponent> midiOut= getSpCoreRuntime()->CreateComponent ("midi_out", "mo", 0, NULL);
	if (midiOut.get()== NULL) ExitErr("error creating component mod_out");

	SmartPtr<CTypeMIDIMessage> msg= CTypeMIDIMessage::CreateInstance();
	if (msg.get()== NULL) ExitErr("cannot create midi message");

	if (midiOut->Initialize()!= 0) ExitErr("error initializing midi_out component");

	// Play scale
	for (unsigned char note= 40; note< 60; ++note) {
		msg->SetNoteOn (0, note, 127);
		IComponent::FindInputPin(*midiOut, "message")->Send(msg);
		sleep_milliseconds(100);
		msg->SetNoteOff (0, note, 127);
		IComponent::FindInputPin(*midiOut, "message")->Send(msg);
	}

	// Change instrument
	msg->SetProgramChange (0, 16);
	IComponent::FindInputPin(*midiOut, "message")->Send(msg);

	// Play scale
	for (unsigned char note= 40; note< 60; ++note) {
		msg->SetNoteOn (0, note, 127);
		IComponent::FindInputPin(*midiOut, "message")->Send(msg);
		sleep_milliseconds(100);
		msg->SetNoteOff (0, note, 127);
		IComponent::FindInputPin(*midiOut, "message")->Send(msg);
	}

	midiOut->Finish();
}

void MyFrame::OnConfigButton( wxCommandEvent& )
{
	ConfigDialog cfgDlg(this);

	cfgDlg.ShowModal();
}

// ----------------------------------------------------------------------------
// main
// ----------------------------------------------------------------------------

int main(int argc, char *argv[]) {

#if defined(__WXGTK__) || defined(__WXMOTIF__) || defined(__WXX11__)
	// Under X11 it's necessary enable threading support
	if ( XInitThreads() == 0 ) {
		ExitErr("Unable to initialize multithreaded X11 code (XInitThreads failed)");
		exit( EXIT_FAILURE );
	}
#endif

	// Initialize spcore
	ICoreRuntime* cr= getSpCoreRuntime();
	if (!cr) return false;

	// Load module
	if (cr->LoadModule("mod_midi")!= 0)
		ExitErr("error loading mod_midi");

	if (cr->InitGUISupport (argc, argv))
		ExitErr("wxEntryStart failed");

	MyFrame* mf= new MyFrame();
	mf->Show();

	// Run wxWidgets message pump
	cr->RunMessageLoop ();

	// GUI cleanup
	cr->CleanupGUISupport();

	// Free spcore
	freeSpCoreRuntime();

	// If execution reaches this => all tests ok
	return 0;
}
