/* Licensed to the Apache Software Foundation (ASF) under one or more
 * contributor license agreements.  See the NOTICE file distributed with
 * this work for additional information regarding copyright ownership.
 * The ASF licenses this file to You under the Apache License, Version 2.0
 * (the "License"); you may not use this file except in compliance with
 * the License.  You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#include <assert.h>
#include <stdio.h>
#include <stdlib.h>

#include "apr_json.h"

#include "abts.h"
#include "testutil.h"

static void test_json_identity(abts_case * tc, void *data)
{
    apr_json_value_t *json = NULL;
    apr_json_kv_t *image, *width, *ids, *title,
            *animated, *thumbnail, *height;
    apr_bucket_alloc_t *ba;
    apr_bucket_brigade *bb;
    const char *src;
    char buf[1024];
    apr_size_t len = sizeof(buf);
    apr_off_t offset = 0;

    ba = apr_bucket_alloc_create(p);
    bb = apr_brigade_create(p, ba);

    src = "{"
        "  \"Image\" : {"
        "    \"Width\" : 800 ,"
        "    \"IDs\" : [116, 943, 234, 38793],"
        "    \"Title\" : \"View from 15th Floor\","
        "    \"Animated\" : false,"
        "    \"Thumbnail\" : {"
        "      \"Height\" : 125,"
        "      \"Width\" : 100,"
        "      \"Url\" : \"http://www.example.com/image/481989943\""
        "    },"
        "    \"Height\" : 600 "
        "  }"
        "}";

    apr_json_decode(&json, src, APR_JSON_VALUE_STRING, &offset, APR_JSON_FLAGS_WHITESPACE,
            10, p);
    apr_json_encode(bb, NULL, NULL, json, APR_JSON_FLAGS_WHITESPACE, p);
    apr_brigade_flatten(bb, buf, &len);
    apr_json_decode(&json, buf, len, &offset, APR_JSON_FLAGS_WHITESPACE, 10, p);

    ABTS_STR_NEQUAL(tc, src, buf, len);

    ABTS_INT_EQUAL(tc, len, offset);
    ABTS_INT_EQUAL(tc, APR_JSON_OBJECT, json->type);
    image = apr_hash_get(json->value.object->hash, "Image", 5);
    ABTS_PTR_NOTNULL(tc, image);
    width = apr_hash_get(image->v->value.object->hash, "Width", 5);
    ABTS_PTR_NOTNULL(tc, width);
    ABTS_INT_EQUAL(tc, APR_JSON_LONG, width->v->type);
    ABTS_INT_EQUAL(tc, 800, width->v->value.lnumber);
    ids = apr_hash_get(image->v->value.object->hash, "IDs", 3);
    ABTS_PTR_NOTNULL(tc, ids);
    ABTS_INT_EQUAL(tc, APR_JSON_ARRAY, ids->v->type);
    title = apr_hash_get(image->v->value.object->hash, "Title", 5);
    ABTS_PTR_NOTNULL(tc, title);
    ABTS_INT_EQUAL(tc, APR_JSON_STRING, title->v->type);
    animated = apr_hash_get(image->v->value.object->hash, "Animated", 8);
    ABTS_PTR_NOTNULL(tc, animated);
    ABTS_INT_EQUAL(tc, APR_JSON_BOOLEAN, animated->v->type);
    ABTS_TRUE(tc, !animated->v->value.boolean);
    thumbnail = apr_hash_get(image->v->value.object->hash, "Thumbnail", 9);
    ABTS_PTR_NOTNULL(tc, thumbnail);
    ABTS_INT_EQUAL(tc, APR_JSON_OBJECT, thumbnail->v->type);
    height = apr_hash_get(image->v->value.object->hash, "Height", 6);
    ABTS_PTR_NOTNULL(tc, height);
    ABTS_INT_EQUAL(tc, APR_JSON_LONG, height->v->type);
    ABTS_INT_EQUAL(tc, 600, height->v->value.lnumber);

}

static void test_json_level(abts_case * tc, void *data)
{
    apr_json_value_t *json = NULL;
    apr_status_t status;
    const char *src;
    apr_off_t offset = 0;

    src = "{"
        "\"One\":{"
        "\"Two\":{"
        "\"Three\":{";

    status = apr_json_decode(&json, src, APR_JSON_VALUE_STRING, &offset,
            APR_JSON_FLAGS_WHITESPACE, 2, p);

    ABTS_INT_EQUAL(tc, APR_EINVAL, status);

}

static void test_json_eof(abts_case * tc, void *data)
{
    apr_json_value_t *json = NULL;
    apr_status_t status;
    const char *src;
    apr_off_t offset = 0;

    src = "{"
        "\"One\":{"
        "\"Two\":{"
        "\"Three\":{";

    status = apr_json_decode(&json, src, APR_JSON_VALUE_STRING, &offset,
            APR_JSON_FLAGS_WHITESPACE, 10, p);

    ABTS_INT_EQUAL(tc, APR_EOF, status);

}

static void test_json_string(abts_case * tc, void *data)
{
    apr_json_value_t *json = NULL;
    apr_status_t status;
    const char *src;
    apr_off_t offset = 0;

    /* "턞\"\t/\b\f\n\r\t"; */
    const unsigned char expected[] = {237, 132, 158, 34, 9, 47, 8, 12, 10, 13, 9, 0};

    src = "\"\\uD834\\uDD1E\\\"\\t\\/\\b\\f\\n\\r\\t\"";

    status = apr_json_decode(&json, src, APR_JSON_VALUE_STRING, &offset,
            APR_JSON_FLAGS_WHITESPACE, 10, p);

    ABTS_INT_EQUAL(tc, APR_SUCCESS, status);
    ABTS_INT_EQUAL(tc, APR_JSON_STRING, json->type);

    ABTS_ASSERT(tc, "check for string unescape match",
            (memcmp(expected, json->value.string.p, json->value.string.len) == 0));
}

