/*
	Реализация спецификаций CLDC версии 1.1 (JSR-139), MIDP версии 2.1 (JSR-118)
	и других спецификаций для функционирования компактных приложений на языке
	Java (мидлетов) в среде программного обеспечения Малик Эмулятор.

	Copyright © 2016, 2019 Малик Разработчик

	Это свободная программа: вы можете перераспространять ее и/или изменять
	ее на условиях Меньшей Стандартной общественной лицензии GNU в том виде,
	в каком она была опубликована Фондом свободного программного обеспечения;
	либо версии 3 лицензии, либо (по вашему выбору) любой более поздней версии.

	Эта программа распространяется в надежде, что она будет полезной,
	но БЕЗО ВСЯКИХ ГАРАНТИЙ; даже без неявной гарантии ТОВАРНОГО ВИДА
	или ПРИГОДНОСТИ ДЛЯ ОПРЕДЕЛЕННЫХ ЦЕЛЕЙ. Подробнее см. в Меньшей Стандартной
	общественной лицензии GNU.

	Вы должны были получить копию Меньшей Стандартной общественной лицензии GNU
	вместе с этой программой. Если это не так, см.
	<https://www.gnu.org/licenses/>.
*/


package malik.emulator.application;

import java.util.*;

final class QueueOfMalikAppEvents extends Queue
{
	private static final int INITIAL_CAPACITY = 0x11;
	private static final Runnable EMPTY_EVENT;

	static
	{
		EMPTY_EVENT = new Runnable() {
			public void run()
			{
			}
		};
	}


	private long[] eventsFromUser;
	private Runnable[] eventsFromApp;

	public QueueOfMalikAppEvents()
	{
		super(INITIAL_CAPACITY);
		this.eventsFromUser = new long[INITIAL_CAPACITY];
		this.eventsFromApp = new Runnable[INITIAL_CAPACITY];
	}

	public void removeTailElement()
	{
		int t = tail;
		eventsFromUser[t] = 0L;
		eventsFromApp[t] = null;
		advanceTail();
	}

	public void push(long eventFromUser, Runnable eventFromApp)
	{
		int h;
		int nc;
		long[] lq = eventsFromUser;
		Runnable[] rq = eventsFromApp;
		if(getFreeElements() == 0)
		{
			nc = (capacity << 1) - 1;
			lq = eventsFromUser = expand(lq, nc);
			rq = eventsFromApp = (Runnable[]) expand(rq, nc);
			reset(nc);
		}
		h = head;
		lq[h] = eventFromUser;
		rq[h] = eventFromApp;
		advanceHead();
	}

	public long peekEventFromUser()
	{
		return eventsFromUser[tail];
	}

	public Runnable peekEventFromApp()
	{
		return eventsFromApp[tail];
	}

	public Runnable findImmediatelyRunnable(Object argument)
	{
		int t = tail;
		int c = capacity;
		Runnable[] e = eventsFromApp;
		for(int i = head; i != t; )
		{
			Runnable r;
			i = (c + i - 1) % c;
			if((r = e[i]) instanceof ImmediatelyRunnable && ((ImmediatelyRunnable) r).argument() == argument)
			{
				e[i] = EMPTY_EVENT;
				return r; 
			}
		}
		return null;
	}
}
