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

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


/// Default protocol version
#define DEFAULT_PROTOCOL "8.05"


CommandGen::CommandGen()
	: Module("CommandGen", "CommandGen module", "v0.0.002")
{
	m_outBuff[0] = 0;
	m_pSocket = NULL;
	m_pParser = NULL;
	m_pSynchro = NULL;
	memset(&m_outCounts, 0, sizeof(m_outCounts));

#ifndef COACH
	realSide = LEFT;
#endif // COACH

	Main::GetInstance()->RegisterModule(this, COMMANDS_TASK);
}

int CommandGen::Init(int argc, char** argv, int)
{
	m_pSocket = (CommunicationInterface*) Main::GetInstance()->GetInterface(COMMUNICATION_TASK);
	if (m_pSocket == NULL) return INIT_ERR;
	m_pParser = (MsgProcessInterface*) Main::GetInstance()->GetInterface(MESSAGE_PROCESS_TASK);
	if (m_pParser == NULL) return INIT_ERR;
	m_pSynchro = (SynchronizationInterface*) Main::GetInstance()->GetInterface(SYNCHRONIZATION_TASK);
	if (m_pSynchro == NULL) return INIT_ERR;

	return INIT_OK;
}

Interface* CommandGen::GetInterface(int iTask) const
{
	return (CommandsInterface*)this;
}

void CommandGen::SetRealSide(RealSide rs)
{
#ifndef COACH
	realSide = rs;
#endif // COACH
}

int CommandGen::Dash(float fPower)
{
	if(!m_pSocket) return 1;	// error (nie je mozne, Marek :-)

	float fPower1 = RoundFloat(fPower);
	sprintf(m_outBuff, "(dash %.2f)", fPower1);
	m_outCounts.dashCount++;

	if(!m_pSocket->SendMsg(m_outBuff)) {
		if(m_pSynchro) m_pSynchro->OnExecDash(fPower1);
		return 0;
	}
	return 1;
}

int CommandGen::Turn(float fMoment)
{
	if(!m_pSocket) return 1;	// error (nie je mozne, Marek :-)

	float fMoment1 = RoundFloat(fMoment);
	sprintf(m_outBuff, "(turn %.2f)", fMoment1);
	m_outCounts.turnCount++;

	if(!m_pSocket->SendMsg(m_outBuff))
	{
		if(m_pSynchro) m_pSynchro->OnExecTurn(fMoment1);
		return 0;
	}
	return 1;
}

int CommandGen::Kick(float fPower, float fDirection)
{
	if(!m_pSocket) return 1;	// error (nie je mozne, Marek :-)

	float fPower1 = RoundFloat(fPower);
	float fDirection1 = RoundFloat(fDirection);
	sprintf(m_outBuff, "(kick %.2f %.2f)", fPower, fDirection);
	m_outCounts.kickCount++;

	if(!m_pSocket->SendMsg(m_outBuff)) {
		if(m_pSynchro) m_pSynchro->OnExecKick(fPower1, fDirection1);
		return 0;
	}
	return 1;
}

int CommandGen::Move(float fX, float fY)
{
	if(!m_pSocket) return 1;	// error (nie je mozne, Marek :-)

	sprintf(m_outBuff, "(move %.2f %.2f)", fX, fY);
	m_outCounts.moveCount++;

	return m_pSocket->SendMsg(m_outBuff);
}

int CommandGen::Catch(float fDirection)
{
	if(!m_pSocket) return 1;	// error (nie je mozne, Marek :-)

	sprintf(m_outBuff, "(catch %.2f)", fDirection);
	m_outCounts.catchCount++;

	return m_pSocket->SendMsg(m_outBuff);
}

int CommandGen::TurnNeck(int iAngle)
{
	if(!m_pSocket) return 1;	// error (nie je mozne, Marek :-)

	sprintf(m_outBuff, "(turn_neck %d)", iAngle);
	m_outCounts.turnNeckCount++;

	if(!m_pSocket->SendMsg(m_outBuff)) {
		if(m_pSynchro) m_pSynchro->OnExecNeck(iAngle);
		return 0;
	}
	return 1;
}

int CommandGen::Say(const char* pMsg)
{
	if(!m_pSocket) return 1;	// error (nie je mozne, Marek :-)

	sprintf(m_outBuff, "(say %s)", pMsg);
	m_outCounts.sayCount++;

	return m_pSocket->SendMsg(m_outBuff);
}

