#include "MessageTool.h"

#include "Log/CsdkLogMacros.h"
#include "Common/CsdkStringConvert.h"
#include "Log/LogChatSdk.h"
#include "Manager/CsdkSubsystem.h"
#include "Message/Core/CsdkCustomMessage.h"
#include "Message/Core/CsdkEventMessage.h"
#include "Message/Core/CsdkTextMessage.h"
#include "Message/Core/CsdkVoiceMessage.h"
#include "Tools/CsdkCommonTools.h"
#include "User/Tool/UserTool.h"
#include "Policies/CondensedJsonPrintPolicy.h"

const FString VoiceMsgUrlKey =TEXT("url");
const FString VoiceMsgDurationKey =TEXT("duration");
const FString EventMsgTypeKey =TEXT("eventType");
const FString MsgDataKey =TEXT("data");
const FString CustomMsgTileKey =TEXT("title");

void FillMsgByPb(UCsdkMessageBase* const Msg, const heroim::client::v3beta::dto::message::model::Message& PbMsg)
{
	Msg->MsgId = STD_STRING_TO_FSTRING(PbMsg.msgid());
	Msg->ClientMsgId = STD_STRING_TO_FSTRING(PbMsg.clientmsgid());
	Msg->MsgType = MessageTool::ConvertStringToMsgType(PbMsg.msgtype());
	Msg->Time = FDateTime::FromUnixTimestamp(PbMsg.time()/1000);
	
	Msg->Status = static_cast<ECsdkMessageStatus::Type>(PbMsg.status());
	Msg->Sequence = PbMsg.sequence();
	Msg->Sender = CsdkUserTool::ConvertUser(PbMsg.fromuser());
	Msg->bIsSelf = Msg->Sender.Id == FCsdkCommonTools::GetUserManager().GetCurrentUserId();
	for(const auto& PbPayloadItem :PbMsg.payload())
	{
		Msg->Extra.Add(STD_STRING_TO_FSTRING(PbPayloadItem.first),STD_STRING_TO_FSTRING(PbPayloadItem.second));
	}
}

TObjectPtr<UCsdkTextMessage> NewTextMsg(UObject* Outer,const heroim::client::v3beta::dto::message::model::Message& PbMsg)
{
	auto Msg = NewObject<UCsdkTextMessage>(FCsdkManager::GetInstance().Subsystem);
	Msg->Content = STD_STRING_TO_FSTRING(PbMsg.content());

	FillMsgByPb(Msg,PbMsg);
	return Msg;
}

TObjectPtr<UCsdkVoiceMessage> NewVoiceMsg(UObject* Outer,const heroim::client::v3beta::dto::message::model::Message& PbMsg)
{
	auto Msg = NewObject<UCsdkVoiceMessage>(FCsdkManager::GetInstance().Subsystem);
	
	TSharedRef<TJsonReader<>> JsonReader = TJsonReaderFactory<TCHAR>::Create(STD_STRING_TO_FSTRING(PbMsg.content()));
	// 创建一个Json对象
	TSharedPtr<FJsonObject> JsonObject;
	// 反序列化，将JsonReader里面的数据，传到JsonObject中
	if(FJsonSerializer::Deserialize(JsonReader, JsonObject))
	{
		JsonObject->TryGetStringField(VoiceMsgUrlKey,Msg->Url);
		double Duration = 0.0;
		JsonObject->TryGetNumberField(VoiceMsgDurationKey,Duration);
		Msg->Duration = Duration;
		JsonObject->TryGetStringField(CustomMsgTileKey,Msg->Title);
	}
	FillMsgByPb(Msg,PbMsg);
	return Msg;
}

TObjectPtr<UCsdkEventMessage> NewEventMsg(UObject* Outer,const heroim::client::v3beta::dto::message::model::Message& PbMsg)
{
	auto Msg = NewObject<UCsdkEventMessage>(FCsdkManager::GetInstance().Subsystem);
	
	TSharedRef<TJsonReader<>> JsonReader = TJsonReaderFactory<TCHAR>::Create(STD_STRING_TO_FSTRING(PbMsg.content()));
	// 创建一个Json对象
	TSharedPtr<FJsonObject> JsonObject;
	// 反序列化，将JsonReader里面的数据，传到JsonObject中

	if(FJsonSerializer::Deserialize(JsonReader, JsonObject))
	{
		FString EventType;
		JsonObject->TryGetStringField(EventMsgTypeKey,EventType);
		
		if(EventType ==TEXT("HTE:RSFriendAdded"))
		{
			Msg->EventType = ECsdkEventMessageType::FriendAdded;
		}
		else if(EventType ==TEXT("HTE:GroupCreated"))
		{
			Msg->EventType = ECsdkEventMessageType::ChatRoomCreated;
		}
		else if(EventType ==TEXT("HTE:GroupQuited"))
		{
			Msg->EventType = ECsdkEventMessageType::ChatRoomQuited;
		}
		else if(EventType ==TEXT("HTE:GroupJoined"))
		{
			Msg->EventType = ECsdkEventMessageType::ChatRoomJoined;
		}
		else if(EventType ==TEXT("HTE:GroupMemberRemoved"))
		{
			Msg->EventType = ECsdkEventMessageType::ChatRoomMemberRemoved;
		}
		else if(EventType ==TEXT("HTE:GroupDismissed"))
		{
			Msg->EventType = ECsdkEventMessageType::ChatRoomDismissed;
		}

		FString Data;
		JsonObject->TryGetStringField(MsgDataKey,Data);
		Msg->SetData(Data);
	}

	FillMsgByPb(Msg,PbMsg);
	return Msg;
}

