#include "postgres.h"

#include <math.h>

#include "fmgr.h"
#include "plperl.h"
#include "utils/fmgrprotos.h"
#include "utils/jsonb.h"

PG_MODULE_MAGIC;

static SV  *Jsonb_to_SV(JsonbContainer *jsonb);
static JsonbValue *SV_to_JsonbValue(SV *obj, JsonbParseState **ps, bool is_elem);


static SV  *
JsonbValue_to_SV(JsonbValue *jbv)
{
	dTHX;

	switch (jbv->type)
	{
		case jbvBinary:
			return Jsonb_to_SV(jbv->val.binary.data);

		case jbvNumeric:
			{
				char	   *str = DatumGetCString(DirectFunctionCall1(numeric_out,
																	  NumericGetDatum(jbv->val.numeric)));
				SV		   *result = newSVnv(SvNV(cstr2sv(str)));

				pfree(str);
				return result;
			}

		case jbvString:
			{
				char	   *str = pnstrdup(jbv->val.string.val,
										   jbv->val.string.len);
				SV		   *result = cstr2sv(str);

				pfree(str);
				return result;
			}

		case jbvBool:
			return newSVnv(SvNV(jbv->val.boolean ? &PL_sv_yes : &PL_sv_no));

		case jbvNull:
			return newSV(0);

		default:
			elog(ERROR, "unexpected jsonb value type: %d", jbv->type);
			return NULL;
	}
}

static SV  *
Jsonb_to_SV(JsonbContainer *jsonb)
{
	dTHX;
	JsonbValue	v;
	JsonbIterator *it;
	JsonbIteratorToken r;

	it = JsonbIteratorInit(jsonb);
	r = JsonbIteratorNext(&it, &v, true);

	switch (r)
	{
		case WJB_BEGIN_ARRAY:
			if (v.val.array.rawScalar)
			{
				JsonbValue	tmp;

				if ((r = JsonbIteratorNext(&it, &v, true)) != WJB_ELEM ||
					(r = JsonbIteratorNext(&it, &tmp, true)) != WJB_END_ARRAY ||
					(r = JsonbIteratorNext(&it, &tmp, true)) != WJB_DONE)
					elog(ERROR, "unexpected jsonb token: %d", r);

				return JsonbValue_to_SV(&v);
			}
			else
			{
				AV		   *av = newAV();

				while ((r = JsonbIteratorNext(&it, &v, true)) != WJB_DONE)
				{
					if (r == WJB_ELEM)
						av_push(av, JsonbValue_to_SV(&v));
				}

				return newRV((SV *) av);
			}

		case WJB_BEGIN_OBJECT:
			{
				HV		   *hv = newHV();

				while ((r = JsonbIteratorNext(&it, &v, true)) != WJB_DONE)
				{
					if (r == WJB_KEY)
					{
						/* json key in v, json value in val */
						JsonbValue	val;

						if (JsonbIteratorNext(&it, &val, true) == WJB_VALUE)
						{
							SV		   *value = JsonbValue_to_SV(&val);

							(void) hv_store(hv,
											v.val.string.val, v.val.string.len,
											value, 0);
						}
					}
				}

				return newRV((SV *) hv);
			}

		default:
			elog(ERROR, "unexpected jsonb token: %d", r);
			return NULL;
	}
}

static JsonbValue *
AV_to_JsonbValue(AV *in, JsonbParseState **jsonb_state)
{
	dTHX;
	SSize_t		pcount = av_len(in) + 1;
	SSize_t		i;

	pushJsonbValue(jsonb_state, WJB_BEGIN_ARRAY, NULL);

	for (i = 0; i < pcount; i++)
	{
		SV		  **value = av_fetch(in, i, FALSE);

		if (value)
			(void) SV_to_JsonbValue(*value, jsonb_state, true);
	}

	return pushJsonbValue(jsonb_state, WJB_END_ARRAY, NULL);
}

