#ifndef _UPLOADMANAGER_H
#define _UPLOADMANAGER_H

#include <siaapi.h>
#include <SQLiteCpp/Database.h>
#include <SQLiteCpp/Exception.h>
#include <autothread.h>
#include <deque>
#include <siacurl.h>
#include <eventsystem.h>
#include <filepath.h>

NS_BEGIN(Sia)
NS_BEGIN(Api)

class SIADRIVE_EXPORTABLE CUploadManager :
	public CAutoThread
{
public:
	enum class _UploadStatus : unsigned
	{
		NotFound,
		Queued,
		Uploading,
		Complete
	};

	enum class _UploadErrorCode
	{
		Success,
		SourceFileNotFound,
		DatabaseError,
    RenameFileFailed,
    RenameFolderFailed
	};

private:
	typedef struct
	{
		std::uint64_t Id;
		SString SiaPath;
		SString FilePath;
		SString TempPath;
		_UploadStatus Status;
	} UploadData;

public:
	CUploadManager(CSiaDriveConfig* siaDriveConfig, const CSiaApi& siaApi);

public:
	virtual ~CUploadManager();

private:
  CSiaDriveConfig* _siaDriveConfig;
  const CSiaApi& _siaApi;
	SQLite::Database _uploadDatabase;
	std::mutex _uploadMutex;
  std::shared_ptr<json> _uploadFileList;

private:
  void CleanUploadDatabase(CSiaDriveConfig* siaDriveConfig);
	void DeleteFilesRemovedFromSia(CSiaDriveConfig* siaDriveConfig, const bool& isStartup = false);
  CSiaDriveConfig& GetSiaDriveConfig() const { return *_siaDriveConfig; }
	void HandleFileRemove(const SString& siaPath);
  void UpdateDatabaseAfterRename(const SString& siaPath, const SString& newSiaPath);

protected:
	virtual void AutoThreadCallback(CSiaDriveConfig* siaDriveConfig) override;

public:
	static SString UploadStatusToString(const _UploadStatus& uploadStatus);

public:
  CSiaError<_UploadErrorCode> AddOrUpdate(const SString& siaPath, SString filePath, const std::uint64_t& lastModified);
	_UploadStatus GetUploadStatus(const SString& siaPath);
  CSiaError<_UploadErrorCode> Remove(const SString& siaPath);
  CSiaError<_UploadErrorCode> RenameFile(const SString& siaPath, const SString& newSiaPath);
  CSiaError<_UploadErrorCode> RenameFolder(const SString& siaPath, const SString& newSiaPath);
  std::shared_ptr<json> GetUploadFileList() const;
};

typedef CUploadManager::_UploadStatus UploadStatus;
typedef CUploadManager::_UploadErrorCode UploadErrorCode;
typedef CSiaError<CUploadManager::_UploadErrorCode> UploadError;

NS_END(2)

#endif //_UPLOADMANAGER_H