TObjectPtr<UCsdkCustomMessage> NewCustomMsg(UObject* Outer,const heroim::client::v3beta::dto::message::model::Message& PbMsg)
{
	auto Msg = NewObject<UCsdkCustomMessage>(FCsdkManager::GetInstance().Subsystem);
	
	TSharedRef<TJsonReader<>> JsonReader = TJsonReaderFactory<TCHAR>::Create(STD_STRING_TO_FSTRING(PbMsg.content()));
	// 创建一个Json对象
	TSharedPtr<FJsonObject> JsonObject;
	if(FJsonSerializer::Deserialize(JsonReader, JsonObject))
	{
		JsonObject->TryGetStringField(CustomMsgTileKey,Msg->Content);
		FillMsgByPb(Msg,PbMsg);
		return Msg;
	}
	return nullptr;
}

TObjectPtr<UCsdkMessageBase> MessageTool::NewMsgObj(UObject* Outer,
	const heroim::client::v3beta::dto::message::model::Message& PbMsg)
{
	UCsdkMessageBase* Msg = nullptr;
	const auto MsgType = ConvertStringToMsgType(PbMsg.msgtype());
	switch (MsgType)
	{
	
	case ECsdkMessageType::Text:
		Msg = NewTextMsg(Outer,PbMsg);
		break;
	case ECsdkMessageType::Voice:
		Msg = NewVoiceMsg(Outer,PbMsg);
		break;
	case ECsdkMessageType::Event:
		Msg = NewEventMsg(Outer,PbMsg);
		break;
	case ECsdkMessageType::Custom:
		Msg = NewCustomMsg(Outer,PbMsg);
		break;
	case ECsdkMessageType::At:
		break;
	case ECsdkMessageType::Invalid:
	default:
		CSDK_LOG(LogChatSdk,Error,TEXT("MsgType Is Invalid,MsgId:%s"),UTF8_TO_TCHAR( PbMsg.msgid().c_str()));
	}
	return Msg;
}



std::string MessageTool::ConvertMsgTypeToString(const ECsdkMessageType MessageType)
{
	switch (MessageType)
	{
	case ECsdkMessageType::Text:
		return "HT:text";
	case ECsdkMessageType::Voice:
		return "HT:voice";
	case ECsdkMessageType::Event:
		return "HT:event";
	case ECsdkMessageType::Custom:
		return "HT:custom";
	case ECsdkMessageType::At:
		return "HT:at";
	default:
		return "";
	}
}

ECsdkMessageType MessageTool::ConvertStringToMsgType(const std::string& Str)
{
	if(Str == "HT:text")
	{
		return ECsdkMessageType::Text;
	}
	else if(Str == "HT:voice")
	{
		return  ECsdkMessageType::Voice;
	}
	else if(Str == "HT:event")
	{
		return  ECsdkMessageType::Event;
	}
	else if(Str == "HT:custom")
	{
		return ECsdkMessageType::Custom;
	}
	else if(Str == "HT:at")
	{
		return ECsdkMessageType::At;
	}
	return ECsdkMessageType::Invalid;
}

FString GetVoiceContent(const UCsdkVoiceMessage* VoiceMessage)
{
	FString JsonStr;
	const TSharedRef<TJsonWriter<TCHAR, TCondensedJsonPrintPolicy<TCHAR>>> JsonWriter =
		TJsonWriterFactory<TCHAR, TCondensedJsonPrintPolicy<TCHAR>>::Create(&JsonStr);
	JsonWriter->WriteObjectStart();
	JsonWriter->WriteValue(VoiceMsgUrlKey, VoiceMessage->Url);
	JsonWriter->WriteValue(VoiceMsgDurationKey, VoiceMessage->Duration);
	JsonWriter->WriteValue(CustomMsgTileKey, VoiceMessage->Title);
	JsonWriter->WriteObjectEnd();
	JsonWriter->Close();

	CSDK_LOG(LogChatSdk,Log,TEXT("VoiceMessage Json: %s"),*JsonStr);
	return JsonStr;
}

FString GetCustomContent(UCsdkCustomMessage* Message)
{
	FString JsonStr;
	const TSharedRef<TJsonWriter<TCHAR, TCondensedJsonPrintPolicy<TCHAR>>> JsonWriter =
		TJsonWriterFactory<TCHAR, TCondensedJsonPrintPolicy<TCHAR>>::Create(&JsonStr);
	JsonWriter->WriteObjectStart();
	JsonWriter->WriteValue(CustomMsgTileKey, Message->Content);
	JsonWriter->WriteObjectEnd();
	JsonWriter->Close();

	CSDK_LOG(LogChatSdk,Log,TEXT("CustomMessage Json: %s"),*JsonStr);
	return JsonStr;
}


FString MessageTool::GetContent(UCsdkMessageBase* CsdkMessage)
{
	FString Content;
	switch (CsdkMessage->MsgType) {
	case ECsdkMessageType::Invalid:
		checkf(true,TEXT("Can't Send Invalid Message"));
		break;
	case ECsdkMessageType::Text:
		Content = Cast<UCsdkTextMessage>(CsdkMessage)->Content;
		break;
	case ECsdkMessageType::Voice:
		Content =GetVoiceContent(Cast<UCsdkVoiceMessage>(CsdkMessage));
		break;
	case ECsdkMessageType::Event:
		checkf(true,TEXT("Can't Send Event Message"));
		break;
	case ECsdkMessageType::Custom:
		Content =GetCustomContent(Cast<UCsdkCustomMessage>(CsdkMessage));
		break;
	case ECsdkMessageType::At:
		checkf(true,TEXT("Can't Send At Message, Todo"));
		break;
	default: ;
	}
	return Content;
}
