/* -*- mia-c++ -*-
 *
 * This file is part of viewitgui - a library and program for the
 * visualization of 3D data sets. 
 *
 * Copyright (c) Leipzig, Madrid 1999-2013 Mirco Hellmann, Gert Wollny
 *
 * viewitgui 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.
 *
 * viewitgui 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 viewitgui; if not, see <http://www.gnu.org/licenses/>.
 */


#include <viewit/event.hh>
#include <iostream>
using namespace std; 

void CEventInfo::read(istream& is)
{
	is >> __command;
}

void CEventInfo::write(ostream& os)
{
	os << __command << endl; 
}

TEventHandler::~TEventHandler()
{
}

bool TEventHandler::handle_event(event_t *event)
{
	bool handled = false; 
	switch (event->what) {
	case event_t::ev_key: 
		handled = do_handle_key_event(event->action.key);
		break; 
	case event_t::ev_mouse:	
		handled =  do_handle_mouse_event(event->action.button,event->where.x, event->where.y);
		break; 
	case event_t::ev_command:
		handled =  do_handle_command_event(event->info);
		break;
	default:
		return false; 
	}
	if (handled)
		event->what = event_t::ev_nothing; // clean event
	return handled;
}

bool TEventHandler::do_handle_key_event(int key)
{
	return false; 
}
bool TEventHandler::do_handle_mouse_event(int button, int x, int y)
{
	return false; 
}	
bool TEventHandler::do_handle_command_event(PEventInfo info)
{
	return false; 
}	


std::ostream& operator << (std::ostream& os, const event_t& event)
{
	switch (event.what) {
	case event_t::ev_key: 
		os << "ev_key <" << char(event.action.key) << "> "; 
		break; 
	case event_t::ev_mouse:	
		os << "ev_mouse <" <<  event.action.button << " , ( " << event.where.x << ", " << event.where.y << ") >"; 
		break; 
	case event_t::ev_command:
		os << "ev_command <" <<  event.info->get_command() << "> ";
		break;
	case event_t::ev_nothing:
		os << "ev_nothing <> ";
		break;
	default:
		os << "ev_unknown "; 
	}
	return os; 
}






/// event queue

bool CEventQueue::handle_events()
{
	bool handled = false; 
	while (! __ev_queue.empty()) {
		
		// get the next event
		event_t event = __ev_queue.front(); 
		__ev_queue.pop();

		if (!__signal_handle_event.empty()) 
			handled = __signal_handle_event.emit(&event);

		if (!handled) {
			switch (event.what) {
			case event_t::ev_key:
				if (!__signal_handle_key.empty()) handled = __signal_handle_key.emit(event.action.key);
				break;
				
			case event_t::ev_mouse: 
				if (!__signal_handle_mouse.empty()) handled = __signal_handle_mouse.emit(event.action.button,event.where.x, event.where.y);
				break;
				
			case event_t::ev_command:
				if (!__signal_handle_command.empty()) handled = __signal_handle_command.emit(event.info);
				break;
			default: 
				clog << "received an ev_nothing\n"; 
			}

		}
	}
	if (handled) __sth_handled = true;
	return handled; 
}


void CEventQueue::push(event_t &ev)
{
	__ev_queue.push(ev);
}
	
CEventQueue::type_signal_handle_event CEventQueue::signal_handle_event()
{
	return __signal_handle_event;
}

CEventQueue::type_signal_handle_key CEventQueue::signal_handle_key()
{
	return __signal_handle_key;
}

CEventQueue::type_signal_handle_mouse CEventQueue::signal_handle_mouse()
{
	return __signal_handle_mouse;
}

CEventQueue::type_signal_handle_command CEventQueue::signal_handle_command()
{
	return __signal_handle_command;
}

bool CEventQueue::get_handled() const
{
	return __sth_handled;
}

void CEventQueue::reset_handled()
{
	__sth_handled = false;
}
