local H={}H.__index=H function H._MoveQueue(H)while#H._query_queue>0 do local e=table.remove(H._query_queue,1)task.spawn(e)if H._is_query_yielded==true then break end end end function H.NextAsync(e,H)if e._profile_store==nil then return nil end local d local s=false local function m()if e._query_failure==true then s=true return end if e._query_pages==nil then e._is_query_yielded=true task.spawn(function()d=e:NextAsync(true)s=true end)local H,m=pcall(function()e._query_pages=e._profile_store._global_data_store:ListVersionsAsync(e._profile_key,e._sort_direction,e._min_date,e._max_date)e._query_index=0 end)if H==false or e._query_pages==nil then warn("\091\080\114\111\102\105\108\101\083\101\114\118\105\099\101\093\058 \086\101\114\115\105\111\110 \113\117\101\114\121 \102\097\105\108 - "..tostring(m))e._query_failure=true end e._is_query_yielded=false e:_MoveQueue()return end local H=e._query_pages:GetCurrentPage()local m=H[e._query_index+1]if e._query_pages.IsFinished==true and m==nil then s=true return end if m==nil then e._is_query_yielded=true task.spawn(function()d=e:NextAsync(true)s=true end)local H=pcall(function()e._query_pages:AdvanceToNextPageAsync()e._query_index=0 end)if H==false or#e._query_pages:GetCurrentPage()==0 then e._query_failure=true end e._is_query_yielded=false e:_MoveQueue()return end e._query_index+=1 d=e._profile_store:ViewProfileAsync(e._profile_key,m.Version)s=true end if e._is_query_yielded==false then m()else if H==true then table.insert(e._query_queue,1,m)else table.insert(e._query_queue,m)end end while s==false do task.wait()end return d end
-- ProfileVersionQuery object:

local ProfileVersionQuery = {
	--[[
		_profile_store = profile_store,
		_profile_key = profile_key,
		_sort_direction = sort_direction,
		_min_date = min_date,
		_max_date = max_date,

		_query_pages = pages, -- [DataStoreVersionPages]
		_query_index = index, -- [number]
		_query_failure = false,

		_is_query_yielded = false,
		_query_queue = {},
	--]]
}
ProfileVersionQuery.__index = ProfileVersionQuery

function ProfileVersionQuery:_MoveQueue()
	while #self._query_queue > 0 do
		local queue_entry = table.remove(self._query_queue, 1)
		task.spawn(queue_entry)
		if self._is_query_yielded == true then
			break
		end
	end
end

function ProfileVersionQuery:NextAsync(_is_stacking) --> [Profile] or nil
	if self._profile_store == nil then
		return nil
	end

	local profile
	local is_finished = false

	local function query_job()
		if self._query_failure == true then
			is_finished = true
			return
		end

		-- First "next" call loads version pages:

		if self._query_pages == nil then
			self._is_query_yielded = true
			task.spawn(function()
				profile = self:NextAsync(true)
				is_finished = true
			end)

			local list_success, error_message = pcall(function()
				self._query_pages = self._profile_store._global_data_store:ListVersionsAsync(
					self._profile_key,
					self._sort_direction,
					self._min_date,
					self._max_date
				)
				self._query_index = 0
			end)

			if list_success == false or self._query_pages == nil then
				warn("[ProfileService]: Version query fail - " .. tostring(error_message))
				self._query_failure = true
			end

			self._is_query_yielded = false
			self:_MoveQueue()

			return
		end

		local current_page = self._query_pages:GetCurrentPage()
		local next_item = current_page[self._query_index + 1]

		-- No more entries:

		if self._query_pages.IsFinished == true and next_item == nil then
			is_finished = true
			return
		end

		-- Load next page when this page is over:

		if next_item == nil then
			self._is_query_yielded = true
			task.spawn(function()
				profile = self:NextAsync(true)
				is_finished = true
			end)

			local success = pcall(function()
				self._query_pages:AdvanceToNextPageAsync()
				self._query_index = 0
			end)

			if success == false or #self._query_pages:GetCurrentPage() == 0 then
				self._query_failure = true
			end

			self._is_query_yielded = false
			self:_MoveQueue()

			return
		end

		-- Next page item:

		self._query_index += 1
		profile = self._profile_store:ViewProfileAsync(self._profile_key, next_item.Version)
		is_finished = true
	end

	if self._is_query_yielded == false then
		query_job()
	else
		if _is_stacking == true then
			table.insert(self._query_queue, 1, query_job)
		else
			table.insert(self._query_queue, query_job)
		end
	end

	while is_finished == false do
		task.wait()
	end

	return profile
end
