#include "OnlineState.h"
#include "Log/CsdkLogMacros.h"
#include "Log/LogChatSdk.h"
#include "../WebSocketConnection.h"
#include "Manager/CsdkSubsystem.h"
#include "Tools/Parser/TransData.h"
#include "Containers/Ticker.h"

constexpr int32 HeartBeatInterval =3;
constexpr int32 MaxHeartBeatCount =2;
constexpr float MaxHeartBeatInterval =120.f;

FOnlineState::~FOnlineState()
{
	Reset();
}

void FOnlineState::Enter()
{
	if(Manager.bHasLogin)//已登陆
	{
		FCsdkManager::GetInstance().Subsystem->OnReconnect.Broadcast();
	}

	CSDK_LOG(LogChatSdk,Log,TEXT("Enter OnlineState"));
	StartHeartBeat();
}

void FOnlineState::Leave()
{
	Reset();
	CSDK_LOG(LogChatSdk,Log,TEXT("Leave OnlineState"));
}

void FOnlineState::Reset()
{
	StopHeartBeat();
	HeartBeatCount = 0;
	Duration =0;
	KeepAliveDuration = 0;
} 

void FOnlineState::OnWebSocketNotify(const TArray<uint8>& Data)
{
	ResetHeartBeat();
	//CSDK_LOG(LogChatSdk,Log,TEXT("On websocket Recive"));
}

void FOnlineState::StartHeartBeat()
{
	TickerHandle = CSDK_Ticker::GetCoreTicker().AddTicker(FTickerDelegate::CreateRaw(this, &FOnlineState::HandleTick), 0.0f);
	CSDK_LOG(LogChatSdk,Log,TEXT("webSocket Heart Beat Started"));
}

void FOnlineState::StopHeartBeat()
{
	if(TickerHandle.IsValid())
	{
		CSDK_Ticker::GetCoreTicker().RemoveTicker(TickerHandle);
		TickerHandle.Reset();
	}
}

void FOnlineState::ResetHeartBeat()
{
	HeartBeatCount = 0;
	Duration = 0;
}

void FOnlineState::OnHeartBeat() const
{
#if !UE_BUILD_SHIPPING
	//CSDK_LOG(LogChatSdk,Log,TEXT("OnHeartBeat send"));
#endif
	const FTransData TransData = FTransData{ServerEOpCode::OpHeartbeat,TArray<uint8>{}};
	WebSocketConnection->SendBinaryMessage(TransData.Serialize());
	//CSDK_LOG(LogChatSdk,Log,TEXT("Heart beat send"));
}

void FOnlineState::HeartBeat(const float InDeltaTime)
{
	Duration += InDeltaTime;
	if(Duration>HeartBeatInterval)
	{
		++HeartBeatCount;
		Duration = 0;
		OnHeartBeat();
	}
}

void FOnlineState::FixTimeHeartBeat(const float InDeltaTime)
{
	KeepAliveDuration += InDeltaTime;
	if(KeepAliveDuration> MaxHeartBeatInterval)
	{
		KeepAliveDuration = 0;
		OnHeartBeat();
	}
}

bool FOnlineState::HandleTick(const float InDeltaTime)
{
	HeartBeat(InDeltaTime);
	FixTimeHeartBeat(InDeltaTime);
	
	if(HeartBeatCount >= MaxHeartBeatCount)
	{
		Reset();
		WebSocketConnection->Close();
		CSDK_LOG(LogChatSdk,Error,TEXT("Heart beat overtime. Need to Relogin"));
		//SwitchState(ELoginStateId::Offline);
	}
	return true;
}
