#pragma once


DECLARE_DELEGATE            (FWebSocketConnectedEvent);
DECLARE_DELEGATE_OneParam   (FWebSocketConnectionErrorEvent, const FString&/* ConnectionError */    );
DECLARE_DELEGATE_ThreeParams(FWebSocketClosedEvent,int64,/*StatusCode*/ const FString&,/* Reason,*/  bool/*bWasClean*/);
DECLARE_DELEGATE_OneParam   (FWebSocketMsgRecvEvent,         const FString& /* MessageString*/  );
DECLARE_DELEGATE_OneParam   (FWebSocketRawMsgRecvEvent,      const TArray<uint8>& /*Data*/		);

class FWebSocketConnection
{
public:
	FWebSocketConnection() = default;
	FWebSocketConnection(const FWebSocketConnection&) =delete;
	~FWebSocketConnection();
	void CreateWebSocket(const FString& Url, const FString& Protocol,const TMap<FString, FString>& Headers = TMap<FString, FString>());
	void Connect();
	void Close() const;
	bool IsConnected() const;
	void SendBinaryMessage(const TArray<uint8>& SendData) const;
public:
	FWebSocketConnectedEvent OnConnectedEvent;
	
	FWebSocketConnectionErrorEvent OnConnectionErrorEvent;
	
	FWebSocketClosedEvent OnCloseEvent;
	
	FWebSocketRawMsgRecvEvent OnRawMsgRecvEvent;
private:
	void OnConnected();
	void OnConnectionError(const FString & Error);
	void OnClosed(int32 Status, const FString& Reason, bool bWasClean) const;
	void OnRawMessage(const void* Data, SIZE_T Size, SIZE_T BytesRemaining);
private:
	TAtomic<bool> bIsConnecting {false} ;
	TSharedPtr<class IWebSocket> WebSocket = nullptr;
	TArray<uint8> TransientStorage;
};
