local K=require(script.Parent.Promise)local M={}M.__index=M local D={HttpService={"\071\101\116\065\115\121\110\099","\080\111\115\116\065\115\121\110\099","\082\101\113\117\101\115\116\065\115\121\110\099"};DataStoreService={"\071\101\116\068\097\116\097\083\116\111\114\101"},GlobalDataStore={"\083\101\116\065\115\121\110\099";"\071\101\116\065\115\121\110\099","\082\101\109\111\118\101\065\115\121\110\099","\085\112\100\097\116\101\065\115\121\110\099";"\073\110\099\114\101\109\101\110\116\065\115\121\110\099"};MarketplaceService={"\085\115\101\114\079\119\110\115\071\097\109\101\080\097\115\115\065\115\121\110\099";"\080\108\097\121\101\114\079\119\110\115\065\115\115\101\116","\071\101\116\068\101\118\101\108\111\112\101\114\080\114\111\100\117\099\116\115\065\115\121\110\099","\071\101\116\080\114\111\100\117\099\116\073\110\102\111"},BadgeService={"\065\119\097\114\100\066\097\100\103\101","\071\101\116\066\097\100\103\101\073\110\102\111\065\115\121\110\099";"\085\115\101\114\072\097\115\066\097\100\103\101\065\115\121\110\099"}}local function b(M)local a=D[M.ClassName]if a then local D={}for a,U in next,a do D[U]=function(D,...)local a={...}return K.new(function(K,D)spawn(function()local Z,A=pcall(M[U],M,unpack(a))if Z then if typeof(A)=="\073\110\115\116\097\110\099\101"then K(b(A))else K(A)end else D(A)end end)end)end end return setmetatable(D,{__index=M;__tostring=function()return"\065\115\121\110\099\087\114\097\112\112\101\114\040"..(tostring(M).."\041")end})else return M end end function M.wrap(K)return b(K)end function M.GetService(M,K)local D=game:GetService(K)return b(D)end function M.default(M,D)assert(typeof(D)=="\102\117\110\099\116\105\111\110")return function(...)local M={...}return K.new(function(K,b)local a,U=pcall(D,unpack(M))if a then K(U)else b(U)end end)end end M.__call=M.default return setmetatable({},M)
--[[
	Creates Async methods
]]
local Promise = require(script.Parent.Promise)

local Promisify = {}
Promisify.__index = Promisify

--[[
	Used to await RBXScriptSignals, for single use events
	e.g.

	Players.PlayerAdded:Connect(function(player)
		Promisify:await(player.CharacterAdded):andThen(function(character)
			-- do stuff with character...
		end)
	end)
]]
-- function Promisify.from(signal)
-- 	assert(typeof(signal) == "RBXScriptSignal" or (typeof(signal) == "table" and typeof(signal.Wait) == "function"))
-- 	return Promise.new(
-- 		function(resolve, reject)
-- 			local results = {signal:Wait()}
-- 			resolve(unpack(results))
-- 		end
-- 	)
-- end

-- luacov: disable
local wrappable = {
	HttpService = {"GetAsync", "PostAsync", "RequestAsync"},
	DataStoreService = {"GetDataStore"},
	GlobalDataStore = {"SetAsync", "GetAsync", "RemoveAsync", "UpdateAsync", "IncrementAsync"},
	MarketplaceService = {"UserOwnsGamePassAsync", "PlayerOwnsAsset", "GetDeveloperProductsAsync", "GetProductInfo"},
	BadgeService = {"AwardBadge", "GetBadgeInfoAsync", "UserHasBadgeAsync"}
}
local function createAsyncWrapperFor(object)
	local wrapperList = wrappable[object.ClassName]
	if wrapperList then
		local asyncWrappers = {}
		for _, method in next, wrapperList do
			asyncWrappers[method] = function(_, ...)
				local argList = {...}
				return Promise.new(
					function(resolve, reject)
						-- Spawn to prevent yielding, since GetAsync yields.
						spawn(
							function()
								local ok, result = pcall(object[method], object, unpack(argList))

								if ok then
									if typeof(result) == "Instance" then
										resolve(createAsyncWrapperFor(result))
									else
										resolve(result)
									end
								else
									reject(result)
								end
							end
						)
					end
				)
			end
		end

		return setmetatable(
			asyncWrappers,
			{
				__index = object,
				__tostring = function()
					return "AsyncWrapper(" .. tostring(object) .. ")"
				end
			}
		)
	else
		return object
	end
end

-- Will wrap yielding methods as async methods
function Promisify.wrap(object)
	return createAsyncWrapperFor(object)
end

-- Gets a promise wrapped version of a service
function Promisify:GetService(serviceName)
	local service = game:GetService(serviceName)
	return createAsyncWrapperFor(service)
end
-- luacov: enable

function Promisify.default(_, value)
	assert(typeof(value) == "function")

	return function(...)
		local argList = {...}
		return Promise.new(
			function(resolve, reject)
				local ok, result = pcall(value, unpack(argList))
				if ok then
					resolve(result)
				else
					reject(result)
				end
			end
		)
	end
end
Promisify.__call = Promisify.default

return setmetatable({}, Promisify)
