#include <stdio.h>
#include <stdlib.h>
#include "scalar-types.pb-c.h"

int main (int argc, const char * argv[])
{
    void *buf;    // Buffer to store serialized data
    unsigned len; // Length of serialized data

    // First fixture (header with string)
    Test__ScalarTypes msg1 = TEST__SCALAR_TYPES__INIT;
    msg1.field_string = "only_header_1";

    len = test__scalar_types__get_packed_size(&msg1);
    buf = malloc(len);
    test__scalar_types__pack(&msg1, buf);
    FILE *f1 = fopen("scalar-types.packed.only_header_1", "w");
    fprintf(stderr, "Writing %d serialized bytes to 'scalar-types.packed.only_header_1'\n", len);
    fwrite(buf, len, 1, f1);
    fclose(f1);
    free(buf);

    // Second fixture (header with string and optional field)
    Test__ScalarTypes msg2 = TEST__SCALAR_TYPES__INIT;
    msg2.field_string = "only_header_2";
    msg2.has_field_double = 1;
    msg2.field_double = 1.1;

    len = test__scalar_types__get_packed_size(&msg2);
    buf = malloc(len);
    test__scalar_types__pack(&msg2, buf);
    FILE *f2 = fopen("scalar-types.packed.only_header_2", "w");
    fprintf(stderr, "Writing %d serialized bytes to 'scalar-types.packed.only_header_2'\n", len);
    fwrite(buf, len, 1, f2);
    fclose(f2);
    free(buf);

    // Third fixture (header with string and repeated field)
    Test__ScalarTypes msg3 = TEST__SCALAR_TYPES__INIT;
    msg3.field_string = "only_header_3";
    msg3.n_field_float = 3;
    msg3.field_float = malloc(sizeof(double) * msg3.n_field_float);
    msg3.field_float[0] = +1.125;
    msg3.field_float[1] = -2.250;
    msg3.field_float[2] = +3.333;

    len = test__scalar_types__get_packed_size(&msg3);
    buf = malloc(len);
    test__scalar_types__pack(&msg3, buf);
    FILE *f3 = fopen("scalar-types.packed.only_header_3", "w");
    fprintf(stderr, "Writing %d serialized bytes to 'scalar-types.packed.only_header_3'\n", len);
    fwrite(buf, len, 1, f3);
    fclose(f3);
    free(buf);
    
    // Forth fixture (full header)
    Test__ScalarTypes msg4 = TEST__SCALAR_TYPES__INIT;
    msg4.field_string = "only_header_4";
    msg4.has_field_double = 1;
    msg4.field_double = 1.1;
    msg4.n_field_float = 3;
    msg4.field_float = malloc(sizeof(double) * msg4.n_field_float);
    msg4.field_float[0] = +1.125;
    msg4.field_float[1] = -2.250;
    msg4.field_float[2] = +3.333;

    len = test__scalar_types__get_packed_size(&msg4);
    buf = malloc(len);
    test__scalar_types__pack(&msg4, buf);
    FILE *f4 = fopen("scalar-types.packed.only_header_4", "w");
    fprintf(stderr, "Writing %d serialized bytes to 'scalar-types.packed.only_header_4'\n", len);
    fwrite(buf, len, 1, f4);
    fclose(f4);
    free(buf);

    // Fifth fixture (integers scalar types)
    Test__ScalarTypes msg5 = TEST__SCALAR_TYPES__INIT;
    msg5.field_string = "integer";
    msg5.has_field_int32 = 1;
    msg5.field_int32 = 1234;
    msg5.has_field_int64 = 1;
    msg5.field_int64 = 500000000;
    msg5.has_field_uint32 = 1;
    msg5.field_uint32 = 1234;
    msg5.has_field_uint64 = 1;
    msg5.field_uint64 = 500000000;
    msg5.has_field_sint32 = 1;
    msg5.field_sint32 = -1234;
    msg5.has_field_sint64 = 1;
    msg5.field_sint64 = -500000000;

    len = test__scalar_types__get_packed_size(&msg5);
    buf = malloc(len);
    test__scalar_types__pack(&msg5, buf);
    FILE *f5 = fopen("scalar-types.packed.integer", "w");
    fprintf(stderr, "Writing %d serialized bytes to 'scalar-types.packed.integer'\n", len);
    fwrite(buf, len, 1, f5);
    fclose(f5);
    free(buf);

    // Sixth fixture (fixed32 scalar types)
    Test__ScalarTypes msg6 = TEST__SCALAR_TYPES__INIT;
    msg6.field_string = "fixed32";
    msg6.has_field_fixed32 = 1;
    msg6.field_fixed32 = 43690; // 0x0000AAAA = 00000000 00000000 10101010 10101010
    msg6.has_field_sfixed32 = 1;
    msg6.field_sfixed32 = -43690; // 0xFFFF5556 = 11111111 11111111 01010101 01010110

    len = test__scalar_types__get_packed_size(&msg6);
    buf = malloc(len);
    test__scalar_types__pack(&msg6, buf);
    FILE *f6 = fopen("scalar-types.packed.fixed32", "w");
    fprintf(stderr, "Writing %d serialized bytes to 'scalar-types.packed.fixed32'\n", len);
    fwrite(buf, len, 1, f6);
    fclose(f6);
    free(buf);

    // Seventh fixture (fixed64 scalar types)
    Test__ScalarTypes msg7 = TEST__SCALAR_TYPES__INIT;
    msg7.field_string = "fixed64";
    msg7.has_field_fixed64 = 1;
    msg7.field_fixed64 = 2863311530; // 0x00000000AAAAAAAA = 00000000 00000000 00000000 00000000 10101010 10101010 10101010 10101010
    msg7.has_field_sfixed64 = 1;
    msg7.field_sfixed64 = -2863311530; // 0xFFFFFFFF55555556 = 11111111 11111111 11111111 11111111 01010101 01010101 01010101 01010110

    len = test__scalar_types__get_packed_size(&msg7);
    buf = malloc(len);
    test__scalar_types__pack(&msg7, buf);
    FILE *f7 = fopen("scalar-types.packed.fixed64", "w");
    fprintf(stderr, "Writing %d serialized bytes to 'scalar-types.packed.fixed64'\n", len);
    fwrite(buf, len, 1, f7);
    fclose(f7);
    free(buf);

    // Eighth fixture (other types)
    Test__ScalarTypes msg8 = TEST__SCALAR_TYPES__INIT;
    msg8.field_string = "other";
    msg8.has_field_bool = 1;
    msg8.field_bool = 1;

    size_t bytes_len = 8;
    uint8_t *bytes_data = malloc(bytes_len);
    for (int i = 0; i < bytes_len; i++) {
        bytes_data[i] = i;
    }

    msg8.has_field_bytes = 1;
    msg8.field_bytes.len = bytes_len;
    msg8.field_bytes.data = bytes_data;

    len = test__scalar_types__get_packed_size(&msg8);
    buf = malloc(len);
    test__scalar_types__pack(&msg8, buf);
    FILE *f8 = fopen("scalar-types.packed.other", "w");
    fprintf(stderr, "Writing %d serialized bytes to 'scalar-types.packed.other'\n", len);
    fwrite(buf, len, 1, f8);
    fclose(f8);
    free(buf);

    return 0;
}
