#ifndef URLFILE_CACHE_H__
#define URLFILE_CACHE_H__

#include "maxon/interfacebase.h"
#include "maxon/url.h"


namespace maxon
{

class UrlFileCacheEntry;

//----------------------------------------------------------------------------------------
/// Flags used by UrlFileCacheInterface::FindOrCreateUrl
//----------------------------------------------------------------------------------------
enum class URLFILECACHEFLAGS
{
	NONE				 = 0,
	FORCE_RELOAD = 1 << 0 ///< Reloads the file from the sourceUrl, a new cache file will be created. The previous cache file will stay until
												///  older UrlFileCacheEntries disappear.
} MAXON_ENUM_FLAGS(URLFILECACHEFLAGS);

//----------------------------------------------------------------------------------------
/// A cache entry generated by UrlFileCacheInterface::FindOrCreateUrl()
/// As long as you keep this reference the cache file will be stored in the temp folder.
/// As soon as the last reference the file will be kept for the maxCacheTime.
//----------------------------------------------------------------------------------------
class UrlFileCacheEntryInterface
{
	MAXON_INTERFACE_NONVIRTUAL(UrlFileCacheEntryInterface, MAXON_REFERENCE_CONST, "net.maxon.interface.urlfilecacheentry");

public:
	MAXON_METHOD Url GetSourceUrl() const;
	MAXON_METHOD Url GetCacheUrl() const;
};

//----------------------------------------------------------------------------------------
/// UrlFileCacheInterface offers helper functions to allow to access to files with unsupported URLSCHEMEs.
/// E.g. preset:// wont work with openexr because this lib needs a valid utf8 character path and InputStreams cannot be used to virtualize
/// the read. In that case you would write:
/// @code
/// 	maxon::Url url = MaxonConvert(name, MAXONCONVERTMODE::READ);
/// 	maxon::UrlFileCacheEntry fileCacheEntry;
///
/// 	if (!maxon::UrlFileCacheInterface::IsAccessible(url))
/// 	{
/// 		fileCacheEntry = maxon::UrlFileCacheInterface::FindOrCreateUrl(url) iferr_return;
/// 		url = fileCacheEntry.GetCacheUrl();
/// 	}
///
/// 	ifnoerr (maxon::BaseArray<Char> buffer = url.GetSystemPath().GetCString(maxon::StringEncodings::Utf8()))
/// 		return exr_load(buffer.GetFirst(), &wbm);
/// 	else
/// 		return IMAGERESULT::MISC_ERROR;
/// @endcode
//----------------------------------------------------------------------------------------
class UrlFileCacheInterface
{
	MAXON_INTERFACE_NONVIRTUAL(UrlFileCacheInterface, MAXON_REFERENCE_NONE, "net.maxon.interface.urlfilecache");

public:
	//----------------------------------------------------------------------------------------
	/// Check if the url scheme is directly accessible via fopen().
	/// @param[in] url								Url to check.
	/// @return												true if the url can accessed directly. false if the url needs a cached copy. in that case use
	///																UrlFileCacheInterface::FindOrCreateUrl() to create or find the cache file.
	//----------------------------------------------------------------------------------------
	static MAXON_METHOD Bool IsAccessible(const maxon::Url& url);

	//----------------------------------------------------------------------------------------
	/// Finds or creates a new UrlFileCacheEntry for the given source Url.
	/// @param[in] sourceUrl					Url to be cached.
	/// @param[in] maxCacheTime				Time to wait until to delete the cache file after it's not needed anymore.
	/// @param[in] flags							See URLFILECACHEFLAGS.
	/// @return												A UrlFileCacheEntry which ensures the existence of the cache file as long as any reference to this
	///																handle exists.
	//----------------------------------------------------------------------------------------
	static MAXON_METHOD Result<UrlFileCacheEntry> FindOrCreateUrl(
		const Url& sourceUrl, const TimeValue& maxCacheTime = Seconds(1.0), URLFILECACHEFLAGS flags = URLFILECACHEFLAGS::NONE);

	//----------------------------------------------------------------------------------------
	/// Flushes the url from the cache. Existing UrlFileCacheEntries keep alive until the last handle vanishes.
	/// Calling the FindOrCreateUrl will create a new cache file for this url.
	//----------------------------------------------------------------------------------------
	static MAXON_METHOD Result<void> FlushCache(const Url& url);
};

#include "urlfile_cache1.hxx"
#include "urlfile_cache2.hxx"

}

#endif // URLFILE_CACHE_H__
