//==============================================================================
//
//  OvenMediaEngine
//
//  Created by Hyunjun Jang
//  Copyright (c) 2020 AirenSoft. All rights reserved.
//
//==============================================================================
#include "push.h"
#include "common.h"

namespace serdes
{
	static void SetPushStreamTrackIds(Json::Value &parent_object, const char *key, const std::shared_ptr<info::Push> &push, Optional optional)
	{
		CONVERTER_RETURN_IF(false, Json::arrayValue);

		for (auto &item : push->GetTrackIds())
		{
			object.append(item);
		}
	}

	static void SetPushStreamVariantNames(Json::Value &parent_object, const char *key, const std::shared_ptr<info::Push> &push, Optional optional)
	{
		CONVERTER_RETURN_IF(false, Json::arrayValue);

		for (auto &item : push->GetVariantNames())
		{
			object.append(item.CStr());
		}
	}

	static void SetPushStream(Json::Value &parent_object, const char *key, const std::shared_ptr<info::Push> &push, Optional optional)
	{
		CONVERTER_RETURN_IF(false, Json::objectValue);

		SetString(object, "name", push->GetStreamName(), Optional::False);
		SetPushStreamTrackIds(object, "trackIds", push, Optional::False);
		SetPushStreamVariantNames(object, "variantNames", push, Optional::False);

	}
			
	// Example of Push Start
	// ----------------------
	// 	{
	// 		"id": "<CustomId | AutoGeneratedId>",
	//
	// 		"stream" : {
	// 			"name" : "<OutputStreamName>",
	// 			"trackIds" : [ 101, 102 ],
	// 			"variantNames" : [ "encodes_name_h264", "encodes_name_aac" ]
	// 		}
	//
	//   	"protocol":"rtmp",
	//		"url":"rtmp://127.0.0.1:1935/app",
	// 		"streamKey":"stream"
	//
	//  }

	// Example of Push Stop
	// ----------------------
	// 	{
	// 		"id": "<CustomId | AutoGeneratedId>"
	// 	}
	std::shared_ptr<info::Push> PushFromJson(const Json::Value &json_body)
	{
		auto push = std::make_shared<info::Push>();

		// <Optional>
		if(json_body.isMember("id"))
		{
			auto json_id = json_body["id"];
			if(json_id.empty() == false && json_id.isString() == true)
			{
				push->SetId(json_id.asString().c_str());			
			}
		}

		// <Required>
		if(json_body.isMember("stream"))
		{
			auto json_stream = json_body["stream"];
			if(json_stream.empty() == false && json_stream.isObject() == true)
			{
				// <Required>
				if(json_stream.isMember("name"))
				{
					auto json_stream_name = json_stream["name"];
					if(json_stream_name.empty() == false && json_stream_name.isString() == true)
					{
						push->SetStreamName(json_stream_name.asString().c_str());
					}
				}				

				// <Optional>
				auto json_stream_track_ids = json_stream["trackIds"];
				if(json_stream_track_ids.empty() == true)
				{
					json_stream_track_ids = json_stream["tracks"];
				}
				if (json_stream_track_ids.empty() == false && json_stream_track_ids.isArray() == true)
				{
					for (uint32_t i = 0; i < json_stream_track_ids.size(); i++)
					{
						if (json_stream_track_ids[i].isInt())
						{
							push->AddTrackId(json_stream_track_ids[i].asInt());
						}
					}
				}

				// <Optional>
				auto json_stream_variant_names = json_stream["variantNames"];
				if (json_stream_variant_names.empty() == false && json_stream_variant_names.isArray() == true)
				{
					for (uint32_t i = 0; i < json_stream_variant_names.size(); i++)
					{
						if (json_stream_variant_names[i].isString())
						{
							push->AddVariantName(json_stream_variant_names[i].asString().c_str());
						}
					}
				}
			}
		}

		if(json_body.isMember("protocol"))
		{
			auto json_protocol = json_body["protocol"];
			if(json_protocol.empty() == false && json_protocol.isString() == true)
			{
				push->SetProtocol(json_protocol.asString().c_str());			
			}
		}
				
		if(json_body.isMember("url"))
		{
			auto json_url = json_body["url"];
			if(json_url.empty() == false && json_url.isString() == true)
			{
				push->SetUrl(json_url.asString().c_str());			
			}
		}

		if(json_body.isMember("streamKey"))
		{
			auto json_stream_key = json_body["streamKey"];
			if(json_stream_key.empty() == false && json_stream_key.isString() == true)
			{
				push->SetStreamKey(json_stream_key.asString().c_str());			
			}
		}

		return push;
	}

	Json::Value JsonFromPush(const std::shared_ptr<info::Push> &push)
	{
		Json::Value response(Json::ValueType::objectValue);
	
		SetString(response, "id", push->GetId(), Optional::False);
		SetString(response, "vhost", push->GetVhost(), Optional::False);
		SetString(response, "app", push->GetApplication(), Optional::False);
		SetPushStream(response, "stream", push, Optional::True);
		SetString(response, "state", push->GetStateString(), Optional::False);
		SetString(response, "protocol", push->GetProtocol(), Optional::False);
		SetString(response, "url", push->GetUrl(), Optional::False);
		SetString(response, "streamKey", push->GetStreamKey(), Optional::False);
		SetInt64(response, "sentBytes", push->GetPushBytes());
		SetInt64(response, "sentTime", push->GetPushTime());
		SetInt64(response, "totalsentBytes", push->GetPushTotalBytes());
		SetInt64(response, "totalsentTime", push->GetPushTotalTime());			
		SetInt(response, "sequence", push->GetSequence());
		SetTimestamp(response, "startTime", push->GetPushStartTime());
		SetTimestamp(response, "finishTime", push->GetPushStopTime());
		SetTimestamp(response, "createdTime", push->GetCreatedTime());
		SetBool(response, "isConfig", push->IsByConfig());

		return response;
	}	

}  // namespace serdes