pg = pg or {}
slot0 = pg
slot0.MessageCache = class("MessageCache")
slot0.MessageCache.DEFAULT_QUEUE_LENGTH = 10000
slot0.MessageCache.CMD_KILL = "CMD_KILL"
slot0.MessageCache.CMD_PUSH = "CMD_PUSH"
slot0.MessageCache.CMD_POP = "CMD_POP"
slot0.MessageCache.CMD_FLUSH = "CMD_FLUSH"
slot0.MessageCache.OK = "OK"
slot0.MessageCache.QUEUE_FULL = "QUEUE_FULL"
slot0.MessageCache.EXCEPTION = "EXCEPTION"

function slot1(...)
	return coroutine.yield(...)
end

function slot2(slot0, slot1, slot2)
	if slot1 == uv0.MessageCache.CMD_PUSH then
		if slot0.cacheQueueLenLimit_ <= #slot0.cacheQueue_ + slot0.curRQLen_ - slot0.curRQPos_ then
			return uv1(slot0, uv2(uv0.MessageCache.QUEUE_FULL, string.format("                    the cache limit length is set with %s, the coming message will be ignored.\n                ", slot0.cacheQueueLenLimit_)))
		else
			table.insert(slot0.cacheQueue_, slot2)

			return uv1(slot0, uv2(uv0.MessageCache.OK, slot3 + 1))
		end
	elseif slot1 == uv0.MessageCache.CMD_POP then
		if slot0.curRQPos_ < slot0.curRQLen_ then
			slot0.curRQPos_ = slot0.curRQPos_ + 1
			slot0.retrieveQueue_[slot0.curRQPos_] = nil

			return uv1(slot0, uv2(uv0.MessageCache.OK, slot0.retrieveQueue_[slot0.curRQPos_]))
		elseif slot0.cacheQueue_[1] then
			slot0.retrieveQueue_ = slot0.cacheQueue_
			slot0.cacheQueue_ = slot0.retrieveQueue_
			slot0.curRQPos_ = 1
			slot0.curRQLen_ = #slot0.retrieveQueue_
			slot0.retrieveQueue_[slot0.curRQPos_] = nil

			return uv1(slot0, uv2(uv0.MessageCache.OK, slot0.retrieveQueue_[slot0.curRQPos_]))
		else
			return uv1(slot0, uv2(uv0.MessageCache.OK))
		end
	elseif slot1 == uv0.MessageCache.CMD_KILL then
		slot3 = slot0.curRQPos_
		slot5 = 1

		while slot3 < slot0.curRQLen_ do
			table.insert(slot0.cacheQueue_, slot5, slot0.retrieveQueue_[slot3])

			slot0.retrieveQueue_[slot3] = nil
			slot5 = slot5 + 1
			slot3 = slot3 + 1
		end

		slot0.curRQPos_ = 0
		slot0.curRQLen_ = 0

		return uv0.MessageCache.OK, slot0.cacheQueue_
	elseif slot1 == uv0.MessageCache.CMD_FLUSH then
		slot3 = slot0.curRQPos_
		slot5 = 1

		while slot3 < slot0.curRQLen_ do
			table.insert(slot0.cacheQueue_, slot5, slot0.retrieveQueue_[slot3])

			slot0.retrieveQueue_[slot3] = nil
			slot5 = slot5 + 1
			slot3 = slot3 + 1
		end

		slot0.curRQPos_ = 0
		slot0.curRQLen_ = 0
		slot0.cacheQueue_ = {}

		return uv1(slot0, uv2(uv0.MessageCache.OK, slot0.cacheQueue_))
	else
		return uv1(slot0, uv2(uv0.MessageCache.EXCEPTION, string.format("unknown cmd type received %s", tostring(slot1))))
	end
end

function slot3(slot0)
	return uv1({
		curRQPos_ = 0,
		curRQLen_ = 0,
		cacheQueue_ = {},
		retrieveQueue_ = {},
		cacheQueueLenLimit_ = slot0 or uv0.MessageCache.DEFAULT_QUEUE_LENGTH
	}, uv2(uv0.MessageCache.OK))
end

function slot0.MessageCache.Ctor(slot0, slot1, slot2)
	slot0._name = slot1
	slot0._thread = coroutine.create(uv0)
	slot3, slot4 = coroutine.resume(slot0._thread, slot2)
end

function slot0.MessageCache.Push(slot0, ...)
	if coroutine.status(slot0._thread) == "suspended" then
		slot2, slot3, slot4 = coroutine.resume(slot0._thread, uv0.MessageCache.CMD_PUSH, {
			...
		})

		if slot2 then
			return slot3, slot4
		else
			return uv0.MessageCache.EXCEPTION, slot3
		end
	else
		return uv0.MessageCache.EXCEPTION, string.format("current thread status %s,\n            maybe the MessageCache:Destroy() is called before the Push operation.", slot1)
	end
end

function slot0.MessageCache.Pop(slot0)
	if coroutine.status(slot0._thread) == "suspended" then
		slot2, slot3, slot4 = coroutine.resume(slot0._thread, uv0.MessageCache.CMD_POP)

		if slot2 then
			if slot3 == uv0.MessageCache.OK and slot4 ~= nil then
				return slot3, unpack(slot4)
			else
				return slot3, slot4
			end
		else
			return uv0.MessageCache.EXCEPTION, slot3
		end
	else
		return uv0.MessageCache.EXCEPTION, string.format("current thread status %s,\n            maybe the MessageCache:Destroy() is called before the Pop operation.", slot1)
	end
end

function slot0.MessageCache.Flush(slot0)
	if coroutine.status(slot0._thread) == "suspended" then
		slot2, slot3, slot4 = coroutine.resume(slot0._thread, uv0.MessageCache.CMD_FLUSH)

		if slot2 then
			return slot3, slot4
		else
			return uv0.MessageCache.EXCEPTION, slot3
		end
	else
		return uv0.MessageCache.EXCEPTION, string.format("current thread status %s,\n            maybe the MessageCache:Destroy() is called before the Destroy operation.", slot1)
	end
end

function slot0.MessageCache.Destroy(slot0)
	if coroutine.status(slot0._thread) == "suspended" then
		slot2, slot3, slot4 = coroutine.resume(slot0._thread, uv0.MessageCache.CMD_KILL)

		if slot2 then
			return slot3, slot4
		else
			return uv0.MessageCache.EXCEPTION, slot3
		end
	else
		return uv0.MessageCache.EXCEPTION, string.format("current thread status %s,\n            maybe the MessageCache:Destroy() is called before the Destroy operation.", slot1)
	end
end
