#include "testcommon/testcommon.h"
#include "spcore/basictypes.h"
#include "spcore/pinimpl.h"

using namespace spcore;
using namespace std;

class CExampleComponent : public spcore::CComponentAdapter
{
public:
	CExampleComponent(const char *name, int argc, const char * argv[])
	: CComponentAdapter(name, argc, argv)
	{
		m_data= 0;
		m_iPin1= SmartPtr<IInputPin>(new CInputPin1("i_pin1", *this), false);
		m_oPin1= CTypeInt::CreateOutputPin ("o_pin");
		if (RegisterInputPin(*m_iPin1)!= 0) exit (-1);
		if (RegisterOutputPin (*m_oPin1)!= 0) exit (-1);
	}
	~CExampleComponent() { }
	const char* GetTypeName(void) const { return "CExampleComponent"; }

private:
	// Listener
	class CInputPin1 : public CInputPinWriteOnly<CTypeInt, CExampleComponent> {
	public:
		CInputPin1 (const char * name, CExampleComponent & component) : CInputPinWriteOnly<CTypeInt, CExampleComponent>(name, component) {}
		virtual int DoSend(const CTypeInt & message) {
			cout << "CInputPin1: " << message.getValue() << endl;
			return 0;
		}
	};

	int m_data;
	SmartPtr<IInputPin> m_iPin1;
	SmartPtr<IOutputPin> m_oPin1;

//public:
/*
	void DoTest()
	{
		m_oPin1->Attach (*m_iPin1);
		CTypeInt* i= CTypeInt::CreateInstance();
		assert (i);
		i->setValue(12);
		m_oPin1->Send (*i);
		i->Release();
	}
	*/
};
/*
void TestContainer()
{
	Container* cont= new Container("my_cont");
	cont->DoTest();

	IIterator<IInputPin*>* ii= cont->GetInputPins();
	for (ii->First(); !ii->IsDone(); ii->Next()) {
		IInputPin* ip= ii->CurrentItem();
		cout << "Input pin: " << ip->GetName() << " TypeID: " << ip->GetTypeID() << " Type name: " << ip->GetTypeName() << endl;
	}
	ii->Release();


	IIterator<IOutputPin*>* io= cont->GetOutputPins();
	for (io->First(); !io->IsDone(); io->Next()) {
		IOutputPin* op= io->CurrentItem();
		cout << "Input pin: " << op->GetName() << " TypeID: " << op->GetTypeID() << " Type name: " << op->GetTypeName() << endl;
	}
	io->Release();

	delete cont;
}
*/

class CCompositeComponent : public CCompositeComponentAdapter
{
public:
	CCompositeComponent(const char* name, int argc, const char * argv[])
	: CCompositeComponentAdapter(name, argc, argv) {}
};

void DoTest()
{
	ICoreRuntime* core= getSpCoreRuntime();
	if (!core) exit (-1);

	// Root container component
	SmartPtr<IComponent> ag= core->CreateComponent("component_composer", "test_composer", 0, NULL);

	// Trying to register a new component should work
	SmartPtr<IComponent> compo(new CExampleComponent("exemple", 0, NULL), false);
	if (ag->AddChild(compo)!= 0) exit (-1);

	// Trying to register again the same component should fail
	if (ag->AddChild(compo)== 0) exit (-1);

	// Trying to register a new component with the same name shouldn't fail
	SmartPtr<IComponent> tmpCont (new CExampleComponent("my_cont", 0, NULL), false);
	if (ag->AddChild(tmpCont)!= 0) exit (-1);

	// Trying to register a new component should work
	SmartPtr<IComponent> adder= core->CreateComponent("iadd", "firstAdder", 0, NULL);
	if (!adder.get()) exit (-1);
	if (ag->AddChild(adder)!= 0) exit (-1);

	// Dump root component status
	DumpComponent (*ag);


	/*
	// Attach pins by number
	//retval= mgr->Attach (adder, (unsigned int) 0, cont, (unsigned int) 0); assert (retval== 0);
	retval= mgr->Attach (adder, "result", cont, "my_in_pin"); assert (retval== 0);

	// Obtain adder input pins for testing
	IteratorPtr<IInputPin*> it(adder->GetInputPins());
	it->First();
	CInputPin* iPinA= static_cast<CInputPin*>(it->CurrentItem());
	it->Next(); assert (!it->IsDone());
	CInputPin* iPinB= static_cast<CInputPin*>(it->CurrentItem());
	CTypeInt *myInt= CTypeInt::CreateInstance(); assert (myInt);

	// Perform addition
	myInt->setValue(5);
	//iPinB->GetListener()->Update(*myInt);
	iPinB->Update(*myInt);
	myInt->setValue(3);
	//iPinA->GetListener()->Update(*myInt);
	iPinA->Update(*myInt);


	myInt->Release();
	*/

}


int main (int, char**)
{
	DoTest();

	// Cleanup
	spcore::freeSpCoreRuntime();

	return 0;
}
