#!/usr/bin/env tclsh

set testdir [file dirname $argv0]
source $testdir/tester.tcl

do_execsql_test json5-ecma-script-1 {
    select json('{a:5,b:6}') ;
} {{{"a":5,"b":6}}}

do_execsql_test json5-ecma-script-2 {
   SELECT json('{ MNO_123$xyz : 789 }');
} {{{"MNO_123$xyz":789}}}

do_execsql_test json5-with-single-trailing-comma-valid {
    select json('{"a":5, "b":6, }');
} {{{"a":5,"b":6}}}

do_execsql_test json5-single-quoted {
    SELECT json('{"a": ''abcd''}');
} {{{"a":"abcd"}}}

do_execsql_test json5-hexadecimal-1 {
   SELECT json('{a: 0x0}')
} {{{"a":0}}}

do_execsql_test json5-hexadecimal-2 {
   SELECT json('{a: 0xabcdef}')
} {{{"a":11259375}}}

do_execsql_test json5-hexadecimal-2 {
   SELECT json('{a: -0xabcdef}')
} {{{"a":-11259375}}}

do_execsql_test json5-number-1 {
   SELECT json('{x: 4.}')
} {{{"x":4.0}}}

do_execsql_test json5-number-2 {
   SELECT json('{x: +4.}')
} {{{"x":4.0}}}

do_execsql_test json5-number-3 {
   SELECT json('{x: -4.}')
} {{{"x":-4.0}}}

do_execsql_test json5-number-5 {
   SELECT json('{x: Infinity}')
} {{{"x":9e999}}}

do_execsql_test json5-number-6 {
   SELECT json('{x: -Infinity}')
} {{{"x":-9e999}}}

do_execsql_test json5-multi-comment {
   SELECT json(' /* abc */ { /*def*/ aaa /* xyz */ : // to the end of line
          123 /* xyz */ , /* 123 */ }')
} {{{"aaa":123}}}

do_execsql_test json_array_str {
   SELECT json_array('a')
} {{["a"]}}

do_execsql_test json_array_numbers {
   SELECT json_array(1, 1.5)
} {{[1,1.5]}}

do_execsql_test json_array_numbers_2 {
   SELECT json_array(1., +2., -2.)
} {{[1.0,2.0,-2.0]}}

do_execsql_test json_array_null {
   SELECT json_array(null)
} {{[null]}}

do_execsql_test json_array_not_json {
   SELECT json_array('{"a":1}')
} {{["{\"a\":1}"]}}

do_execsql_test json_array_json {
   SELECT json_array(json('{"a":1}'))
} {{[{"a":1}]}}

do_execsql_test json_array_nested {
   SELECT json_array(json_array(1,2,3), json('[1,2,3]'), '[1,2,3]')
} {{[[1,2,3],[1,2,3],"[1,2,3]"]}}


do_execsql_test json_extract_null {
    SELECT json_extract(null, '$')
} {{}}

do_execsql_test json_extract_empty {
    SELECT json_extract()
} {{}}

do_execsql_test json_extract_single_param {
    SELECT json_extract(1)
} {{}}

do_execsql_test json_extract_null_invalid_path {
    SELECT json_extract(null, 1)
} {{}}

do_execsql_test json_extract_null_invalid_path_2 {
    SELECT json_extract(null, CAST(1 AS BLOB))
} {{}}

do_execsql_test json_extract_multiple_nulls {
    SELECT json_extract(null, CAST(1 AS BLOB), null, 1, 2, 3)
} {{}}

do_execsql_test json_extract_number {
    SELECT json_extract(1, '$')
} {{1}}

do_execsql_test json_extract_object_1 {
    SELECT json_extract('{"a": [1,2,3]}', '$.a')
} {{[1,2,3]}}

do_execsql_test json_extract_object_2 {
    SELECT json_extract('{"a": [1,2,3]}', '$.a', '$.a[0]', '$.a[1]', '$.a[3]')
} {{[[1,2,3],1,2,null]}}

do_execsql_test json_extract_object_3 {
    SELECT json_extract('{"a": [1,2,3]}', '$.a', '$.a[0]', '$.a[1]', null, '$.a[3]')
} {{}}

# TODO: fix me - this passes on SQLite and needs to be fixed in Limbo.
#       \x61 is the ASCII code for 'a'
# do_execsql_test json_extract_with_escaping {
#     SELECT json_extract('{"\x61": 1}', '$.a')
# } {{1}}

# TODO: fix me - this passes on SQLite and needs to be fixed in Limbo.
#do_execsql_test json_extract_with_escaping_2 {
#    SELECT json_extract('{"\x61": 1}', '$.\x61')
#} {{1}}

do_execsql_test json_extract_null_path {
    SELECT json_extract(1, null)
} {{}}

