typedef enum JsonToIndex {
	jtiKey		= 0x01,
	jtiString	= 0x02,
	jtiNumeric	= 0x04,
	jtiBool		= 0x08,
	jtiAll		= jtiKey | jtiString | jtiNumeric | jtiBool
} JsonToIndex;

static uint32
parse_jsonb_index_flags(Jsonb *jb)
{
	JsonbIterator *it;
	JsonbValue  v;
	JsonbIteratorToken type;
	uint32				flags = 0;

	it = JsonbIteratorInit(&jb->root);

	type = JsonbIteratorNext(&it, &v, false);

	if (type != WJB_BEGIN_ARRAY)
		elog(ERROR, "wrong flag type");

	while ((type = JsonbIteratorNext(&it, &v, false)) == WJB_ELEM)
	{
		if (v.type != jbvString)
			elog(ERROR, "text is only accepted");

		if (v.val.string.len == 3 &&
				 pg_strncasecmp(v.val.string.val, "all", 3) == 0)
			flags |= jtiAll;
		else if (v.val.string.len == 3 &&
				 pg_strncasecmp(v.val.string.val, "key", 3) == 0)
			flags |= jtiKey;
		else if (v.val.string.len == 6 &&
				 pg_strncasecmp(v.val.string.val, "string", 5) == 0)
			flags |= jtiString;
		else if (v.val.string.len == 7 &&
				 pg_strncasecmp(v.val.string.val, "numeric", 7) == 0)
			flags |= jtiNumeric;
		else if (v.val.string.len == 7 &&
				 pg_strncasecmp(v.val.string.val, "boolean", 7) == 0)
			flags |= jtiBool;
		else
			elog(ERROR, "string, numeric, boolean, key and all are only accepted");
	}

	if (type != WJB_END_ARRAY)
		elog(ERROR, "wrong flag type");

	JsonbIteratorNext(&it, &v, false);

	return flags;
}


/*
 * Worker function for jsonb(_all)_to_tsvector(_byid)
 */
static TSVector
jsonb_to_tsvector_worker(Oid cfgId, Jsonb *jb, uint32 flags)
{
	TSVectorBuildState state;
	ParsedText	prs;
	JsonbIterator *it;
	JsonbValue  v;
	JsonbIteratorToken type;

	prs.words = NULL;
	prs.curwords = 0;
	state.prs = &prs;
	state.cfgId = cfgId;


	it = JsonbIteratorInit(&jb->root);

	type = JsonbIteratorNext(&it, &v, false);

	while ((type = JsonbIteratorNext(&it, &v, false)) != WJB_DONE)
	{
		if (type == WJB_KEY && (flags & jtiKey))
			add_to_tsvector(&state, v.val.string.val, v.val.string.len);
		else if (type == WJB_VALUE || type == WJB_ELEM)
		{
			switch(v.type)
			{
				case jbvString:
					if (flags & jtiString)
						add_to_tsvector(&state, v.val.string.val,
										v.val.string.len);
					break;
				case jbvNumeric:
					if (flags & jtiNumeric)
					{
						char *val;

						val = DatumGetCString(DirectFunctionCall1(numeric_out,
											  NumericGetDatum(v.val.numeric)));

						add_to_tsvector(&state, val, strlen(val));
					}
					break;
				case jbvBool:
					if (flags & jtiBool)
					{
						if (v.val.boolean)
							add_to_tsvector(&state, pstrdup("true"), 4);
						else
							add_to_tsvector(&state, pstrdup("false"), 5);
					}
					break;
				default:
					break;
			}
		}
	}

	return make_tsvector(&prs);
}
