#include <ZUtil/ZJSONReader.hpp>

#include <ZSTL/ZString.hpp>
#include <ZSTL/ZBasicStringAlgo.hpp>
#include <jansson.h>

/* iterate over the values, adding to the KVTree as needed */
static void recurse_and_populate ( json_t* _object, void* _itr, ZKVTree& _storage, ZString _currPath )
{
	/* for each key-value pair in the object...*/
	while (_itr != NULL)
	{
		json_t* val = json_object_iter_value(_itr);

		if ( json_is_array ( val ) )
		{			

			/*
			TODO:
			What happens if we have an array of arrays? An array of objects?
			*/
			size_t arraySize = json_array_size(val);			
			for (size_t i = 0; i < arraySize; i++)
			{
				ZBasicStringAlgo::BuildPrintf(_currPath,"%s.%s[%d]", _currPath.Data(), json_object_iter_key(_itr), i );
				json_t* data = json_array_get(val, i);
				_storage.Put( _currPath, json_string_value(data) );
			}						
		}
		else if ( json_is_object( val ) == false)
		{
			/* store the pair if it just a value...*/
			ZBasicStringAlgo::BuildPrintf(_currPath,"%s.%s", _currPath.Data(), json_object_iter_key(_itr) );
			json_t* data= json_object_iter_value( _itr );
			_storage.Put( _currPath, json_string_value(data) );
		}
		else
		{
			/*...or parse it if it isn't */
			_currPath = ZString( json_object_iter_key(_itr)) + ".";
			recurse_and_populate( _object, _itr, _storage, _currPath );
		}

		_itr = json_object_iter_next( _object, _itr );
	}
}

ZJSONReader::ZJSONReader(const ZString& _jsonData)
: ErrorMessage(), JSONData(_jsonData), Registry(new (std::nothrow) ZKVTree())
{
	json_t* rootNode;

	if (Registry == NULL)
	{
		ErrorMessage = "ZJSONReader: unable to create registry!";
		return;
	}

	/* have Jansson parse the string out and make an object */
	json_error_t error;
	rootNode = json_loads( _jsonData.Data(), 0, &error);
	if (rootNode == NULL)
	{
		ZBasicStringAlgo::BuildPrintf(ErrorMessage, "ZJSONReader: %s on line %d", error.text, error.line);
		return;
	}

	/* now, we parse it out */
	void* itr = json_object_iter(rootNode);
	recurse_and_populate( rootNode, itr, *Registry, "");
}

const ZString& ZJSONReader::GetErrorString()
{
	return this->ErrorMessage;
}

ZPtr<ZKVTree> ZJSONReader::GetKVTree()
{
	return this->Registry;
}