#include "jsonBuilder.h"


#include <rapidjson/writer.h>
#include <rapidjson/stringbuffer.h>
#include <rapidjson/prettywriter.h>
#include "constdef.h"

namespace YA
{

	jsonBuilder::jsonBuilder()
	{


	}

	jsonBuilder::~jsonBuilder()
	{

	}

	void jsonBuilder::__AddVersion( rapidjson::Value& root, rapidjson::Document::AllocatorType& allocator )
	{
		rapidjson::Value key( rapidjson::kStringType );
		rapidjson::Value value( rapidjson::kStringType );

		key.SetString( JSON_ROOT_KEY_VERSION, allocator );
		value.SetString( JASON_CURRENT_VERSION, allocator );
		root.AddMember( key, value, allocator );
	}

	std::string jsonBuilder::BuildLogin( const _JS_LOGIN_& Login )
	{
		rapidjson::StringBuffer sb;
		rapidjson::Writer<rapidjson::StringBuffer> writer( sb );

		rapidjson::Document doc;

		rapidjson::Document::AllocatorType& allocator = doc.GetAllocator();
		rapidjson::Value root( rapidjson::kObjectType );
		rapidjson::Value child( rapidjson::kObjectType );
		rapidjson::Value key( rapidjson::kStringType );
		rapidjson::Value value( rapidjson::kStringType );

		key.SetString( JSON_ROOT_KEY_CMD, allocator );
		value.SetString( JASON_CMD_LOGIN, allocator );
		root.AddMember( key, value, allocator );

		key.SetString( JSON_KEY_USERNAME, allocator );
		value.SetString( Login.user_name.c_str(), allocator );
		child.AddMember( key, value, allocator );

		key.SetString( JSON_KEY_PASSWORD, allocator );
		value.SetString( Login.user_password.c_str(), allocator );
		child.AddMember( key, value, allocator );

		key.SetString( JSON_ROOT_KEY_DATA, allocator );
		root.AddMember( key, child, allocator );

		root.Accept( writer );

		return sb.GetString();
	}

	bool jsonBuilder::ParseCall_Card_Req( const std::string& JasonText, _JS_CALL_CARD_REQ_& CallCardReq, std::string& Error )
	{
		rapidjson::Document doc;
		if ( doc.Parse( JasonText.c_str() ).HasParseError() )
		{
			Error = "Failed to parse jason text!";
			return false;
		}

		rapidjson::Value::MemberIterator itValue;
		itValue = doc.FindMember( "data" );
		if ( itValue == doc.MemberEnd() )
		{
			Error = "Failed to find member: data!";
			return false;
		}

		rapidjson::Value Data;
		rapidjson::Document::AllocatorType allocator;
		Data.CopyFrom( itValue->value, allocator );

		if ( !Data.HasMember( JSON_KEY_CALL_CARD_CALL_TYPE ) )
		{
			Error = "Failed to find value: ";
			Error += JSON_KEY_CALL_CARD_CALL_TYPE;
			return false;
		}
		CallCardReq.call_type_id = Data[JSON_KEY_CALL_CARD_CALL_TYPE].GetInt();

		if ( !Data.HasMember( JSON_KEY_CALL_CARD_CALL_TIME_OUT ) )
		{
			Error = "Failed to find value: ";
			Error += JSON_KEY_CALL_CARD_CALL_TIME_OUT;
			return false;
		}
		CallCardReq.call_time_out = Data[JSON_KEY_CALL_CARD_CALL_TIME_OUT].GetInt();

		if ( !Data.HasMember( JSON_KEY_CALL_CARD_CALL_LEVEL ) )
		{
			Error = "Failed to find value: ";
			Error += JSON_KEY_CALL_CARD_CALL_LEVEL;
			return false;
		}
		CallCardReq.call_time_interval = Data[JSON_KEY_CALL_CARD_CALL_LEVEL].GetInt();

		if ( !Data.HasMember( JSON_KEY_CALL_CARD_USER_NAME ) )
		{
			Error = "Failed to find value: ";
			Error += JSON_KEY_CALL_CARD_USER_NAME;
			return false;
		}
		CallCardReq.user_name = Data[JSON_KEY_CALL_CARD_USER_NAME].GetString();

		//data::stations
		if ( !Data.HasMember( JSON_KEY_CALL_CARD_STATIONS ) )
		{
			Error = "Failed to find value: ";
			Error += JSON_KEY_CALL_CARD_STATIONS;
			return false;
		}
		rapidjson::Value & stations = Data[JSON_KEY_CALL_CARD_STATIONS];
		if ( !stations.IsArray() )
		{
			Error = "data::stations is not a valid array!";
			return false;
		}
		for ( int i = 0; i < stations.Size(); ++i )
		{
			rapidjson::Value & v = stations[i];
			if ( !v.IsObject() )
			{
				char szError[1024] = { 0 };
				sprintf( szError, "data::stations[%d] is not a object!", i );
				Error = szError;
				return false;
			}

			_JS_STATION_ Station;
			if ( !v.HasMember( JSON_KEY_CALL_CARD_STATION_ID ) && v[JSON_KEY_CALL_CARD_STATION_ID].IsInt() )
			{
				Error = "Error, failed to found value: ";
				Error += JSON_KEY_CALL_CARD_STATION_ID;
				return false;
			}
			Station.stationid = v[JSON_KEY_CALL_CARD_STATION_ID].GetInt();

			CallCardReq.stations.push_back( Station );
		}

		//data::cards
		if ( !Data.HasMember( JSON_KEY_CALL_CARD_CARDS ) )
		{
			Error = "Failed to find value: ";
			Error += JSON_KEY_CALL_CARD_CARDS;
			return false;
		}
		rapidjson::Value & cards = Data[JSON_KEY_CALL_CARD_CARDS];
		for ( int i = 0; i < cards.Size(); ++i )
		{
			rapidjson::Value & v = cards[i];
			if ( !v.IsObject() )
			{
				char szError[1024] = { 0 };
				sprintf( szError, "data::cards[%d] is not a object!", i );
				Error = szError;
				return false;
			}

			_JS_CARD_ Card;
			if ( !v.HasMember( JSON_KEY_CALL_CARD_CARD_ID ) && v[JSON_KEY_CALL_CARD_CARD_ID].IsInt() )
			{
				Error = "Error, failed to found value: ";
				Error += JSON_KEY_CALL_CARD_CARD_ID;
				return false;
			}
			Card.cardid = v[JSON_KEY_CALL_CARD_CARD_ID].GetInt();

			if ( !v.HasMember( JSON_KEY_CALL_CARD_CARD_TYPE_ID ) && v[JSON_KEY_CALL_CARD_CARD_TYPE_ID].IsInt() )
			{
				Error = "Error, failed to found value: ";
				Error += JSON_KEY_CALL_CARD_CARD_TYPE_ID;
				return false;
			}
			Card.cardtype = v[JSON_KEY_CALL_CARD_CARD_TYPE_ID].GetInt();

			CallCardReq.cards.push_back( Card );
		}

		return true;
	}
}