1 module eventmanager.eventlist;
2 
3 import std.container : DList;
4 import std.algorithm.comparison : equal;
5 
6 import std.stdio;
7 
8 import eventmanager.abstractevent;
9 import eventmanager.eventinterface;
10 import eventmanager.eventdispatcher;
11 
12 struct EventContainer
13 {
14     TypeInfo eventType;
15     EventInterface event;
16 }
17 
18 interface EventListInterface {
19     public void append(EventInterface event, TypeInfo eventType) @safe;
20     public void dispatch(EventDispatcherInterface dispatcher) @safe;
21     public DList!EventContainer getEventList() @safe;
22     public ulong size() @safe;
23 }
24 
25 class EventList : EventListInterface
26 {
27     private DList!EventContainer eventList;
28 
29     this() @safe {
30         this.eventList = DList!EventContainer();
31     }  
32 
33     public void append(EventInterface event, TypeInfo eventType) @safe
34     {
35         EventContainer container;
36         container.eventType = eventType;
37         container.event = event;
38 
39         this.eventList.insertBack(container);
40     }
41 
42     // Allow appending from one event list into another.
43     public void append(EventListInterface newEventList) @safe {
44         foreach (container; newEventList.getEventList()) {
45             this.append(container.event, container.eventType);
46         }
47     }
48 
49     /**
50     Process all of the events in this event list.  Each event may
51     in turn create new events which must also be processed.  Keep
52     looping until all events have been processed and no new events
53     have been created.
54     */
55     public void dispatch(EventDispatcherInterface dispatcher) @safe
56     {
57         auto eventList = this.eventList;
58 
59         while (true) {
60             auto newEventList = new EventList();
61 
62             foreach (container; eventList) {
63                 newEventList.append(dispatcher.dispatch(container.event, container.eventType));
64             }
65 
66             // If no new events were created, terminate the loop.
67             if (newEventList.size() == 0) {
68                 break;
69             }
70 
71             // Use the "new event list" as the basis of the loop
72             // for the next interation.
73             eventList = newEventList.getEventList();
74         }
75     }
76 
77     public DList!EventContainer getEventList() @safe
78     {
79         return this.eventList;
80     } 
81 
82     public ulong size() @safe
83     {
84         ulong count = 0;
85 
86         foreach (container; this.eventList) {
87             ++count;
88         }
89 
90         return count;
91     }
92 }