static void test_json_overlay(abts_case * tc, void *data)
{
    const char *o = "{\"o1\":\"foo\",\"common\":\"bar\",\"o2\":\"baz\"}";
    const char *b = "{\"b1\":\"foo\",\"common\":\"bar\",\"b2\":\"baz\"}";

    apr_json_value_t *res;
    apr_json_value_t *base;
    apr_json_value_t *overlay;

    apr_off_t offset;
    apr_status_t status;

    status = apr_json_decode(&base, b, APR_JSON_VALUE_STRING, &offset,
            APR_JSON_FLAGS_WHITESPACE, 10, p);
    ABTS_INT_EQUAL(tc, APR_SUCCESS, status);

    status = apr_json_decode(&overlay, o, APR_JSON_VALUE_STRING, &offset,
            APR_JSON_FLAGS_WHITESPACE, 10, p);
    ABTS_INT_EQUAL(tc, APR_SUCCESS, status);

    res = apr_json_overlay(p, overlay, base, APR_JSON_FLAGS_NONE);
    ABTS_INT_EQUAL(tc, 5, apr_hash_count(res->value.object->hash));

    res = apr_json_overlay(p, overlay, base, APR_JSON_FLAGS_STRICT);
    ABTS_ASSERT(tc, "overlay strict should return NULL",
            (res == NULL));

}

static void test_json_object_iterate(abts_case * tc, void *data)
{
    const char *o = "{\"o1\":\"foo\",\"o2\":\"bar\"}";

    apr_json_value_t *val;
    apr_json_kv_t *kv;

    apr_off_t offset;
    apr_status_t status;

    status = apr_json_decode(&val, o, APR_JSON_VALUE_STRING, &offset,
            APR_JSON_FLAGS_WHITESPACE, 10, p);
    ABTS_INT_EQUAL(tc, APR_SUCCESS, status);

    kv = apr_json_object_first(val);
    ABTS_PTR_NOTNULL(tc, kv);

    kv = apr_json_object_next(val, kv);
    ABTS_PTR_NOTNULL(tc, kv);

    kv = apr_json_object_next(val, kv);
    ABTS_ASSERT(tc, "object next should return NULL",
            (kv == NULL));

}

static void test_json_array_iterate(abts_case * tc, void *data)
{
    const char *o = "[\"a1\",\"a2\"]";

    apr_json_value_t *arr;
    apr_json_value_t *val;

    apr_off_t offset;
    apr_status_t status;

    status = apr_json_decode(&arr, o, APR_JSON_VALUE_STRING, &offset,
            APR_JSON_FLAGS_WHITESPACE, 10, p);
    ABTS_INT_EQUAL(tc, APR_SUCCESS, status);

    val = apr_json_array_first(arr);
    ABTS_PTR_NOTNULL(tc, val);

    val = apr_json_array_next(arr, val);
    ABTS_PTR_NOTNULL(tc, val);

    val = apr_json_array_next(arr, val);
    ABTS_ASSERT(tc, "array next should return NULL",
            (val == NULL));

}

abts_suite *testjson(abts_suite * suite)
{
    suite = ADD_SUITE(suite);

    abts_run_test(suite, test_json_identity, NULL);
    abts_run_test(suite, test_json_level, NULL);
    abts_run_test(suite, test_json_eof, NULL);
    abts_run_test(suite, test_json_string, NULL);
    abts_run_test(suite, test_json_overlay, NULL);
    abts_run_test(suite, test_json_object_iterate, NULL);
    abts_run_test(suite, test_json_array_iterate, NULL);

    return suite;
}
