// Copyright Epic Games, Inc. All Rights Reserved.

#pragma once

#include "CoreTypes.h"
#include "HeroAsyncWriter.h"
#include "Misc/OutputDeviceFile.h"
#include "Templates/UniquePtr.h"


class  FCsdkOutputDeviceFile : public FOutputDevice
{
public:
	/**
	* Constructor, initializing member variables.
	*
	* @param InFilename	Filename to use, can be nullptr. If null, a file name will be automatically generated. If a filename is specified but cannot be opened
	*                   because it is already open/used by another process, the implementation will try to generate a new name automatically, until the a file
	*                   is created or the number of trials exhausted (32). 
	* @param bDisableBackup If true, existing files will not be backed up
	* @param bCreateWriterLazily If true, delay the creation of the file until something needs to be written, otherwise, open it immediatedly.
	*/
	FCsdkOutputDeviceFile(const TCHAR* InFilename = nullptr, bool bDisableBackup = false, bool bAppendIfExists = false, bool bCreateWriterLazily = true);

	/**
	* Destructor to perform teardown
	*
	*/
	virtual  ~FCsdkOutputDeviceFile() override;
	
	//~ Begin FOutputDevice Interface.
	/**
	* Closes output device and cleans up. This can't happen in the destructor
	* as we have to call "delete" which cannot be done for static/ global
	* objects.
	*/
	virtual  void TearDown() override;

	/**
	* Flush the write cache so the file isn't truncated in case we crash right
	* after calling this function.
	*/
	virtual  void Flush() override;

	virtual void Serialize(const TCHAR* Data, ELogVerbosity::Type Verbosity, const class FName& Category, const double Time) override;
	//调用上一个接口
	virtual void Serialize(const TCHAR* Data, ELogVerbosity::Type Verbosity, const class FName& Category) override;
	virtual bool CanBeUsedOnAnyThread() const override
	{
		return true;
	}
	//~ End FOutputDevice Interface.

	/** 以时间戳创建备份文件，但在windows平台很可能会在CreateFileW时失败*/
	static void CreateBackupCopy(const TCHAR* Filename);

	/** 检查log文件是否含有backup字段 */
	static bool IsBackupCopy(const TCHAR* Filename);

	/*/** 添加一个Category #1#
	void IncludeCategory(const class FName& InCategoryName);*/
	
	/** AsyncWriter是否已创建*/
	FORCEINLINE bool HasWriter() const;

private:

	/** Writes to a file on a separate thread */
	FHeroAsyncWriter* AsyncWriter;
	/** Archive used by the async writer */
	FArchive* WriterArchive;

	TCHAR Filename[1024];
	//是否时追加
	bool bAppendIfExists;
	//是否死亡
	bool bDead;

	/*/** Internal data for category inclusion. Must be declared inside CPP file as it uses a TSet<FName> #1#
	struct FCategoryInclusionInternal;
	TUniquePtr<FCategoryInclusionInternal> CategoryInclusionInternal;*/

	/** If true, existing files will not be backed up */
	bool		bDisableBackup;
	
	/** 创建writer*/
	bool CreateWriter(uint32 MaxAttempts = 32);
	//只能输出UTF8-BOM头，否则报错
	void WriteByteOrderMarkToArchive(EByteOrderMark ByteOrderMark);
	//清理函数
	FORCEINLINE void Clear();
};