/*
 * Nombre: epoll_escucharGeneral/6
 * Argumentos:
 * 		- epollfd (int) (file descriptor de un epoll)
 * 		- uniqueSocket (int) (si no se requiere, poner -1)
 * 		- uniqueHandler (funcion que le pasas epoll_data_t y devuelve void) (si uniqueSocket == -1, poner NULL)
 * 		- normalHandler (funcion que le pasas epoll_data_t y devuelve void) (NECESARIO 100%)
 * 		- closeHandler (funcion que le pasas epoll_data_t y devuelve void) (Puede ser NULL)
 * 		- timeOut cuanto tiempo tarda hasta que se desbloquee
 *
 * Devuelve:
 * 		int (-1 si hay error, 0 si no hubo ninguno).
 *
 * Funcion: Invoca a la funcion epoll_wait y se fija si hubo conexiones en algun file descriptor del epoll.
 * Trata a cada fd segun las funciones.
 * uniqueHandler trata si uniqueSocket tubo actividad. Generalmente usado para servidores. Si no se quiere utilizar, uniqueSocket poner -1 y uniqueHandler NULL.
 * closeHandler trata si un socket se cerro. Puede ser NULL (lo que hace es cerrar al socket nada mas). Si se tiene un puntero asociado, hacer una funcion que haga algo.
 * normalHandler trata a cualquier socket que no haya caido en ninguna de las otras... Este es 100% necesario.
 */
int epoll_escucharGeneralTimeOut(int epollfd, int serverSocket, void(*serverHandler)(epoll_data_t), void(*normalHandler)(epoll_data_t), void(*closeHandler)(epoll_data_t), int timeOut){
	struct epoll_event events[MAX_EVENTS_EPOLL];
	int nfds, n;
	nfds = epoll_escucharTimeOut(epollfd, events, timeOut);
	if (nfds == -1) {
		if (errno == EINTR ){
			return epoll_escucharGeneralTimeOut(epollfd, serverSocket, serverHandler, normalHandler, closeHandler, timeOut);
		}
		return -1;
	}

	for (n = 0; n < nfds; ++n) {
		if (events[n].data.fd == serverSocket) { 	// Si uniqueSocket == -1, nunca va a entrar porque los fd son >1.
			serverHandler(events[n].data);	// Si uniqueSocket == -1. Esto no se va a usar. Asi que puede ser NULL.
		}
		else {
			if( events[n].events & EPOLLRDHUP) {
				socket_cerrarConexion(events[n].data.fd); //No hace falta sacarlo de epoll, este lo hace solo.
				if (closeHandler != NULL) { //Si closeHandler era NULL automaticamente cierro la coneccion, sino invoco a la funcion.
					closeHandler(events[n].data);
				}
			}
			else {
				normalHandler(events[n].data);	// SI no cae en los dos casos anteriores, si o si cae aca.
			}
		}
	}

	return 0;
}
void GeometryLoader::parse(std::string& input)
{
	std::istringstream stream(input);

	// 1. Prepare the keyword
	std::string keyword;
	stream >> keyword;

	if (keyword.compare("#") == 0)
	{
		return;
	}

	// 2. Prepare tokens
	std::vector<std::string> tokens;
	tokens.reserve(4);

	std::string temp;
	while (stream >> temp)
	{
		tokens.push_back(temp);
	}

	switch (translate(keyword))
	{
	case EKeyword::UNDEFINED:
		break;
	case EKeyword::VERTEX:
		vertexHandler(tokens);
		break;
	case EKeyword::NORMAL:
		normalHandler(tokens);
		break;
	case EKeyword::FACE:
		faceHandler(tokens);
		break;
	case EKeyword::TEXCOORD:
		textureHandler(tokens);
		break;
	default:
		break;
	}
}