// DWBS ------------------------------------------------------------------ DWBS
//
// PLATFORM		: ALL
// PRODUCT		: BIT_DEMON
// VISIBILITY	: PUBLIC
//
// DWBS ------------------------------------------------------------------ DWBS

#include <bdExampleCommon/RemoteLogSubscriber.h>

RemoteLogSubscriber::RemoteLogSubscriber()
: m_socketType(BD_UDP_BROADCAST_SOCKET)
{	
}
 
RemoteLogSubscriber::~RemoteLogSubscriber()
{
	quit();
}

bdBool RemoteLogSubscriber::init(	const bdSocketType type,
									const bdAddr &logMachine)
{
	bdBool result = false;
	m_socketType = type;
	switch(type)
	{
		case BD_UDP_BROADCAST_SOCKET:
		{
			const bdBool broadcastFlag = true;
			result = createSocket(broadcastFlag);
			setDestination(logMachine);
			break;
		}
		case BD_UDP_SOCKET:
		{
			const bdBool broadcastFlag = false;
			result = createSocket(broadcastFlag);
			setDestination(logMachine);
			break;
		}
		case BD_TCP_SOCKET:
		{
			result = createStreamSocket(logMachine);
			break;
		}
		default:
		{
			break;
		}
	}
	return result;
}

void RemoteLogSubscriber::quit()
{
	closeSocket();
}

bdBool RemoteLogSubscriber::createSocket(const bdBool isBroadcast)
{
	return m_socket.create(isBroadcast);
}

bdBool RemoteLogSubscriber::createStreamSocket(const bdAddr destination)
{
	bdBool result = m_streamSocket.create();
	if(true == result)
	{
		bdSocketStatusCode status = m_streamSocket.connect(destination);
		if(status == BD_NET_SUCCESS || status == BD_NET_WOULD_BLOCK)
		{
			m_logMachine = destination;
		}
		else
		{
			result = false;
		}
	}
	return result;
}

void RemoteLogSubscriber::closeSocket()
{
	m_socket.close();
}

void RemoteLogSubscriber::setDestination(const bdAddr &logMachine)
{
	m_logMachine = logMachine;
}

void RemoteLogSubscriber::publish(const bdNChar8 *const fullChannelName, 
									const bdNChar8 *const file, 
									const bdNChar8 *const function, 
									const bdUInt line, 
									const bdNChar8 *const msg) 
{
	if(	(BD_UDP_BROADCAST_SOCKET == m_socketType ) ||
		(BD_UDP_SOCKET == m_socketType ))
	{
		if(m_logMachine.getAddress().isValid())
		{
			const bdNChar8 *pos = bdStrrchr(file, '\\');
			bdUWord fileOffset = 0;

			if(pos)
			{
				fileOffset = (pos - file) + 1;
			}

			if(bdStrstr(fullChannelName, BD_LOG_INFO) == fullChannelName)
			{
				bdNChar8 string[2048];
				bdSnprintf(string, sizeof(string), "%s(%u): %s\n", file + fileOffset, line, msg);
				m_socket.sendTo(m_logMachine, string, static_cast<bdUInt>(bdStrlen(string)));
			}
			else if(bdStrstr(fullChannelName, BD_LOG_WARN) == fullChannelName)
			{
				bdNChar8 string[2048];		
				bdSnprintf(string, sizeof(string), "%s(%u): %s\n\tWARNING: %s\n", file + fileOffset, line, function, msg);
				m_socket.sendTo(m_logMachine, string, static_cast<bdUInt>(bdStrlen(string)));
			}
			else if(bdStrstr(fullChannelName, BD_LOG_ERR) == fullChannelName)
			{
				bdNChar8 string[2048];
				bdSnprintf(string, sizeof(string), "%s(%u): %s\n\tERROR: %s\n", file + fileOffset, line, function, msg);
				m_socket.sendTo(m_logMachine, string, static_cast<bdUInt>(bdStrlen(string)));
			}
			else
			{
				//RemoteLogSubscriber::publish: invalid channel name!
				BD_BREAK();
			}
		}
	}
	else if (BD_TCP_SOCKET == m_socketType)
	{
		if(m_logMachine.getAddress().isValid())
		{
			const bdNChar8 *pos = bdStrrchr(file, '\\');
			bdUWord fileOffset = 0;

			if(pos)
			{
				fileOffset = (pos - file) + 1;
			}

			if(bdStrstr(fullChannelName, BD_LOG_INFO) == fullChannelName)
			{
				bdNChar8 string[2048];
				bdSnprintf(string, sizeof(string), "%s(%u): %s\n", file + fileOffset, line, msg);
				m_streamSocket.send(string, static_cast<bdUInt>(bdStrlen(string)));
			}
			else if(bdStrstr(fullChannelName, BD_LOG_WARN) == fullChannelName)
			{
				bdNChar8 string[2048];		
				bdSnprintf(string, sizeof(string), "%s(%u): %s\n\tWARNING: %s\n", file + fileOffset, line, function, msg);
				m_streamSocket.send(string, static_cast<bdUInt>(bdStrlen(string)));
			}
			else if(bdStrstr(fullChannelName, BD_LOG_ERR) == fullChannelName)
			{
				bdNChar8 string[2048];
				bdSnprintf(string, sizeof(string), "%s(%u): %s\n\tERROR: %s\n", file + fileOffset, line, function, msg);
				m_streamSocket.send(string, static_cast<bdUInt>(bdStrlen(string)));
			}
			else
			{
				//RemoteLogSubscriber::publish: invalid channel name!
				BD_BREAK();
			}
		}
	}
	else
	{
		bdUInt socTypeAsInt = m_socketType;
		BD_ERR("remoteLog", "Coding Error in RemoteLogSubscriber m_socketType has unexpected type : %u" , socTypeAsInt);
	}
}