#ifdef COACH
int CommandGen::Eye(const char* onOff)
{
	if(!m_pSocket) return 1;	// error (nie je mozne, Marek :-)

	sprintf(m_outBuff, "(eye %s)", onOff);
	m_outCounts.sayCount++;

	return m_pSocket->SendMsg(m_outBuff);
}

int CommandGen::TeamNames()
{
	if(!m_pSocket) return 1;	// error (nie je mozne, Marek :-)

	sprintf(m_outBuff, "(team_names)");
	m_outCounts.sayCount++;

	return m_pSocket->SendMsg(m_outBuff);
}

int CommandGen::ChangePlayerType(const int uniformNumber, const int type)
{
	if(!m_pSocket) return 1;	// error (nie je mozne, Marek :-)

	sprintf(m_outBuff, "(change_player_type %d %d)", uniformNumber, type);
	m_outCounts.sayCount++;

	return m_pSocket->SendMsg(m_outBuff);
}

int CommandGen::TeamGraphic(int i, int j, const char* lines)
{
	if(!m_pSocket) return 1;	// error (nie je mozne, Marek :-)

	sprintf(m_outBuff, "(team_graphic (%i %i %s))", i, j, lines);

//	DBGN("send: >>%s<<", m_outBuff);
	return m_pSocket->SendMsg(m_outBuff);
}

#endif // COACH

int CommandGen::ServerInit(const char* teamName, bool goalie, const char* ver)
{
	if(!m_pSocket) return 1;	// error (nie je mozne, Marek :-)

	sprintf(m_outBuff, "(init %s (version %s)%s)",
		teamName, (ver == NULL) ? DEFAULT_PROTOCOL : ver,
		goalie ? " (goalie)" : "");
	
	if(m_pParser) m_pParser->SetTeamName(teamName);

	return m_pSocket->Connect(m_outBuff);
}

int CommandGen::CLangInit()
{
	if(!m_pSocket) return 1;	// error (nie je mozne, Marek :-)

	sprintf(m_outBuff, "(clang (ver 8 8))");
	
	return m_pSocket->SendMsg(m_outBuff);
}

int CommandGen::Reconnect(const char* pTeamName,unsigned uUniformNumber)
{
	if(!m_pSocket) return 1;	// error (nie je mozne, Marek :-)

	sprintf(m_outBuff, "(reconnect %s %d)", pTeamName, uUniformNumber);

	if(m_pParser) m_pParser->SetTeamName(pTeamName);

	return m_pSocket->Connect(m_outBuff);
}

int CommandGen::Bye()
{
	if(!m_pSocket) return 1;	// error (nie je mozne, Marek :-)
	return m_pSocket->Disconnect("(bye)");
}

int CommandGen::SenseBody()
{
	if(!m_pSocket) return 1;	// error (nie je mozne, Marek :-)
	return m_pSocket->SendMsg("(sense_body)");
}

int CommandGen::Score()
{
	if(!m_pSocket) return 1;	// error (nie je mozne, Marek :-)
	return m_pSocket->SendMsg("(score)");
}

int CommandGen::ChangeView(ViewWidth iWidth)
{
	if(!m_pSocket) return 1;	// error (nie je mozne, Marek :-)
	m_outCounts.changeViewCount++;

	switch(iWidth) {
		case NARROW_VIEW:
			return m_pSocket->SendMsg("(change_view narrow high)");
		case NORMAL_VIEW:
			return m_pSocket->SendMsg("(change_view normal high)");
		case WIDE_VIEW:
			return m_pSocket->SendMsg("(change_view wide high)");
	}

	return 1;
}

int CommandGen::Tackle(float power)
{
	if(!m_pSocket) return 1;	// error (nie je mozne, Marek :-)

	sprintf(m_outBuff, "(tackle %.2f)", power);
	return m_pSocket->SendMsg(m_outBuff);
/*
	if(!m_pSocket->SendMsg(m_outBuff)) {
		if(m_pSynchro) m_pSynchro->OnExecKick(fPower1, fDirection1);
		return 0;
	}
	return 1;
*/
}

int CommandGen::PointTo(float dist, float direction)
{
	if(!m_pSocket) return 1;	// error (nie je mozne, Marek :-)

	sprintf(m_outBuff, "(pointto %.2f %.2f)", dist, direction);
	m_outCounts.pointtoCount++;

	return m_pSocket->SendMsg(m_outBuff);
}

int CommandGen::PointToOff()
{
	if(!m_pSocket) return 1;	// error (nie je mozne, Marek :-)

	sprintf(m_outBuff, "(pointto off)");
	m_outCounts.pointtoCount++;

	return m_pSocket->SendMsg(m_outBuff);

}
