// Fill out your copyright notice in the Description page of Project Settings.

#pragma once

#include "CoreMinimal.h"
#include "Message/Core/CsdkMessageBase.h"
#include "Message/Data/CsdkMsgPullDirection.h"
#include "Session/Data/CsdkSessionId.h"
#include "UObject/GCObject.h"
#include "UObject/NoExportTypes.h"

/*
 *消息环形数组,当队列满时不可从前插入，但是可以从后插入
 *当head和tail重合时队列为空
 *环形队列为半开半闭区间，[Head,Tail)
*/
class  FCsdkMessageRingBuffer : public FGCObject
{
public:
	FCsdkMessageRingBuffer(const FCsdkSessionId& InSessionId);
	virtual void AddReferencedObjects( FReferenceCollector& Collector ) override;
	virtual FString GetReferencerName() const override
	{
		return TEXT("FCsdkMessageRingBuffer");
	}
	bool TryPushFront(UCsdkMessageBase* Msg);
	void PushBack(UCsdkMessageBase* Msg);
	
	static  int32 Capacity();
	int32 Size() const;
	//TArray<UCsdkMessageBase*> GetAsArray() const;
	bool IsFull() const;
	bool IsEmpty() const;
	bool Contains(const FString& MsgId) const;
	void Empty();
	UCsdkMessageBase* operator[](int32 Index) const;
	
	TArray<UCsdkMessageBase*> GetFilteredMsgs( const FString& AnchorMsgId, const int32 DesiredPullCount,const ECsdkMsgPullDirection Direction) const;

	bool GetRemoteHeadHasMore() const
	{
		return bRemoteHeadHasMore;
	}

	void SetRemoteHeadHasMore(const bool bHeadHasMore)
	{
		bRemoteHeadHasMore = bHeadHasMore;
	}
private:
	UCsdkMessageBase* At(int32 Index) const;
	int32 GetIndexByAnchorId(const FString& AnchorMsgId) const;
private:
	FCsdkSessionId SessionId;
	TMap<FString,int32> MsgId2ArrayIndex;
	TArray<TObjectPtr<UCsdkMessageBase>> CachedMessages;
	int32 Head = 0;
	int32 Tail = 0;
	bool bRemoteHeadHasMore = true;
};


