/* Generated by j2s */

#include <Schema/PduV3.h>

#include <Memory.h>
#include <Json.h>
#include <Str.h>

int
PduV3EventHashFromJson(HashMap *json, PduV3EventHash *out, char **errp)
{
    JsonValue *val;
    int enumParseRes;

    (void) enumParseRes;

    if (!json | !out)
    {
        *errp = "Invalid pointers passed to PduV3EventHashFromJson()";
        return 0;
    }

    val = HashMapGet(json, "sha256");
    if (val)
    {
        if (JsonValueType(val) != JSON_STRING)
        {
            *errp = "PduV3EventHash.sha256 must be of type string.";
            return 0;
        }

        out->sha256 = StrDuplicate(JsonValueAsString(val));
    }
    else
    {
        *errp = "PduV3EventHash.sha256 is required.";
        return 0;
    }

    return 1;
}

HashMap *
PduV3EventHashToJson(PduV3EventHash *val)
{
    HashMap *json;

    if (!val)
    {
        return NULL;
    }

    json = HashMapCreate();
    if (!json)
    {
        return NULL;
    }

    HashMapSet(json, "sha256", JsonValueString(val->sha256));
    return json;
}

void
PduV3EventHashFree(PduV3EventHash *val)
{
    if (!val)
    {
        return;
    }

    Free(val->sha256);
}

