/////////////////////////////////////////////////////////////////////////////
// File:        mod_hid.cpp
// Author:      Cesar Mauri Loba (cesar at crea-si dot com)
// 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/component.h"
#include "spcore/module.h"
#include "spcore/libimpexp.h"
#include "spcore/basictypes.h"

#include "mousecontrol.h"

using namespace spcore;

namespace mod_hid {

/**
	mouse_output component

		Send mouse events.
		
	Input pins:
		left_click (any)	- Perform left click when message received.
		right_click (any)	- Perform right click when message received.
		middle_click (any)	- Perform middle click when message received.
	
	Ouput pins:		

	Command line:
*/
class MouseOutput : public CComponentAdapter {
public:
	static const char* getTypeName() { return "mouse_output"; }
	virtual const char* GetTypeName() const { return MouseOutput::getTypeName(); }
	MouseOutput(const char * name, int argc, const char * argv[]) 
	: CComponentAdapter(name, argc, argv)
	{
		//m_opinElapsed= CTypeInt::CreateOutputPin("elapsed");
		//if (RegisterOutputPin(*m_opinElapsed)!= 0)
		//	throw std::runtime_error("error registering output pin");

		if (RegisterInputPin(*SmartPtr<IInputPin>(new InputPinClick("left_click", *this, MouseOutput::LEFT_CLICK), false))!= 0)
			throw std::runtime_error("error creating input pin left_click");

		if (RegisterInputPin(*SmartPtr<IInputPin>(new InputPinClick("right_click", *this, MouseOutput::RIGHT_CLICK), false))!= 0)
			throw std::runtime_error("error creating input pin right_click");

		if (RegisterInputPin(*SmartPtr<IInputPin>(new InputPinClick("middle_click", *this, MouseOutput::MIDDLE_CLICK), false))!= 0)
			throw std::runtime_error("error creating input pin middle_click");
	}

	enum EClickType { LEFT_CLICK= 0, RIGHT_CLICK= 1, MIDDLE_CLICK= 2 } ;

private:
	virtual ~MouseOutput() {}

	class InputPinClick : public CInputPinWriteOnly<CTypeAny, MouseOutput> {
	public:
		InputPinClick (const char * name, MouseOutput & component, MouseOutput::EClickType ct)
		: CInputPinWriteOnly<CTypeAny, MouseOutput>(name, component) 
		, m_clickType(ct) 
		{			
		}

		virtual int DoSend(const CTypeAny & ) {
			switch (m_clickType) {
				case MouseOutput::LEFT_CLICK:
					this->m_component->m_mouseControl.LeftClick();
					break;
				case MouseOutput::RIGHT_CLICK:
					this->m_component->m_mouseControl.RightClick();
					break;
				case MouseOutput::MIDDLE_CLICK:
					this->m_component->m_mouseControl.MiddleClick();
					break;
				default:
					assert(false);
			}
			return 0;
		}

	private:
		MouseOutput::EClickType m_clickType;
	};

	//
	// Data members
	//
	//SmartPtr<IOutputPin> m_opinElapsed;
	CMouseControl m_mouseControl;
	
};

typedef ComponentFactory<MouseOutput> MouseOutputFactory;

/* ******************************************************************************
	hid  module
****************************************************************************** */
class HidModule : public CModuleAdapter {
public:
	HidModule() {
		//
		// components
		//
		RegisterComponentFactory(SmartPtr<spcore::IComponentFactory>(new MouseOutputFactory(), false));
	}

	~HidModule() {
	}

	virtual const char * GetName() const { return "mod_hid"; }
};

static spcore::IModule* g_module= NULL;
SPEXPORT_FUNCTION spcore::IModule* module_create_instance()
{
	if (g_module== NULL) g_module= new HidModule();
	return g_module;
}

};
