/**
 * Copyright (c) 2009-2019, quasardb SAS
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are met:
 *
 *    * Redistributions of source code must retain the above copyright
 *      notice, this list of conditions and the following disclaimer.
 *    * Redistributions in binary form must reproduce the above copyright
 *      notice, this list of conditions and the following disclaimer in the
 *      documentation and/or other materials provided with the distribution.
 *    * Neither the name of quasardb nor the names of its contributors may
 *      be used to endorse or promote products derived from this software
 *      without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY QUASARDB AND CONTRIBUTORS ``AS IS'' AND ANY
 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
 * DISCLAIMED. IN NO EVENT SHALL THE REGENTS AND CONTRIBUTORS BE LIABLE FOR ANY
 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */

#define __STDC_FORMAT_MACROS
#include <inttypes.h>
#undef __STDC_FORMAT_MACROS
#include <qdb/stream.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#define BUFFER_SIZE (1024 * 1024) // 1MB

qdb_error_t write_to_stream_impl(const char * uri, const char * alias, const void * content, size_t content_length)
{
    qdb_error_t error = qdb_e_uninitialized;
    qdb_handle_t handle;

    error = qdb_open(&handle, qdb_p_tcp);
    if (error) return error;

    error = qdb_connect(handle, uri);
    if (error) return error;

    // doc-start-stream_open
    qdb_stream_t stream;
    error = qdb_stream_open(handle, alias, qdb_stream_mode_append, &stream);
    if (error)
    {
        fprintf(stderr, "qdb_stream_open failed!\n");
        return error;
    }
    // doc-end-stream_open

    puts("Press Ctrl-C stop...\n");

    for (;;)
    {
        size_t length_to_write = rand() % content_length; // NOLINT(cert-msc30-c,cert-msc50-cpp)
        // doc-start-stream_write
        // const void * content; // possibly large amount of data
        error = qdb_stream_write(stream, content, length_to_write);
        if (error)
        {
            fprintf(stderr, "qdb_stream_write failed!\n");
            break;
        }
        // doc-end-stream_write

        // doc-start-stream_size
        qdb_stream_size_t size;
        error = qdb_stream_size(stream, &size);
        if (error)
        {
            fprintf(stderr, "qdb_stream_size failed!\n");
            break;
        }
        // doc-end-stream_size

        printf("\rWrote %" PRIu64 " MB so far  ", size >> 20);
    }

    error = qdb_close(handle);

    return error;
}

qdb_error_t write_to_stream(const char * uri, const char * alias)
{
    qdb_error_t error = qdb_e_uninitialized;
    char * random_data;
    int i;

    random_data = malloc(BUFFER_SIZE);
    if (!random_data)
    {
        return qdb_e_no_memory_local;
    }

    for (i = 0; i < BUFFER_SIZE; i++)
    {
        random_data[i] = rand() & 0xFF; // NOLINT
    }

    error = write_to_stream_impl(uri, alias, random_data, BUFFER_SIZE);

    free(random_data);

    return error;
}

int main(int argc, char * argv[])
{
    qdb_error_t error = qdb_e_uninitialized;

    if (argc != 3)
    {
        fprintf(stderr, "Usage: %s <uri> <alias>\n", argv[0]);
        return EXIT_FAILURE;
    }

    error = write_to_stream(/*uri=*/argv[1], /*alias=*/argv[2]);
    if (error)
    {
        fprintf(stderr, "%s\n", qdb_error(error));
        return EXIT_FAILURE;
    }

    return EXIT_SUCCESS;
}
