1 
  2 /**
  3 	* Function to return a JSON object containing the express router properties.
  4 	* @param {Object} req The express routing HTTP client request object.
  5 	* @param {Object} res The express routing HTTP client response object.
  6 	* @param {callback} next The express routing callback function to invoke next middleware in the stack.
  7 	* @return {Object} A JSON object that holds req, res, and next.
  8 */
  9 var routerProperties = function(req, res, next) {
 10 	return {
 11 		req: req,
 12 		res: res,
 13 		next: next
 14 	};
 15 }
 16 
 17 /**
 18 	* Function to search for all users meeting a criteria.
 19 	* The server returns a 404 error if no users matching criteria are found.
 20 	* @param {Object} properties JSON object containing the express router properties.
 21 	* @param {Object} criteria JSON object to determine the search criteria for the user(s) we wish to find.
 22 	* @param {callback} processUsers A callback function to be invoked on the resulting set of users found.
 23 	* @return {Void}
 24 */
 25 var searchUsers = function(properties, criteria, results, processUsers) {
 26 	let req = properties.req;
 27 	let res = properties.res;
 28 	let next = properties.next;
 29 
 30 	let db = req.app.locals.db;
 31 	const userCollection = db.collection("Users");
 32 
 33 	userCollection.find(criteria).toArray(function(err, users) {
 34 		if (err) {
 35 			next(err);
 36 			return;
 37 		}
 38 		if (users.length === 0) {
 39 			res.status(404).send(`Unable to find users that met search criteria`);
 40 			return;
 41 		}
 42 		processUsers(users, results);
 43 	});
 44 }
 45 
 46 // var searchEvents = function(properties, criteria, processEvents) {
 47 // 	let req = properties.req;
 48 // 	let res = properties.res;
 49 // 	let next = properties.next;
 50 
 51 // 	let db = req.app.locals.db;
 52 // 	const eventCollection = db.collection("Events");
 53 
 54 // 	eventCollection.find(criteria).toArray(function(err, events) {
 55 // 		if (err) {
 56 // 			next(err);
 57 // 			return;
 58 // 		}
 59 // 		if (events.length === 0) {
 60 // 			res.status(404).send(`Unable to find events that met search criteria`);
 61 // 			return;
 62 // 		}
 63 // 		processEvents(events);
 64 // 	});
 65 // }
 66 
 67 // var searchActivities = function(properties, criteria, processActivities) {
 68 // 	let req = properties.req;
 69 // 	let res = properties.res;
 70 // 	let next = properties.next;
 71 
 72 // 	let db = req.app.locals.db;
 73 // 	const activityCollection = db.collection("Activities");
 74 
 75 // 	activityCollection.find(criteria).toArray(function(err, activities) {
 76 // 		if (err) {
 77 // 			next(err);
 78 // 			return;
 79 // 		}
 80 // 		if (activities.length === 0) {
 81 // 			//res.status(404).send(`Unable to find activities that met search criteria`);
 82 // 			return;
 83 // 		}
 84 // 		processActivities(activities);
 85 // 	});
 86 // }
 87 
 88 /**
 89 	* Function to return update a user's data in Users collection in MongoDB.
 90 	* The server returns a 404 error if unable to find a matching user in the database.
 91 	* Returns a 201 if it succesfully updates user data.
 92 	* @param {Object} properties JSON object containing the express router properties.
 93 	* @param {string} email The email of the user whose fields we wish to update.
 94 	* @param {Object} updateSet JSON object containing the data we wish to update.
 95 	* @return {Void}
 96 */
 97 var updateUser = function(properties, email, updateSet) {
 98 	let req = properties.req;
 99 	let res = properties.res;
100 	let next = properties.next;
101 
102 	let db = req.app.locals.db;
103 	const userCollection = db.collection("Users");
104 
105 	userCollection.findOne({"email": email}, function(err, resultUser) {
106 		if (err) {
107 			next(err);
108 			return;
109 		}
110 		if (result.length === 0) {
111 			res.status(404).send(`Unable to find user with email`);
112 			return;
113 		}
114 		userCollection.updateOne({"email": email}, updateSet, function(err, updateResult) {
115 			if (err) {
116 				next(err);
117 				return;
118 			}
119 			res.status(201).send(`Successfully updated user data`);
120 			return;
121 		});
122 	});
123 }
124 
125 /**
126 	* Function to insert a new user into the Users collection in MongoDB.
127 	* The server returns a 404 error if the email in the request body is already in use.
128 	* Otherwise it creates a new user with the given userID and hashed password,
129 	* default availabilities, and no activities or events, and adds it to the MongoDB database,
130 	* returning a 201 status code.
131 	* @param {Object} properties JSON object containing the express router properties.
132 	* @param {string} name The name of the new user.
133 	* @param {string} email The email of the new user.
134 	* @param {string} password The password of the new user that is encrypted with bcrypt.
135 	* @return {Void}
136 */
137 var insertUser = function(properties, name, email, password) {
138 	let req = properties.req;
139 	let res = properties.res;
140 	let next = properties.next;
141 
142 	let db = req.app.locals.db;
143 	const userCollection = db.collection("Users");
144 	const valuesCollection = db.collection("Values");
145 
146 	userCollection.find({"email": email}).toArray(
147 		function(err, result) {
148 			if (err) {
149 				next(err);
150 				return;
151 			}
152 			if (result.length !== 0) {
153 				// res.status(404).send(`Email already in use`);
154 				res.status(404).render('register', {err: 'Email already in use.'});
155 				return;
156 			}
157 
158 			valuesCollection.find({"name": "Users"}).toArray(function(err, resId) {
159 				if (err) {
160 					next(err);
161 					return;
162 				}
163 				let maxUserId = resId[0].maxUserId;
164 
165 				let defaultAvailability = [];
166 				for (let i = 0; i < 7; i++) {
167 					let week = [];
168 					for (let j = 0; j < 48; j++) {
169 						week.push(false);
170 					}
171 					defaultAvailability.push(week);
172 				}
173 
174 				let newUser = {
175 					userId: maxUserId,
176 					name: name,
177 					email: email,
178 					password: password,
179 					rating: { "scoreSum": 0, "numRatings": 0},
180 					activities: [],
181 					availability: defaultAvailability,
182 					events: []
183 				};
184 				userCollection.insertOne(newUser, function (err, insertResult) {
185 					if (err) {
186 						next(err);
187 						return;
188 					}
189 					let newValue = {$set: {"maxUserId": maxUserId + 1}}; // this is buggy
190 					valuesCollection.updateOne({"name": "Users"}, newValue, function(err, updateResult) {
191 						if (err) {
192 							next(err);
193 							return;
194 						}
195 
196 						res.redirect(`/active/profile/${newUser.userId}`);
197 						return;
198 					});
199 				});
200 			});
201 			return;
202 		}
203 	);
204 }
205 
206 
207 
208 /**
209 	* Function to insert a new event into the Events collection in MongoDB.
210 	* The server returns a 404 error if the event in the request body is already in use.
211 	* Otherwise it creates a new event with the given ,
212 	* and adds it to the MongoDB database,
213 	* returning a 201 status code.
214 	* @param {Object} properties JSON object containing the express router properties.
215 	* @param {string} email The email of the new user.
216 	* @param {string} password The password of the new user that is encrypted with bcrypt.
217 	* @return {Void}
218 */
219 var insertEvent = function(properties, myUserId, friendUserId, activity, startTime, endTime, location) {
220 	let req = properties.req;
221 	let res = properties.res;
222 	let next = properties.next;
223 
224 	let db = req.app.locals.db;
225 	const eventCollection = db.collection("Events");
226 	const valuesCollection = db.collection("Values");
227 
228 	var invitedIds = [myUserId, friendUserId];
229 	invitedIds.sort();
230 
231 
232 	eventCollection.find({"invitedIds": invitedIds, "activity": activity, "startTime": startTime, "endTime": endTime}).toArray( //check invitedIds, activity, startTime, endTime aren't in
233 		function(err, result) {
234 			if (err) {
235 				next(err);
236 				return;
237 			}
238 			if (result.length !== 0) { //event already exists
239 				//res.status(404).send(`Event already in use`);
240 				res.status(404).render('register', {err: 'Event already in use.'});
241 				return;
242 			}
243 
244 
245 			//console.log(valuesCollection);
246 			valuesCollection.find({"name": "Users"}).toArray(function(err, resId) { //to get maxEventId for new eventId
247 				if (err) {
248 					next(err);
249 					return;
250 				}
251 				console.log(resId);
252 				// console.log(resId);
253 
254 				let maxEventId = resId[0].maxEventId; //grab maxEventId from Values collection
255 
256 				let newEvent = {
257 					eventId: maxEventId,
258 					acceptedIds: [],
259 					invitedIds: invitedIds,
260 					activity: activity,
261 					startTime: startTime,
262 					endTime: endTime,
263 					status: "matched",
264 					location: location
265 				};
266 				eventCollection.insertOne(newEvent, function (err, insertResult) { //insert event to db
267 					if (err) {
268 						next(err);
269 						return;
270 					}
271 					let newValue = {$set: {"maxEventId": maxEventId + 1}}; // this is buggy?
272 					valuesCollection.updateOne({"name": "Events"}, newValue, function(err, updateResult) { //update maxEventId in Values collection
273 						if (err) {
274 							next(err);
275 							return;
276 						}
277 
278 						next();
279 						//res.redirect(`/active/match/${myUserId}`);
280 
281 						// res.status(201).render('match', {
282 						// 	newEvent
283 						// });
284 						return;
285 					});
286 				});
287 			});
288 			return;
289 		}
290 	);
291 }
292 
293 
294 
295 module.exports = {
296 	insertUser: insertUser,
297 	insertEvent: insertEvent,
298 	updateUser: updateUser,
299 	searchUsers: searchUsers,
300 //	searchActivities: searchActivities,
301 	routerProperties: routerProperties
302 };
303