package net.cis.client.game.ctrl;
import java.util.HashMap;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.Queue;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.LinkedBlockingQueue;
import net.cis.client.game.common.ctrl.IDispatcher;
import net.cis.client.game.common.model.event.AbstractEvent;
import net.cis.client.game.common.model.event.IEventListener;
import net.cis.client.game.ctrl.threading.AbstractTimedCallbackHandler;
import net.cis.client.game.ctrl.threading.TimedCallbackStruct;
import com.jme3.system.Timer;
public class Dispatcher
extends
AbstractTimedCallbackHandler<Map<Object, List<TimedCallbackStruct<IEventListener<? extends AbstractEvent>>>>, IEventListener<? extends AbstractEvent>>
implements IDispatcher {
private final int DISPATCHER_SLEEP_TIME = 1;
private final Map<Object, AbstractEvent> slotEvents = new ConcurrentHashMap<Object, AbstractEvent>();
private final Queue<AbstractEvent> listEvents = new LinkedBlockingQueue<AbstractEvent>();
public Dispatcher(Timer timer) {
super(new HashMap<Object, List<TimedCallbackStruct<IEventListener<? extends AbstractEvent>>>>(), timer);
}
@Override
public void publish(AbstractEvent event) {
switch (event.publishType) {
case LIST:
listEvents.add(event);
break;
case SLOT:
slotEvents.put(event.eventType, event);
break;
}
}
@Override
protected int getSleepTime() {
return DISPATCHER_SLEEP_TIME;
}
@Override
protected void handleCallees() {
while (!listEvents.isEmpty()) {
AbstractEvent event = listEvents.poll();
if (event == null)
break;
fireEvent(event);
}
for (Object eventType : slotEvents.keySet()) {
AbstractEvent event = slotEvents.get(eventType);
if (event == null)
{
slotEvents.remove(eventType);
break;
}
if(fireSlotEvent(event))
slotEvents.remove(eventType);
}
}
@Override
protected void addCalleeStruct(IEventListener<? extends AbstractEvent> callee) {
Set<Object> eventTypes = callee.getEventTypes();
for (Object eventType : eventTypes) {
List<TimedCallbackStruct<IEventListener<? extends AbstractEvent>>> list = calleeContainer.get(eventType);
if (list == null)
calleeContainer.put(eventType, list = new LinkedList<TimedCallbackStruct<IEventListener<? extends AbstractEvent>>>());
list.add(createCalleeStruct(callee));
}
}
@Override
protected void removeCalleeStruct(IEventListener<? extends AbstractEvent> callee) {
Set<Object> eventTypes = callee.getEventTypes();
for (Object eventType : eventTypes) {
List<TimedCallbackStruct<IEventListener<? extends AbstractEvent>>> list = calleeContainer.get(eventType);
if (list == null)
return;
for (int i = list.size(); i-- > 0;) {
TimedCallbackStruct<IEventListener<? extends AbstractEvent>> struct = list.get(i);
if (struct.callback == callee)
list.remove(i);
}
}
}
private void fireEvent(AbstractEvent event) {
List<TimedCallbackStruct<IEventListener<? extends AbstractEvent>>> listener = calleeContainer
.get(event.eventType);
if (listener == null)
return;
float time = timer.getTimeInSeconds();
for (TimedCallbackStruct<IEventListener<? extends AbstractEvent>> struct : listener) {
if (time > struct.lastcall + struct.callback.getUpdateTime()) {
@SuppressWarnings("unchecked")
IEventListener<AbstractEvent> lsnr = (IEventListener<AbstractEvent>) struct.callback;
lsnr.onEvent(event);
struct.lastcall = time;
}
}
}
private boolean fireSlotEvent(AbstractEvent event) {
List<TimedCallbackStruct<IEventListener<? extends AbstractEvent>>> listener = calleeContainer.get(event.eventType);
if (listener == null)
return true;
boolean allHandled = true;
float time = timer.getTimeInSeconds();
for (TimedCallbackStruct<IEventListener<? extends AbstractEvent>> struct : listener) {
if(struct.lastCallID >= event.eventID)
continue;
if (time > struct.lastcall + struct.callback.getUpdateTime()) {
@SuppressWarnings("unchecked")
IEventListener<AbstractEvent> lsnr = (IEventListener<AbstractEvent>) struct.callback;
lsnr.onEvent(event);
struct.lastcall = time;
struct.lastCallID = event.eventID;
}
else
allHandled = false;
}
return allHandled;
}
@Override
protected boolean initialize()
{
// nothing to do
return true;
}
@Override
protected void shutdown()
{
// nothing to do
}
}