int
PduV3FromJson(HashMap *json, PduV3 *out, char **errp)
{
    JsonValue *val;
    int enumParseRes;

    (void) enumParseRes;

    if (!json | !out)
    {
        *errp = "Invalid pointers passed to PduV3FromJson()";
        return 0;
    }

    val = HashMapGet(json, "origin_server_ts");
    if (val)
    {
        if (JsonValueType(val) != JSON_INTEGER)
        {
            *errp = "PduV3.origin_server_ts must be of type integer.";
            return 0;
        }

        out->origin_server_ts = JsonValueAsInteger(val);
    }
    else
    {
        *errp = "PduV3.origin_server_ts is required.";
        return 0;
    }

    val = HashMapGet(json, "content");
    if (val)
    {
        if (JsonValueType(val) != JSON_OBJECT)
        {
            *errp = "PduV3.content must be of type object.";
            return 0;
        }

        out->content = JsonValueAsObject(JsonValueDuplicate(val));
    }
    else
    {
        *errp = "PduV3.content is required.";
        return 0;
    }

    val = HashMapGet(json, "redacts");
    if (val)
    {
        if (JsonValueType(val) != JSON_STRING)
        {
            *errp = "PduV3.redacts must be of type string.";
            return 0;
        }

        out->redacts = StrDuplicate(JsonValueAsString(val));
    }

    val = HashMapGet(json, "sender");
    if (val)
    {
        if (JsonValueType(val) != JSON_STRING)
        {
            *errp = "PduV3.sender must be of type string.";
            return 0;
        }

        out->sender = StrDuplicate(JsonValueAsString(val));
    }
    else
    {
        *errp = "PduV3.sender is required.";
        return 0;
    }

    val = HashMapGet(json, "depth");
    if (val)
    {
        if (JsonValueType(val) != JSON_INTEGER)
        {
            *errp = "PduV3.depth must be of type integer.";
            return 0;
        }

        out->depth = JsonValueAsInteger(val);
    }
    else
    {
        *errp = "PduV3.depth is required.";
        return 0;
    }

    val = HashMapGet(json, "prev_events");
    if (val)
    {
        if (JsonValueType(val) != JSON_ARRAY)
        {
            *errp = "PduV3.prev_events must be of type [string].";
            return 0;
        }

        out->prev_events = ArrayCreate();
        if (!out->prev_events)
        {
            *errp = "Failed to allocate memory for PduV3.prev_events.";
            return 0;
        }
        else
        {
            Array *arr = JsonValueAsArray(val);
            size_t i;

            for (i = 0; i <ArraySize(arr); i++)
            {
                JsonValue *v = ArrayGet(arr, i);
                if (JsonValueType(v) != JSON_STRING)
                {
                    *errp = "PduV3.prev_events[] contains an invalid value.";
                    return 0;
                }
                ArrayAdd(out->prev_events, StrDuplicate(JsonValueAsString(v)));
            }
        }
    }
    else
    {
        *errp = "PduV3.prev_events is required.";
        return 0;
    }

    val = HashMapGet(json, "type");
    if (val)
    {
        if (JsonValueType(val) != JSON_STRING)
        {
            *errp = "PduV3.type must be of type string.";
            return 0;
        }

        out->type = StrDuplicate(JsonValueAsString(val));
    }
    else
    {
        *errp = "PduV3.type is required.";
        return 0;
    }

    val = HashMapGet(json, "unsigned");
    if (val)
    {
        if (JsonValueType(val) != JSON_OBJECT)
        {
            *errp = "PduV3.unsigned must be of type PduV3UnsignedData.";
            return 0;
        }

        if (!PduV3UnsignedDataFromJson(JsonValueAsObject(val), &out->_unsigned, errp))
        {
            return 0;
        }
    }

    val = HashMapGet(json, "auth_events");
    if (val)
    {
        if (JsonValueType(val) != JSON_ARRAY)
        {
            *errp = "PduV3.auth_events must be of type [string].";
            return 0;
        }

        out->auth_events = ArrayCreate();
        if (!out->auth_events)
        {
            *errp = "Failed to allocate memory for PduV3.auth_events.";
            return 0;
        }
        else
        {
            Array *arr = JsonValueAsArray(val);
            size_t i;

            for (i = 0; i <ArraySize(arr); i++)
            {
                JsonValue *v = ArrayGet(arr, i);
                if (JsonValueType(v) != JSON_STRING)
                {
                    *errp = "PduV3.auth_events[] contains an invalid value.";
                    return 0;
                }
                ArrayAdd(out->auth_events, StrDuplicate(JsonValueAsString(v)));
            }
        }
    }
    else
    {
        *errp = "PduV3.auth_events is required.";
        return 0;
    }

    val = HashMapGet(json, "room_id");
    if (val)
    {
        if (JsonValueType(val) != JSON_STRING)
        {
            *errp = "PduV3.room_id must be of type string.";
            return 0;
        }

        out->room_id = StrDuplicate(JsonValueAsString(val));
    }
    else
    {
        *errp = "PduV3.room_id is required.";
        return 0;
    }

    val = HashMapGet(json, "state_key");
    if (val)
    {
        if (JsonValueType(val) != JSON_STRING)
        {
            *errp = "PduV3.state_key must be of type string.";
            return 0;
        }

        out->state_key = StrDuplicate(JsonValueAsString(val));
    }

    val = HashMapGet(json, "signatures");
    if (val)
    {
        if (JsonValueType(val) != JSON_OBJECT)
        {
            *errp = "PduV3.signatures must be of type object.";
            return 0;
        }

        out->signatures = JsonValueAsObject(JsonValueDuplicate(val));
    }
    else
    {
        *errp = "PduV3.signatures is required.";
        return 0;
    }

    val = HashMapGet(json, "hashes");
    if (val)
    {
        if (JsonValueType(val) != JSON_OBJECT)
        {
            *errp = "PduV3.hashes must be of type PduV3EventHash.";
            return 0;
        }

        if (!PduV3EventHashFromJson(JsonValueAsObject(val), &out->hashes, errp))
        {
            return 0;
        }
    }
    else
    {
        *errp = "PduV3.hashes is required.";
        return 0;
    }

    return 1;
}

