/*
 * Called when a packet with the opcode XPT_OPC_S_SHARE_ACK is received
 */
bool xptClient_processPacket_shareAck(xptClient_t* xptClient)
{
	xptPacketbuffer_t* cpb = xptClient->recvBuffer;
	// read data from the packet
	xptPacketbuffer_beginReadPacket(cpb);
	// start parsing
	bool readError = false;
	// read error code field
	uint32 shareErrorCode = xptPacketbuffer_readU32(cpb, &readError);
	if( readError )
		return false;
	// read reject reason
	char rejectReason[512];
	xptPacketbuffer_readString(cpb, rejectReason, 512, &readError);
	rejectReason[511] = '\0';
	float shareValue = xptPacketbuffer_readFloat(cpb, &readError);
	if( readError )
		return false;
	if( shareErrorCode == 0 )
	{
		time_t now = time(0);
		char* dt = ctime(&now);
		//printf("Share accepted by server\n");
		//printf(" [ %d / %d val: %.6f] %s", valid_shares, total_shares, shareValue, dt);
		//primeStats.fShareValue += shareValue;
	}
	else
	{
		// share not accepted by server
		printf("Invalid share\n");
		if( rejectReason[0] != '\0' )
			printf("Reason: %s\n", rejectReason);
	}
	return true;
}
/*
 * Called when a packet with the opcode XPT_OPC_S_AUTH_ACK is received
 */
bool xptClient_processPacket_authResponse(xptClient_t* xptClient)
{
	xptPacketbuffer_t* cpb = xptClient->recvBuffer;
	// read data from the packet
	xptPacketbuffer_beginReadPacket(cpb);
	// start parsing
	bool readError = false;
	// read error code field
	uint32 authErrorCode = xptPacketbuffer_readU32(cpb, &readError);
	if( readError )
		return false;
	// read reject reason / motd
	char rejectReason[512];
	xptPacketbuffer_readString(cpb, rejectReason, 512, &readError);
	rejectReason[511] = '\0';
	if( readError )
		return false;
	if( authErrorCode == 0 )
	{
		xptClient->clientState = XPT_CLIENT_STATE_LOGGED_IN;
		printf("xpt: Logged in\n");
		if( rejectReason[0] != '\0' )
			printf("Message from server: %s\n", rejectReason);
	}
	else
	{
		// error logging in -> disconnect
		printf("xpt: Failed to log in\n");
		if( rejectReason[0] != '\0' )
			printf("Reason: %s\n", rejectReason);
		return false;
	}
	return true;
}
/*
 * Called when a packet with the opcode XPT_OPC_S_MESSAGE is received
 */
bool xptClient_processPacket_message(xptClient_t* xptClient)
{
	xptPacketbuffer_t* cpb = xptClient->recvBuffer;
	// read data from the packet
	xptPacketbuffer_beginReadPacket(cpb);
	// start parsing
	bool readError = false;
	// read type field (not used yet)
	uint32 messageType = xptPacketbuffer_readU8(cpb, &readError);
	if( readError )
		return false;
	// read message text (up to 1024 bytes)
	char messageText[1024];
	xptPacketbuffer_readString(cpb, messageText, 1024, &readError);
	messageText[1023] = '\0';
	if( readError )
		return false;
	printf("Server message: %s\n", messageText);
	return true;
}
/*
 * Called when a packet with the opcode XPT_OPC_S_SHARE_ACK is received
 */
bool xptClient_processPacket_shareAck(xptClient_t* xptClient)
{
    xptPacketbuffer_t* cpb = xptClient->recvBuffer;
    // read data from the packet
    xptPacketbuffer_beginReadPacket(cpb);
    // start parsing
    bool readError = false;
    // read error code field
    uint32 shareErrorCode = xptPacketbuffer_readU32(cpb, &readError);
    if( readError )
        return false;
    // read reject reason
    char rejectReason[512];
    xptPacketbuffer_readString(cpb, rejectReason, 512, &readError);
    rejectReason[511] = '\0';
    float shareValue = xptPacketbuffer_readFloat(cpb, &readError);
    if( readError )
        return false;
    if( shareErrorCode == 0 )
    {
        total_shares++;
        valid_shares++;
        time_t now = time(0);
        char* dt = ctime(&now);
        std::cout << "ACCEPTED [ " << valid_shares << " / " << total_shares << " val: " << shareValue << "] " << dt << std::endl;
        primeStats.fShareValue += shareValue;
        primeStats.fBlockShareValue += shareValue;
        primeStats.fTotalSubmittedShareValue += shareValue;
    }
    else
    {
        // error logging in -> disconnect
        total_shares++;
        std::cout << "Invalid share" << std::endl;
        if( rejectReason[0] != '\0' )
            std::cout << "Reason: " << rejectReason << std::endl;
    }
    return true;
}
/*
 * Called when a packet with the opcode XPT_OPC_S_AUTH_ACK is received
 */
bool xptClient_processPacket_authResponse(xptClient_t* xptClient)
{
	xptPacketbuffer_t* cpb = xptClient->recvBuffer;
	// read data from the packet
	xptPacketbuffer_beginReadPacket(cpb);
	// start parsing
	bool readError = false;
	// read error code field
	uint32 authErrorCode = xptPacketbuffer_readU32(cpb, &readError);
	if( readError )
		return false;
	// read reject reason / motd
	char rejectReason[512];
	xptPacketbuffer_readString(cpb, rejectReason, 512, &readError);
	rejectReason[511] = '\0';
	if( readError )
		return false;
	if( authErrorCode == 0 )
	{
		xptClient->clientState = XPT_CLIENT_STATE_LOGGED_IN;
		printf("xpt: Logged in with %s\n", xptClient->username);
		if( rejectReason[0] != '\0' )
			printf("Message from server: %s\n", rejectReason);
		// start ping mechanism
		xptClient->time_sendPing = (uint32)time(NULL) + 60; // first ping after one minute
	}
	else
	{
		// error logging in -> disconnect
		printf("xpt: Failed to log in with %s\n", xptClient->username);
		if( rejectReason[0] != '\0' )
			printf("Reason: %s\n", rejectReason);
		return false;
	}
	// get algorithm used by this worker
	xptClient->algorithm = xptPacketbuffer_readU8(cpb, &readError);
	return true;
}
/*
 * Called when a packet with the opcode XPT_OPC_S_AUTH_ACK is received
 */
bool xptClient_processPacket_authResponse(xptClient_t* xptClient)
{
    xptPacketbuffer_t* cpb = xptClient->recvBuffer;
    // read data from the packet
    xptPacketbuffer_beginReadPacket(cpb);
    // start parsing
    bool readError = false;
    // read error code field
    uint32 authErrorCode = xptPacketbuffer_readU32(cpb, &readError);
    if( readError )
        return false;
    // read reject reason / motd
    char rejectReason[512];
    xptPacketbuffer_readString(cpb, rejectReason, 512, &readError);
    rejectReason[511] = '\0';
    if( readError )
        return false;
    if( authErrorCode == 0 )
    {
        xptClient->clientState = XPT_CLIENT_STATE_LOGGED_IN;
        std::cout << "xpt: Logged in" << std::endl;
        if( rejectReason[0] != '\0' )
            std::cout << "Message from server: " << rejectReason << std::endl;
        // start ping mechanism
        xptClient->time_sendPing = (uint32)time(NULL) + 60; // first ping after one minute
    }
    else
    {
        // error logging in -> disconnect
        std::cout << "xpt: Failed to log in" << std::endl;
        if( rejectReason[0] != '\0' )
            std::cout << "Reason: " << rejectReason << std::endl;
        return false;
    }
    return true;
}