#include "msg_private.h"
#include "sv_snapshot_private.h"
#include "../core_runtime/core_runtime_private.h"

#include <string.h>

int32_t
SV_RateMsec(client_t *client,
            int32_t messageSize)
{
    int32_t rate;

    if (messageSize > 1500) {
        messageSize = 1500;
    }

    rate = client->rate;

    if (sv_maxRate->integer != 0) {
        if (sv_maxRate->integer < 1000) {
            Cvar_Set("sv_MaxRate", "1000");
        }
        if (sv_maxRate->integer < rate) {
            rate = sv_maxRate->integer;
        }
    }

    return (messageSize * 1000 + 48000) / rate;
}

void SV_UpdateServerCommandsToClient(client_t *client,
                                     msg_t *msg)
{
    int32_t commandSequence;

    commandSequence = client->reliableAcknowledge + 1;
    /* ORIGINAL_BINARY_BUG: signed relational iteration cannot traverse a
     * pending reliable-command window that straddles INT32_MAX. See
     * original-bugs/coduomp-server-command-sequence-wrap.md. */
    while (commandSequence <= client->reliableSequence) {
        MSG_WriteByte(msg, 5);
        MSG_WriteLong(msg, commandSequence);
        MSG_WriteString(
            msg,
            client->reliableCommands
                [commandSequence & (CODUO_HOST_CLIENT_RELIABLE_COMMAND_COUNT -
                                    1)]
                    .commandText);
        ++commandSequence;
    }

    client->reliableSent = client->reliableSequence;
}

void SV_UpdateServerCommandsToClient_PreventOverflow(
    client_t *client,
    msg_t *msg,
    int32_t maxBytes)
{
    int32_t commandSequence;
    int32_t commandBytes;

    commandSequence = client->reliableAcknowledge + 1;
    /* ORIGINAL_BINARY_BUG: signed relational iteration cannot traverse a
     * pending reliable-command window that straddles INT32_MAX. See
     * original-bugs/coduomp-server-command-sequence-wrap.md. */
    while (commandSequence <= client->reliableSequence) {
        commandBytes =
            (int32_t)strlen(
                client->reliableCommands
                    [commandSequence &
                     (CODUO_HOST_CLIENT_RELIABLE_COMMAND_COUNT - 1)]
                        .commandText) +
            6;

        if (commandBytes + msg->cursize >= maxBytes) {
            break;
        }

        MSG_WriteByte(msg, 5);
        MSG_WriteLong(msg, commandSequence);
        MSG_WriteString(
            msg,
            client->reliableCommands
                [commandSequence & (CODUO_HOST_CLIENT_RELIABLE_COMMAND_COUNT -
                                    1)]
                    .commandText);

        ++commandSequence;
    }

    --commandSequence;
    if (commandSequence > client->reliableSent) {
        client->reliableSent = commandSequence;
    }
}