HashMap *
PduV3ToJson(PduV3 *val)
{
    HashMap *json;

    if (!val)
    {
        return NULL;
    }

    json = HashMapCreate();
    if (!json)
    {
        return NULL;
    }

    HashMapSet(json, "origin_server_ts", JsonValueInteger(val->origin_server_ts));
    HashMapSet(json, "content", JsonValueObject(JsonDuplicate(val->content)));
    HashMapSet(json, "redacts", JsonValueString(val->redacts));
    HashMapSet(json, "sender", JsonValueString(val->sender));
    HashMapSet(json, "depth", JsonValueInteger(val->depth));
    if (val->prev_events)
    {
        size_t i;
        Array *jsonArr = ArrayCreate();
        if (!jsonArr)
        {
            JsonFree(json);
            return NULL;
        }
        for (i = 0; i < ArraySize(val->prev_events); i++)
        {
            ArrayAdd(jsonArr, JsonValueString(ArrayGet(val->prev_events, i)));
        }
        HashMapSet(json, "prev_events", JsonValueArray(jsonArr));
    }
    HashMapSet(json, "type", JsonValueString(val->type));
    HashMapSet(json, "unsigned", JsonValueObject(PduV3UnsignedDataToJson(&val->_unsigned)));
    if (val->auth_events)
    {
        size_t i;
        Array *jsonArr = ArrayCreate();
        if (!jsonArr)
        {
            JsonFree(json);
            return NULL;
        }
        for (i = 0; i < ArraySize(val->auth_events); i++)
        {
            ArrayAdd(jsonArr, JsonValueString(ArrayGet(val->auth_events, i)));
        }
        HashMapSet(json, "auth_events", JsonValueArray(jsonArr));
    }
    HashMapSet(json, "room_id", JsonValueString(val->room_id));
    HashMapSet(json, "state_key", JsonValueString(val->state_key));
    HashMapSet(json, "signatures", JsonValueObject(JsonDuplicate(val->signatures)));
    HashMapSet(json, "hashes", JsonValueObject(PduV3EventHashToJson(&val->hashes)));
    return json;
}

void
PduV3Free(PduV3 *val)
{
    if (!val)
    {
        return;
    }

    JsonFree(val->content);
    Free(val->redacts);
    Free(val->sender);
    if (val->prev_events)
    {
        size_t i;
        for (i = 0; i < ArraySize(val->prev_events); i++)
        {
            Free(ArrayGet(val->prev_events, i));
        }
        ArrayFree(val->prev_events);
    }
    Free(val->type);
    PduV3UnsignedDataFree(&val->_unsigned);
    if (val->auth_events)
    {
        size_t i;
        for (i = 0; i < ArraySize(val->auth_events); i++)
        {
            Free(ArrayGet(val->auth_events, i));
        }
        ArrayFree(val->auth_events);
    }
    Free(val->room_id);
    Free(val->state_key);
    JsonFree(val->signatures);
    PduV3EventHashFree(&val->hashes);
}

int
PduV3UnsignedDataFromJson(HashMap *json, PduV3UnsignedData *out, char **errp)
{
    JsonValue *val;
    int enumParseRes;

    (void) enumParseRes;

    if (!json | !out)
    {
        *errp = "Invalid pointers passed to PduV3UnsignedDataFromJson()";
        return 0;
    }

    val = HashMapGet(json, "age");
    if (val)
    {
        if (JsonValueType(val) != JSON_INTEGER)
        {
            *errp = "PduV3UnsignedData.age must be of type integer.";
            return 0;
        }

        out->age = JsonValueAsInteger(val);
    }

    return 1;
}

HashMap *
PduV3UnsignedDataToJson(PduV3UnsignedData *val)
{
    HashMap *json;

    if (!val)
    {
        return NULL;
    }

    json = HashMapCreate();
    if (!json)
    {
        return NULL;
    }

    HashMapSet(json, "age", JsonValueInteger(val->age));
    return json;
}

void
PduV3UnsignedDataFree(PduV3UnsignedData *val)
{
    if (!val)
    {
        return;
    }

}