# TODO: fix me - this passes on SQLite and needs to be fixed in Limbo.
do_execsql_test json_extract_multiple_null_paths {
    SELECT json_extract(1, null, null, null)
} {{}}

# TODO: fix me - this passes on SQLite and needs to be fixed in Limbo.
#do_execsql_test json_extract_quote {
#  SELECT json_extract('{"\"":1 }', '$.\"')
#} {{1}}

# Overflows 2**32 is equivalent to 0
do_execsql_test json_extract_overflow_int32_1 {
  SELECT json_extract('[1,2,3]', '$[4294967296]')
} {{1}}

# Overflows 2**32 + 1 is equivalent to 1
do_execsql_test json_extract_overflow_int32_2 {
  SELECT json_extract('[1,2,3]', '$[4294967297]')
} {{2}}

# Overflows -2**32 - 1 is equivalent to -1
do_execsql_test json_extract_overflow_int32_3 {
  SELECT json_extract('[1,2,3]', '$[#-4294967297]')
} {{3}}

# Overflows -2**32 - 2 is equivalent to -2
do_execsql_test json_extract_overflow_int32_3 {
  SELECT json_extract('[1,2,3]', '$[#-4294967298]')
} {{2}}

# pow(2,63) + 1 == 9223372036854775808
do_execsql_test json_extract_overflow_int64 {
  SELECT json_extract('[1,2,3]', '$[9223372036854775808]');
} {{1}}

# TODO: fix me - this passes on SQLite and needs to be fixed in Limbo.
# pow(2, 127) + 1 == 170141183460469231731687303715884105729
#do_execsql_test json_extract_overflow_int128 {
#  SELECT json_extract('[1, 2, 3]', '$[170141183460469231731687303715884105729]');
#} {{2}}

# TODO: fix me - this passes on SQLite and needs to be fixed in Limbo.
#do_execsql_test json_extract_blob {
#  select json_extract(CAST('[1,2,3]' as BLOB), '$[1]')
#} {{2}}

do_execsql_test json_array_length {
   SELECT json_array_length('[1,2,3,4]');
} {{4}}

do_execsql_test json_array_length_empty {
   SELECT json_array_length('[]');
} {{0}}

do_execsql_test json_array_length_root {
  SELECT json_array_length('[1,2,3,4]', '$');
} {{4}}

do_execsql_test json_array_length_not_array {
  SELECT json_array_length('{"one":[1,2,3]}');
} {{0}}

do_execsql_test json_array_length_via_prop {
  SELECT json_array_length('{"one":[1,2,3]}', '$.one');
} {{3}}

do_execsql_test json_array_length_via_index {
  SELECT json_array_length('[[1,2,3,4]]', '$[0]');
} {{4}}

do_execsql_test json_array_length_via_index_not_array {
  SELECT json_array_length('[1,2,3,4]', '$[2]');
} {{0}}

do_execsql_test json_array_length_via_bad_prop {
  SELECT json_array_length('{"one":[1,2,3]}', '$.two');
} {{}}

do_execsql_test json_array_length_nested {
  SELECT json_array_length('{"one":[[1,2,3],2,3]}', '$.one[0]');
} {{3}}

do_execsql_test json_type_no_path {
  select json_type('{"a":[2,3.5,true,false,null,"x"]}')
} {{object}}

do_execsql_test json_type_root_path {
  select json_type('{"a":[2,3.5,true,false,null,"x"]}','$')
} {{object}}

do_execsql_test json_type_array {
  select json_type('{"a":[2,3.5,true,false,null,"x"]}','$.a')
} {{array}}

do_execsql_test json_type_integer {
  select json_type('{"a":[2,3.5,true,false,null,"x"]}','$.a[0]')
} {{integer}}

do_execsql_test json_type_real {
  select json_type('{"a":[2,3.5,true,false,null,"x"]}','$.a[1]')
} {{real}}

do_execsql_test json_type_true {
  select json_type('{"a":[2,3.5,true,false,null,"x"]}','$.a[2]')
} {{true}}

do_execsql_test json_type_false {
  select json_type('{"a":[2,3.5,true,false,null,"x"]}','$.a[3]')
} {{false}}

do_execsql_test json_type_null {
  select json_type('{"a":[2,3.5,true,false,null,"x"]}','$.a[4]')
} {{null}}

do_execsql_test json_type_text {
  select json_type('{"a":[2,3.5,true,false,null,"x"]}','$.a[5]')
} {{text}}

do_execsql_test json_type_NULL {
  select json_type('{"a":[2,3.5,true,false,null,"x"]}','$.a[6]')
} {{}}

do_execsql_test json_type_cast {
  select json_type(1)
} {{integer}}

do_execsql_test json_type_null_arg {
  select json_type(null)
} {{}}
