1 module Connection;
2 
3 import core.thread;
4 import gui;
5 import gdk.Threads : te = threadsEnter, tl = threadsLeave;
6 import gtk.Box;
7 import std.stdio;
8 import libdnet.dclient;
9 import std.socket;
10 import gtk.ListBox;
11 import gtk.Label;
12 
13 public final class Connection : Thread
14 {
15     private GUI gui;
16     private Box box;
17     private ListBox channels;
18     private ListBox users;
19     private ListBox textArea;
20 
21     private DClient client;
22     private Address address;
23 
24     /* TODO: Check if we need to protect */
25     /* TODO: So far usage is in signal handlers (mutex safved) and within te-tl lock for notifications */
26     private string currentChannel;
27 
28     this(GUI gui, Address address)
29     {
30         super(&worker);
31         this.gui = gui;
32         this.address = address;
33         start();
34     }
35 
36     private void worker()
37     {
38         te();
39 
40         box = getChatPane();
41         gui.notebook.add(box);
42 
43         gui.notebook.setTabLabelText(box, "user@"~address.toString());
44 
45         gui.notebook.showAll();
46 
47         
48 
49         tl();
50         writeln("connection gtk unlock");
51 
52         client = new DClient(address);
53         client.auth("bru", "kak"); /* TODO: DO this without auth (the list in the loop, crahses server) */
54         writeln("br");
55 
56 
57         channelList();
58 
59         /**
60         * Notification loop
61         *
62         * Awaits notifications and then displays them
63         */
64         while(true)
65         {
66             /* Receive a notification */
67             byte[] notificationData = client.awaitNotification();
68             writeln(notificationData);
69 
70             te();
71             import std.conv;
72             textArea.add(new Label(to!(string)(notificationData)));
73             textArea.showAll();
74 
75             process(notificationData);
76             //gui.mainWindow.showAll();
77 
78             tl();
79 
80             //Thread.sleep(dur!("seconds")(2));
81         }
82     }
83 
84     
85 
86 	/**
87 	* Processes an incoming notification
88 	* accordingly
89 	*/
90 	private void process(byte[] data)
91 	{
92 		/* TODO: Implement me */
93 
94 		/* TODO: Check notification type */
95 		ubyte notificationType = data[0];
96 
97 		/* For normal message (to channel or user) */
98 		if(notificationType == 0)
99 		{
100 			/* TODO: Decode using tristanable */
101 
102             
103 			writeln("new message");
104 		}
105 		/* Channel notification (ntype=1) */
106 		else if(notificationType == 1)
107 		{
108 			/* TODO: Decode using tristanable */
109 			/* TODO: Get the username of the user that left */
110 			//writeln("user left/join message");
111 
112 			/* Get the sub-type */
113 			ubyte subType = data[1];
114 
115 			/* If the notification was leave (stype=0) */
116 			if(subType == 0)
117 			{
118 				string username = cast(string)data[2..data.length];
119                 textArea.add(new Label(("<-- "~username~" left the channel")));
120                 textArea.showAll();
121 			}
122 			/* If the notification was join (stype=1) */
123 			else if(subType == 1)
124 			{
125 				string username = cast(string)data[2..data.length];
126 
127                 /* Show joined message */
128                 textArea.add(new Label(("--> "~username~" joined the channel")));
129                 textArea.showAll();
130 
131                 /* Add the joined user to the members list */
132                 users.add(new Label(username));
133                 users.showAll();
134 			}
135 			/* TODO: Unknown */
136 			else
137 			{
138 				
139 			}
140 		}
141 	}
142 
143 
144 
145 
146 
147     private void channelList()
148     {
149         te();
150         channelList_unsafe();
151         tl();
152     }
153 
154     /**
155     * Lists all channels and displays them
156     *
157     * Only to be aclled when locked (i.e. by the event
158     * loop signal dispatch or when we lock it
159     * i.e. `channelList`)
160     */
161     private void channelList_unsafe()
162     {
163         string[] channelList = client.list();
164 
165         foreach(string channel; channelList)
166         {
167             channels.add(new Label(channel));
168             channels.showAll();
169         }
170     }
171     
172     private void selectChannel(ListBox s)
173     {
174         /* Get the name of the channel selected */
175         string channelSelected = (cast(Label)(s.getSelectedRow().getChild())).getText();
176 
177         /* Join the channel */
178         client.join(channelSelected);
179 
180         /* Set this as the currently selected channel */
181         currentChannel = channelSelected;
182 
183         /* Fetch a list of members */
184         string[] members = client.getMembers(channelSelected);
185 
186         /* Display the members */
187         users.removeAll();
188         foreach(string member; members)
189         {
190             users.add(new Label(member));
191             users.showAll();
192         }
193     }
194 
195 
196     /**
197     * Creates a message box
198     *
199     * A message box consists of two labels
200     * one being the name of the person who sent
201     * the message and the next being the message
202     * itself
203     */
204     private Box createMessageBox()
205     {
206         return null;
207     }
208 
209     private Box getChatPane()
210     {
211         /* The main page of the tab */
212         Box box = new Box(GtkOrientation.HORIZONTAL, 1);
213 
214         /* The channels box */
215         Box channelBox = new Box(GtkOrientation.VERTICAL, 1);
216 
217         /* The channel's list */
218         channels = new ListBox();
219         channels.addOnSelectedRowsChanged(&selectChannel);
220 
221         channelBox.add(new Label("Channels"));
222         channelBox.add(channels);
223 
224         /* The user's box */
225         Box userBox = new Box(GtkOrientation.VERTICAL, 1);
226 
227         /* The user's list */
228         users = new ListBox();
229 
230         userBox.add(new Label("Users"));
231         userBox.add(users);
232         
233         
234 
235        
236         textArea = new ListBox();
237 
238 
239         box.add(channelBox);
240         box.add(textArea);
241         box.add(userBox);
242         
243 
244 
245         return box;
246     }
247 
248     private int getPageNum()
249     {
250         return gui.notebook.pageNum(box);
251     }
252 
253     public void shutdown()
254     {
255         /* This is called from gui.d */
256         int pageNum = getPageNum();
257 
258         if(pageNum == -1)
259         {
260             /* TODO: Error handling */
261         }
262         else
263         {
264             gui.notebook.removePage(pageNum);
265             gui.notebook.showAll();
266         }
267     }
268 }