static JsonbValue *
HV_to_JsonbValue(HV *obj, JsonbParseState **jsonb_state)
{
	dTHX;
	JsonbValue	key;
	SV		   *val;
	char	   *kstr;
	I32			klen;

	key.type = jbvString;

	pushJsonbValue(jsonb_state, WJB_BEGIN_OBJECT, NULL);

	(void) hv_iterinit(obj);

	while ((val = hv_iternextsv(obj, &kstr, &klen)))
	{
		key.val.string.val = pnstrdup(kstr, klen);
		key.val.string.len = klen;
		pushJsonbValue(jsonb_state, WJB_KEY, &key);
		(void) SV_to_JsonbValue(val, jsonb_state, false);
	}

	return pushJsonbValue(jsonb_state, WJB_END_OBJECT, NULL);
}

static JsonbValue *
SV_to_JsonbValue(SV *in, JsonbParseState **jsonb_state, bool is_elem)
{
	dTHX;
	JsonbValue	out;			/* result */

	/* Dereference references recursively. */
	while (SvROK(in))
		in = SvRV(in);

	switch (SvTYPE(in))
	{
		case SVt_PVAV:
			return AV_to_JsonbValue((AV *) in, jsonb_state);

		case SVt_PVHV:
			return HV_to_JsonbValue((HV *) in, jsonb_state);

		default:
			if (!SvOK(in))
			{
				out.type = jbvNull;
			}
			else if (SvUOK(in))
			{
				/*
				 * If UV is >=64 bits, we have no better way to make this
				 * happen than converting to text and back.  Given the low
				 * usage of UV in Perl code, it's not clear it's worth working
				 * hard to provide alternate code paths.
				 */
				const char *strval = SvPV_nolen(in);

				out.type = jbvNumeric;
				out.val.numeric =
					DatumGetNumeric(DirectFunctionCall3(numeric_in,
														CStringGetDatum(strval),
														ObjectIdGetDatum(InvalidOid),
														Int32GetDatum(-1)));
			}
			else if (SvIOK(in))
			{
				IV			ival = SvIV(in);

				out.type = jbvNumeric;
				out.val.numeric = int64_to_numeric(ival);
			}
			else if (SvNOK(in))
			{
				double		nval = SvNV(in);

				/*
				 * jsonb doesn't allow infinity or NaN (per JSON
				 * specification), but the numeric type that is used for the
				 * storage accepts those, so we have to reject them here
				 * explicitly.
				 */
				if (isinf(nval))
					ereport(ERROR,
							(errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
							 errmsg("cannot convert infinity to jsonb")));
				if (isnan(nval))
					ereport(ERROR,
							(errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
							 errmsg("cannot convert NaN to jsonb")));

				out.type = jbvNumeric;
				out.val.numeric =
					DatumGetNumeric(DirectFunctionCall1(float8_numeric,
														Float8GetDatum(nval)));
			}
			else if (SvPOK(in))
			{
				out.type = jbvString;
				out.val.string.val = sv2cstr(in);
				out.val.string.len = strlen(out.val.string.val);
			}
			else
			{
				/*
				 * XXX It might be nice if we could include the Perl type in
				 * the error message.
				 */
				ereport(ERROR,
						(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
						 errmsg("cannot transform this Perl type to jsonb")));
				return NULL;
			}
	}

	/* Push result into 'jsonb_state' unless it is a raw scalar. */
	return *jsonb_state
		? pushJsonbValue(jsonb_state, is_elem ? WJB_ELEM : WJB_VALUE, &out)
		: memcpy(palloc(sizeof(JsonbValue)), &out, sizeof(JsonbValue));
}


PG_FUNCTION_INFO_V1(jsonb_to_plperl);

Datum
jsonb_to_plperl(PG_FUNCTION_ARGS)
{
	dTHX;
	Jsonb	   *in = PG_GETARG_JSONB_P(0);
	SV		   *sv = Jsonb_to_SV(&in->root);

	return PointerGetDatum(sv);
}


PG_FUNCTION_INFO_V1(plperl_to_jsonb);

Datum
plperl_to_jsonb(PG_FUNCTION_ARGS)
{
	dTHX;
	JsonbParseState *jsonb_state = NULL;
	SV		   *in = (SV *) PG_GETARG_POINTER(0);
	JsonbValue *out = SV_to_JsonbValue(in, &jsonb_state, true);
	Jsonb	   *result = JsonbValueToJsonb(out);

	PG_RETURN_JSONB_P(result);
}
