/**
 * \file Interact.cpp
 *
 * Implementation of the Interact class
 */

#include "Common/Interact.h"
#include "Common/Support/Debug.h"
#include "Common/Tasks.h"
#include <stdio.h>
#include <string.h>

#ifdef WIN32
	#include <conio.h>
#else	// WIN32
	#include <sys/types.h>
	#include <sys/time.h>
	#include <unistd.h>
#endif	// WIN32

///////////////////////////////////////////////////////////////////////////////
// Interact interface

int Interact::Init(int argc, char** argv, int)
{
	m_pSocket = (CommunicationInterface*) Main::GetInstance()->GetInterface(COMMUNICATION_TASK);
	if (m_pSocket == NULL) return INIT_ERR;
	m_pCommandGen = (CommandsInterface*) Main::GetInstance()->GetInterface(COMMANDS_TASK);
	if (m_pCommandGen == NULL) return INIT_ERR;

	for (int i = 1; i < argc; i++) {
		if (strcmp(argv[i], "-h") == 0) {
			fprintf(stderr, "\n%s %s switches\n\n", (char*)GetName(),
				(char*)GetVer());
			fprintf(stderr, "\t-h: this help\n");
			fprintf(stderr, "\t-a: non-interactive automatic run\n");
			fprintf(stderr, "\t-g: tells player to connect as a goalie\n");
			fprintf(stderr, "\t-s <server>: specifies server name to connect to\n");
			fprintf(stderr, "\t-p <port>: specifies server port to connect to\n");
			fprintf(stderr, "\t-n <name>: specifies team name of player\n\n");
			return INIT_ERR;
		}
		else if (strcmp(argv[i], "-a") == 0) {
			m_bAuto = true;
		}
		else if (strcmp(argv[i], "-g") == 0) {
			m_bGoalie = true;
		}
		else if (strcmp(argv[i], "-s") == 0) {
			if (argv[++i]) strncpy(m_strServer, argv[i], 32);
		}
		else if (strcmp(argv[i], "-p") == 0) {
			if (argv[++i]) sscanf(argv[i], "%d", &m_uPort);
		}
		else if (strcmp(argv[i], "-n") == 0) {
			if (argv[++i]) strncpy(m_strTeamName, argv[i], 32);
		}
	}

	return INIT_OK;
}

void Interact::Run(int)
{
	if (m_bAuto && !m_bInit) {
		m_pSocket->SetServer(m_strServer, m_uPort);
		m_pCommandGen->ServerInit(m_strTeamName, m_bGoalie);
		m_bInit = true;
		return;
	}

#ifndef COACH
	if(!clangInit)
	{
		m_pCommandGen->CLangInit();
		clangInit = true;
	}
#endif

#ifndef WITH_VISUAL

#ifdef WIN32
	if (_kbhit()) m_strBuf[m_iPos++] = _getche();
	if ((m_iPos == 0) || (m_strBuf[m_iPos-1] != '\r')) return;
	printf("\n");
	m_strBuf[m_iPos]='\0';
#else	// WIN32
	fd_set rfds;
	struct timeval tv;
	int retval;

	FD_ZERO(&rfds);
	FD_SET(0, &rfds);
	tv.tv_sec = 0;
	tv.tv_usec = 0;

	retval = select(1, &rfds, NULL, NULL, &tv);
	if (retval) fgets(m_strBuf, 128, stdin);
	else return;
#endif	// WIN32
	float fNum1, fNum2;

	if ((m_strBuf[0] == '\r') || (m_strBuf[0] == '\n')) strcpy(m_strBuf, m_strLast);
	else strcpy(m_strLast, m_strBuf);
	if (m_bAuto) {
		m_pCommandGen->Bye();
		Main::GetInstance()->ShutDown();
	}
	else if (strncmp(m_strBuf, "init", 4) == 0) {
		if (!m_bInit) {
			m_pSocket->SetServer(m_strServer, m_uPort);
			m_pCommandGen->ServerInit(m_strTeamName, m_bGoalie);
			m_bInit = true;
		}
	}
	else if (strncmp(m_strBuf, "bye", 3) == 0) {
		m_pCommandGen->Bye();
	}
	else if (strncmp(m_strBuf, "dash", 4) == 0) {
		sscanf(m_strBuf + 5, "%f", &fNum1);
		m_pCommandGen->Dash(fNum1);
	}
	else if (strncmp(m_strBuf, "kick", 4) == 0) {
		sscanf(m_strBuf + 5, "%f %f", &fNum1, &fNum2);
		m_pCommandGen->Kick(fNum1, fNum2);
	}
	else if (strncmp(m_strBuf, "turn", 4) == 0) {
		sscanf(m_strBuf + 5, "%f", &fNum1);
		m_pCommandGen->Turn(fNum1);
	}
	else if (strncmp(m_strBuf, "move", 4) == 0) {
		sscanf(m_strBuf + 5, "%f %f", &fNum1, &fNum2);
		m_pCommandGen->Move(fNum1, fNum2);
	}
	else if (strncmp(m_strBuf, "exit", 4) == 0) {
		m_pCommandGen->Bye();
		Main::GetInstance()->ShutDown();
	}
	m_strBuf[0] = 0;
	m_iPos = 0;

#endif // WITH_VISUAL
}

///////////////////////////////////////////////////////////////////////////////
// Interact construction

Interact::Interact()
	: Module("Interact", "Interaction module", "v0.1.006")
{
	m_pSocket = NULL;
	m_pCommandGen = NULL;
	m_bInit = false;
	m_bAuto = false;
	m_bGoalie = false;
	strcpy(m_strTeamName, "StjupitDox");
	strcpy(m_strServer, "localhost");
#ifdef COACH
	m_uPort = 6002;
#else // COACH
	m_uPort = 6000;
	clangInit = false;
#endif // COACH
	m_strBuf[0] = 0;
	m_strLast[0] = 0;
	m_iPos = 0;

	if(Main::GetInstance()->RegisterModule(this, USER_INTERACTION_TASK))
	{
		//TXTN("Interact: Register OK");
	}
	else
	{
		ERRN("Interact: Register failed\n\tAborting system");
		Main::GetInstance()->ShutDown();	// not very correct to ShutDown in constructor
	}
}

///////////////////////////////////////////////////////////////////////////////
// Interact operations

///////////////////////////////////////////////////////////////////////////////
// Interact destruction
