#pragma once

#include "TwitchInGames.h"
#include "http/HttpRequest.h"

namespace TwitchInGames {
#ifdef _DEBUG
	void DebugWriteLine_(string_t format, ...);
# define DebugWriteLine(...) DebugWriteLine_(__VA_ARGS__)
#else
# define DebugWriteLine(...) ((void)0)
#endif
	tstring ExtractToken(tstring const& s, string_t name= _T("token"));

	template<typename FN>
	auto LockedOperation(std::mutex& m, FN fn) {
		std::lock_guard<decltype(m)> lock(m);
		return fn();
	}

	inline void ThrowIfFailed(int result) {
		if(result < 0) {
			throw TwitchException(result);
		}
	}

	inline void ThrowIfResponseFailed(HttpResponse const& httpResponse) {
		if(httpResponse.Result) {
			throw TwitchException(httpResponse.Result);
		}
		if(!HttpResponse::IsSuccessful(httpResponse.ResultCode)) {
			throw TwitchException(httpResponse.ResultCode);
		}
	}

	template<typename R, typename T>
	struct Handle {
		Handle(T value, std::function<R(T)> destroyFn) : value(value), destroyFn(destroyFn) {}
		~Handle() { destroyFn(value); }
		operator T() const { return value; }

	private:
		T value;
		std::function<R(T)> destroyFn;
	};

#ifdef _WIN32
# if WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_DESKTOP)
	struct RegKey {
		RegKey() : key(HKEY()) {}
		~RegKey() { RegCloseKey(key); }
		HKEY* operator&() { return &key; }
		operator HKEY() const { return key; }

	private:
		HKEY key;
	};
# endif
#endif

	tstring ToLowerCase(tstring const& s);
	std::string Base64Encode(std::vector<char> const& data);
	std::time_t ParseTime(std::string const& s);
	void SendTokenScienceEvent(tstring const& clientId, tstring const& token, tstring const& method, std::map<tstring, tstring> const& properties) noexcept;
	void SendUserScienceEvent(tstring const& clientId, tstring const& userId, tstring const& method, std::map<tstring, tstring> const& properties) noexcept;

#ifdef _WIN32
	std::string FromTstring(tstring const& s);
	tstring ToTstring(std::string const& s);
#else
	inline std::string FromTstring(tstring const& s) { return s; }
	inline tstring ToTstring(std::string const& s) { return s; }
# define _istspace isspace
#endif
#ifdef __APPLE__
	bool GetMacAddress(unsigned short* macAddress);
#endif
}
