void mpeServerTCP::threadedFunction()
{
	while(isThreadRunning()){

		if(shouldTriggerFrame){
			float now = ofGetElapsedTimef();
			float elapsed = (now - lastFrameTriggeredTime);

			//cout << "should trigger frame!" << endl;

			if(elapsed >= 1.0/framerate){

				//cout << "triggered frame with framerate error of " << fabs( elapsed - 1.0/framerate)  << endl;

				string message = "G,"+ofToString(currentFrame);
				if (newMessage){
					message += currentMessage;
					newMessage = false;
					currentMessage = "";
				}

				server.sendToAll(message);

				for(int i = 0; i < connections.size(); i++){
					connections[i].ready = false;
				}

				shouldTriggerFrame = false;
				lastFrameTriggeredTime = now;
				currentFrame++;
			}
		}
		else {

			//check for dead clients
			bool lostConnection = false;
			for(int c = 0; c < numExpectedClients; c++){
				if(connections[c].started && !server.isClientConnected(connections[c].tcpServerIndex)){
					connections[c].started = false;
					lostConnection = true;
				}
			}

			if(allconnected && lostConnection){

				ofLog(OF_LOG_NOTICE, "MPE :: Client Disconnected -- RESET");

				//oops someone left
				printClientStatus();
				currentFrame = 0;
				shouldTriggerFrame = false;
				allconnected = false;

				server.sendToAll("R");
			}

			//cout << "All clients are connected! " << endl;

			for(int i = 0; i < server.getLastID(); i++){

				if(!server.isClientConnected(i)){
					continue;
				}

				string response = server.receive(i);

				if(response == ""){
					continue;
				}

	//			cout << "received a response " << response << endl;

				char first = response.at(0);
				if(first == 'L'){
					//Listener connected
					listeners.push_back(i);
				}
				else if(first == 'S'){
					//that's the start!
					int clientID = ofToInt(response.substr(1,1));
					if(clientID < numExpectedClients){
						vector<string> info = ofSplitString(response, ",", true, true);
						if(connections[clientID].started && currentFrame != 0){
                            //client already started, must have reset...
                            allconnected = false;
                            currentFrame = 0;
                            shouldTriggerFrame = false;
                            server.sendToAll("R");
						}

						connections[clientID].tcpServerIndex = i;
						connections[clientID].started = true;
						connections[clientID].name = info[1];
						cout << "Client ID " << clientID << " with response " << response << endl;
						//TODO: parse name
						printClientStatus();
					}
					else{
						ofLog(OF_LOG_ERROR, "Received Client ID " + ofToString(clientID)  + " out of range");
					}
				}
				else if(first == 'D'){

					if(!allconnected){
						continue;
					}

					vector<string> info = ofSplitString(response, ",", true, true);
					if(info.size() >= 3){
						int clientID = ofToInt(info[1]);
						int fc = ofToInt(info[2]);
						if(fc == currentFrame){
							//todo validate client id
							connections[clientID].ready = true;
							//cout << " client " << clientID << " is ready " << endl;
						}
						if(info.size() > 3){
							newMessage = true;
							for(int i = 3; i < info.size(); i++){
								currentMessage += ":" + info[i];
							}
							//cout << "NEW FORMAT :: MESSSAGE IS " << currentMessage << endl;
						}
					}
					else {
						ofLog(OF_LOG_ERROR, "MPE Server :: Response String " + response + " Invalid size");
					}
				}
			}

			if(!allconnected){
				allconnected = true;
				for(int c = 0; c < connections.size(); c++){
					if(!connections[c].started){
						allconnected = false;
						break;
					}
				}
				if(allconnected){
					shouldTriggerFrame = true;
					cout << "All clients connected!" << endl;
				}
			}
			//All connected and going
			else {
				bool allready = true;
				for(int c = 0; c < connections.size(); c++){
					if(!connections[c].ready){
						allready = false;
						break;
					}
				}
				if(allready){
					shouldTriggerFrame = true;
				}
			}
		}
        ofSleepMillis(5);
	}//end while
}
int main(int args, char *argv[]) {

	char message[100];
	MainPlayerData toPlayerData;
	CandidateData toCandidateData;
	StatusType status;
	fd_set allSocket;
	fd_set readfds;
	int fdmax, k, l;
	int n;
	int playerIndex;
	int mainPlayerSelected = 0;
	int clientId;
	int playerAnswer;
	int level;
	int numberOfClient = 0;
	int yes = 1;
	int readResult;
	int listener;
	int acceptSocket;
	struct sockaddr_in server, client;
	int sin_size;
	int socket_in_allSocket;
	int nbytes;
	int i, j;
	char clientName[40];
	initializeClientList();
	createCashPrizeList();
	sin_size = sizeof(struct sockaddr_in);
	FD_ZERO(&allSocket);
	FD_ZERO(&readfds);
	if (args < 2) {
		printf("Usage : %s <PORT>\n", argv[0]);
		exit(-1);
	}
	readResult = readQuestionFile("question.txt");
	if (readResult < 0) {
		printf("Can't load the questions !");
		exit(-1);
	}
	if ((listener = socket(AF_INET, SOCK_STREAM, 0)) == -1) {
		printf("socket() error!\n");
		exit(-1);
	}
	server.sin_family = AF_INET;
	server.sin_port = htons(atoi(argv[1]));
	server.sin_addr.s_addr = INADDR_ANY;
	bzero(&(server.sin_zero), 8);
	setsockopt(listener, SOL_SOCKET, SO_REUSEADDR, &yes, sizeof(int));
	if (bind(listener, (struct sockaddr*) &server, sizeof(struct sockaddr))
			== -1) {
		printf("bind() error!\n");
		exit(-1);
	}
	//listen
	if (listen(listener, 2) == -1) {
		perror("listen");
		exit(3);
	}
	FD_SET(listener, &allSocket);
	fdmax = listener;
	printf("\t<<<Gameshow GHE NONG - AI LA TRIEU PHU>>>\n");
	while (1) {

		readfds = allSocket;

		/* On error, -1 is returned, select() and pselect() return the number of file descriptors */
		if (mainPlayerSelected == 0) {
			if (select(fdmax + 1, &readfds, NULL, NULL, NULL ) == -1) {
				perror("select");
				printf("errno = %d.\n", errno);
				exit(4);
			}
		}

		for (i = 0; i <= fdmax; i++) {

			if (FD_ISSET(i, &readfds)) {
				//printf("isset i=%d\n", i);
				if (i == listener) {

					acceptSocket = accept(listener, (struct sockaddr*) &client,
							&sin_size);
					printf("Listener : %d accept %d\n", listener, acceptSocket);
					//in dia chi ip
					printf("\n client address %s\n",
							inet_ntoa(client.sin_addr));
					if (acceptSocket == -1) {
						perror("accept");

					} else if (isClientListFull()) {
						clientId = NULL_ID;
						send(acceptSocket, &clientId, sizeof clientId, 0);
						close(acceptSocket);
						//FD_CLR(acceptSocket, &allSocket);
					} else {
						FD_SET(acceptSocket, &allSocket);
						printf("Server connected with socket %d\n",
								acceptSocket);
						addClient(acceptSocket);
						clientId = acceptSocket;
						if (acceptSocket > fdmax) {
							fdmax = acceptSocket;
							//printf("Now fdmax is : %d\n", fdmax);
						}
						send(acceptSocket, &clientId, sizeof clientId, 0);
						numberOfClient = getNumberOfClient();
						printf("We're now having %d clients connected !\n",
								numberOfClient);
					}

				} else {
//					printf("i before switch = %d Fmax=%d\n", i, fdmax);
					switch_case: switch (getClientStatus(i)) {
					case CONNECTED:
						if ((nbytes = recv(i, &toCandidateData,
								sizeof toCandidateData, 0)) <= 0) {
							printf(
									"Server stopped connecting to client id %d\n",
									i);
							close(i);
							removeClient(i);
							printf("%d clients left !\n", getNumberOfClient());
							FD_CLR(i, &allSocket);
							break;
						} else {
							recv(i, clientName, sizeof clientName, 0);
							setClientStatus(i, WAITING, clientName);
							strcpy(message, "Welcome : ");
							strcat(message, clientName);
							strcat(message, "\n");
							strcpy(toCandidateData.message, message);
							toCandidateData.status = WAITING;
							send(i, &toCandidateData, sizeof toCandidateData,
									0);
							printClientList();
							/* check if have enough 6 clients, so we can start the game */
							if (readyToStart()) {
								printf("We can start the game !!\n");
								k = randomNumber(NUMBERS_PER_QUES);
								//send question to all the clients //
								for (j = 0; j < BACKLOG; j++) {
									setCompetition(j);
									copyQuestion(&(toCandidateData.question),
											questLib[0][k]);
									toCandidateData.ansTime = 0;
									toCandidateData.status = COMPETING;
									strcpy(toCandidateData.message,
											QUICK_QUESTION_MESSAGE);
									send(clientInfo[j].id, &toCandidateData,
											sizeof(CandidateData), 0);
								}
								//get the answer back from them //
								for (j = 0; j < BACKLOG; j++) {
									if (recv(clientInfo[j].id, &toCandidateData,
											sizeof toCandidateData, 0) <= 0) {
										printf(
												"Server stopped connecting to client id %d\n",
												i);
										close(i);
										removeClient(i);
										printf("%d clients left !\n",
												getNumberOfClient());
										FD_CLR(i, &allSocket);
									} else {
										clientInfo[j].quick_answer =
												toCandidateData.answer;
										clientInfo[j].ansTime =
												toCandidateData.ansTime;
									}
								}
								//printf("Sending question done!\n");
								printClientsAnswerList();
								//select the main player //
								playerIndex = selectMainPlayer(questLib[0][k],
										BACKLOG);
								printf(
										"Our answer for the quick question : %d\n",
										questLib[0][k].ans);
								printf("====MAIN PLAYER SELECTED : %s ====\n",
										clientInfo[playerIndex].clientName);
								printClientStatus(clientInfo[playerIndex].id);
								startGame(playerIndex);

								for (j = 0; j < BACKLOG; j++) {
									if (j != playerIndex) {
										strcpy(toCandidateData.message,
												JOINER_MESSAGE);
									} else {
										strcpy(toCandidateData.message,
												MAIN_PLAYER_SELECTED);
										strcpy(toPlayerData.name,
												clientInfo[j].clientName);
									}
									toCandidateData.status = getClientStatus(
											clientInfo[j].id);
									send(clientInfo[j].id, &toCandidateData,
											sizeof(CandidateData), 0);

								}
								printClientList();
								//printf("Current i = %d\n", i);
								i = clientInfo[playerIndex].id;
								mainPlayerSelected = 1;
								goto switch_case;
//								break;
							} else {
								sprintf(message,
										"We now have %d players online, please wait until we have more %d client(s) !\n",
										getNumberOfClient(),
										BACKLOG - getNumberOfClient());
								strcpy(toCandidateData.message, message);
								send(i, &toCandidateData,
										sizeof toCandidateData, 0);

							}
						}
						break;
					case JOINING:
						//printf("[JOINING] Current i = %d\n", i);
//						i = 0;
//						if (mainPlayerSelected == 1) {
//							if ((nbytes = recv(i, &toCandidateData,
//									sizeof toCandidateData, 0)) <= 0) {
//								printf(
//										"Server stopped connecting to client id %d\n",
//										i);
//								close(i);
//								removeClient(i);
//								printf("%d clients left !\n",
//										getNumberOfClient());
//								FD_CLR(i, &allSocket);
//								break;
//							}
//						}
						break;
					case PLAYING:
						mainPlayerSelected = 1;
						initializeMainPlayerData(&toPlayerData);
						level = 1;
						do {
							selectQuestion(level, &toPlayerData);
							send(clientInfo[playerIndex].id, &toPlayerData,
									sizeof toPlayerData, 0);
							for (n = 0; n < BACKLOG; n++) {
								if (clientInfo[n].status == JOINING) {
									send(clientInfo[n].id, &toPlayerData,
											sizeof toPlayerData, 0);
								}
							}
							if (recv(i, &playerAnswer, sizeof playerAnswer, 0)
									<= 0) {
								printf(
										"Server stopped connecting to client id %d\n",
										i);
								close(i);
								removeClient(i);
								printf("%d clients left !\n",
										getNumberOfClient());
								FD_CLR(i, &allSocket);
								gameFinish(&toPlayerData,END);
								for (n = 0; n < BACKLOG; n++) {
									if (clientInfo[n].status == JOINING) {
										toPlayerData.status = FINISHED;
										send(clientInfo[n].id, &toPlayerData,
												sizeof toPlayerData, 0);
										close(clientInfo[n].id);
										removeClient(clientInfo[n].id);
										FD_CLR(clientInfo[n].id, &allSocket);
									}
								}
								continue;
							}

							if (playerAnswer == RIGHT) {
								printf("Good job! The player gave a right answer!\n");
								increaseQuestion(&toPlayerData);
								//tra loi dung o cau hoi so 15
								if (level == MAX_LEVEL) {
									wonGame(&toPlayerData);
									send(i, &toPlayerData, sizeof toPlayerData,
											0);
									for (n = 0; n < BACKLOG; n++) {
										if (clientInfo[n].status == JOINING) {
											send(clientInfo[n].id,
													&toPlayerData,
													sizeof toPlayerData, 0);
											close(clientInfo[n].id);
											removeClient(clientInfo[n].id);
											FD_CLR(clientInfo[n].id,
													&allSocket);
										}
									}
									close(i);
									removeClient(i);
									FD_CLR(i, &allSocket);
									exit(1);
								}
								level = level + 1;
							} else {
								endGame(&toPlayerData, playerAnswer);
								gameFinish(&toPlayerData,playerAnswer);
								send(i, &toPlayerData, sizeof toPlayerData, 0);
								for (n = 0; n < BACKLOG; n++) {
									if (clientInfo[n].status == JOINING) {
										toPlayerData.status = FINISHED;
										send(clientInfo[n].id, &toPlayerData,
												sizeof toPlayerData, 0);
										close(clientInfo[n].id);
										removeClient(clientInfo[n].id);
										FD_CLR(clientInfo[n].id, &allSocket);
									}
								}
								close(i);
								removeClient(i);
								printf("%d clients left !\n",
										getNumberOfClient());
								FD_CLR(i, &allSocket);
							}
						} while (playerAnswer == RIGHT && level <= MAX_LEVEL);
						printf("The game of player : %s ended !\n",
								toPlayerData.name);
						exit(1);
						break;
					default:
						break;
					}

				}
			}

		}

	}
}