/**
 *	OpenSocial Framework
 *	@version: 1.0.1
 *	@author: Suhail Doshi (suhail.doshi@asu.edu)
 *	Notes: Supports version 0.7 of OpenSocial.
 */

var osNetwork = function() {
	network = {};
	
	network.owner = null;
	network.viewer = null;
	network.raw_persons = {};
	
	// Static URI used for makeRequest() if set, so you don't have to keep typing in:
	// example.com/my_app/do_something, make staticURI = 'example.com/my_app' and pass:
	// '/do_something' into your URL parameter for doRequest();
	network.staticURI = null;
	
	// Use network.setRequestAuth('SIGNED'); to make doRequest() (wrapper of makeRequest())
	// send signed requests.
	network.authentication = gadgets.io.AuthorizationType.NONE;
	
	network.getUser = function(person) {
		info = {};
		
		info.person = person;
		info.current_location = null;
		
		/*
		 * Add more keys to the userInfo array as more available data is available.
		 *
		 * returns an object structure.
		 */
		info.aggregate = function() {
			userInfo = {
							'about_me'		:	info.about_me(),
							'age'			:	info.age(),
							'date_of_birth' :	info.date_of_birth(),
							'display_name'	:	info.display_name(),
							'gender'		:	info.gender(),
							'os_id'			:	info.id(),
							'name'			:	info.name(),
							'thumbnail_url' :	info.thumbnail_url(),
							'is_owner'		:	info.isOwner(),
							'is_viewer'		:	info.isViewer(),
							'profile_url'	:	info.getProfileURL(),
							'city'			:	info.city(),
							'region'		:	info.region(),
							'country'		:	info.country(),
							'postal_code'	:	info.postal_code()
							//'is_online'	  :	  info.isOnline(),
							//'allow_send'	  :	  info.allowedToSend()
						};
						
			userInfo.has_app = (userInfo.is_owner && userInfo.is_viewer);
			
			return userInfo;
		};
		
		/*info.allowedToSend = function() {
			return person.getField(opensocial.Person.ALLOWSEND);
		}*/
		
		/*info.isOnline = function() {
			if (person) {
				switch (person.getField(opensocial.Person.PRESENCE).toUpperString()) {
					case 'OFFLINE':
						return false;
					case 'ONLINE':
						return true;
					default:
						return null;
				}
			} else
				return null;
		}*/
		
		info.getProfileURL = function() {
			if (person){
				return person.getField(opensocial.Person.Field.PROFILE_URL);
			} else {
				return null;
			}
		};
		
		info.isOwner = function() {
			if (person) {
				return person.isOwner();
			} else {
				return false;
			}
		};
		
		info.isViewer = function() {
			if (person) {
				return person.isViewer();
			}
			else {
				return false;
			}
		};
		
		info.display_name = function() {
			if (person) {
				return person.getDisplayName();
			}
			else {
				return null;
			}
		};
		
		info.name = function() {
			if (person.getField && person.getField(opensocial.Person.Field.NAME)) {
				var name = person.getField(opensocial.Person.Field.NAME);
				
				// Some containers return it this way. (maybe it will change later?)
				if (typeof(name) != 'string') {
					name = name.getField(opensocial.Name.Field.UNSTRUCTURED);
				}
				
				if (typeof(name) == 'string') {
					return name;
				} else {
					return null;
				}
			} else {
				return null;
			}
		};
		
		info.id = function() {
			if (person && person.getId()) {
				return person.getId();
			}
			else {
				return null;
			}
		};
		
		info.about_me = function() {
			if (person.getField) {
				return person.getField(opensocial.Person.Field.ABOUT_ME);
			} else {
				return null;
			}
		};
		
		info.age = function() {
			if (person.getField) {
				return person.getField(opensocial.Person.Field.AGE);
			} else {
				return null;
			}
		};

		info.set_current_location = function() {
			if (person.getField) {
				info.user_location = person.getField(opensocial.Person.Field.CURRENT_LOCATION);
			}
		};
		
		info.city = function() {
			if (! info.user_location || info.user_location === null) {
				info.set_current_location(); // Grab location info
			}
			
			if (info.user_location && info.user_location.getField) {
				return info.user_location.getField(opensocial.Address.Field.LOCALITY);
			}
			else {
				return null;
			}
		};
		
		info.region = function() {
			if (! info.user_location && info.user_location === null) {
				info.set_current_location(); // Grab location info
			}
			
			if (info.user_location && info.user_location.getField) {
				return info.user_location.getField(opensocial.Address.Field.REGION);
			}
			else {
				return null;
			}
		};
		
		info.country = function() {
			if (! info.user_location && info.user_location === null) {
				info.set_current_location(); // Grab location info
			}
			
			if (info.user_location && info.user_location.getField) {
				return info.user_location.getField(opensocial.Address.Field.COUNTRY);
			}
			else {
				return null;
			}
		};
		
		info.postal_code = function() {
			if (! info.user_location && info.user_location === null) {
				info.set_current_location(); // Grab location info
			}
			
			if (info.user_location && info.user_location.getField) {
				return info.user_location.getField(opensocial.Address.Field.POSTAL_CODE);
			}
			else {
				return null;
			}
		};
		
		info.thumbnail_url = function() {
			if (person.getField) {
				return person.getField(opensocial.Person.Field.THUMBNAIL_URL);
			}
			else {
				return null;
			}
		};
		
		info.date_of_birth = function() {
			if (person.getField) {
				return person.getField(opensocial.Person.Field.DATE_OF_BIRTH);
			}
			else {
				return null;
			}
		};
		
		info.gender = function() {
			if (person.getField(opensocial.Person.Field.GENDER) && person.getField(opensocial.Person.Field.GENDER).getKey) {
				return person.getField(opensocial.Person.Field.GENDER).getKey(opensocial.Enum.Gender);
			}
			else {
				return null;
			}
		};
		
		// For any other fields
		info.getField = function(key) {
			if (person.getField) {
				return person.getField(key);
			}
			else {
				return null;
			}
		};
		
		return info;
	};
	
	/*
	 *	@param url example.com/my_app/
	 *	@param method -> GET/POST
	 *	@param params Either mapped string object or a string of style: var1=val1&var2=val2
	 *	@param contentType Should be an alias that works with the function: getContentType();
	 *	@param refreshInterval -1 means no cache is used, null or 0 means caching always, any other value caches in seconds
	 */
	network.doRequest = function(url, method, params, callback, contentType, refreshInterval) {
		
		var encodedParams;
		
		// Does the url already have query params, adjust seperator!
		var sep = (url.indexOf("?") > -1) ? '&' : '?'
		
		if (params !== null) {
			if (typeof(params) != 'string') {
				encodedParams = gadgets.io.encodeValues(params); // Encode params to form correct URL
			} else {
				encodedParams = params;
			}
		}
		else {
		  encodedParams = null;
		}
		
		contentType = network.getContentType(contentType); // Select content type
		
		// What kind of request is being made
		if (method.toUpperCase() == 'POST') {
			optParams = { METHOD : 'POST', CONTENT_TYPE : contentType, POST_DATA : encodedParams, AUTHORIZATION : network.authentication };
		} else { // GET request
			if (encodedParams !== null) {
				url += sep + encodedParams; // Append to URL
			}
			optParams = { METHOD : 'GET', CONTENT_TYPE : contentType, AUTHORIZATION : network.authentication };
		}
		
		// Refresh cache result? -1 = no cached requests.
		if (refreshInterval || refreshInterval == -1) {
			if (refreshInterval == -1) {
				refreshInterval = 0;
			}
			sep = (url.indexOf("?") > -1) ? '&' : '?' // Readjust
			url += sep + 'nocache=' + network.getRefreshInterval(refreshInterval);
		}
		
		// Append which container is sending the request (SIGNED requests will pass it anyway)
		if (network.authentication !== gadgets.io.AuthorizationType.SIGNED) {
			sep = (url.indexOf("?") > -1) ? '&' : '?' // Readjust
			url += sep + 'container_src=' + network.getContainerHost();
		}
		
		// If a staticURI to make a request to has been specified, always use it.
		if (network.staticURI) {
			url = network.staticURI + url;
		}
		
		// Send request
		gadgets.io.makeRequest(url, callback, optParams);
	};
	
	network.setRequestAuth = function(type) {
		if (! type) {
			type = null;
		}
		
		switch (type.toUpperCase()) {
			case 'SIGNED':
				network.authentication = gadgets.io.AuthorizationType.SIGNED;
				break;
			case 'AUTHENTICATED':
				network.authentication = gadgets.io.AuthorizationType.AUTHENTICATED;
				break;
			default:
				network.authentication = gadgets.io.AuthorizationType.NONE;
		}
	};
	
	network.getContentType = function(type) {
		var contentType = null; // Initialize
		if (! type || type === null) {
			contentType = gadgets.io.ContentType.JSON;
		}
		else {
			switch (type.toUpperCase()) {
				case 'DOM':
					contentType = gadgets.io.ContentType.DOM;
					break;
				case 'FEED':
					contentType = gadgets.io.ContentType.FEED;
					break;
				case 'JSON':
					contentType = gadgets.io.ContentType.JSON;
					break;
				case 'TEXT':
					contentType = gadgets.io.ContentType.TEXT;
					break;
				default:
					contentType = gadgets.io.ContentType.JSON;
			}
		}
		
		return contentType;
	};
	
	// A refresh interval of 0, means current date time stamp.
	network.getRefreshInterval = function(refreshInterval) {
		var ts = new Date().getTime();
		if (refreshInterval && refreshInterval > 0) {
			return Math.floor(ts / (refreshInterval * 1000));
		}
		return ts;
	};
	
	/*
	 * returns the location where the application is currently being used.
	 */
	network.getAppSurface = function() {
		if (gadgets.views) {
			return gadgets.views.getCurrentView().getName();
		}
		else {
			return null;
		}
	};
	
	network.getAllRequestFields = function() {
		var fields = [];
		// Only bothered to do ones I felt the social networks were going to actually implement or
		// were relevant to applications in a majority of the categories as a just in case mechanism.
		fields.push(	opensocial.Person.Field.ABOUT_ME,
						opensocial.Person.Field.ADDRESSES,
						opensocial.Person.Field.AGE,
						opensocial.Person.Field.CURRENT_LOCATION, // yes
						opensocial.Person.Field.DATE_OF_BIRTH,
						opensocial.Person.Field.EMAILS,
						opensocial.Person.Field.ETHNICITY,
						opensocial.Person.Field.GENDER,			  // yes
						opensocial.Person.Field.FOOD,
						opensocial.Person.Field.HEROES,
						opensocial.Person.Field.ID,				  // yes
						opensocial.Person.Field.INTERESTS,
						opensocial.Person.Field.LANGUAGES_SPOKEN,
						opensocial.Person.Field.MOVIES,
						opensocial.Person.Field.MUSIC,
						opensocial.Person.Field.NAME,
						opensocial.Person.Field.NICKNAME,
						opensocial.Person.Field.PETS,
						opensocial.Person.Field.PHONE_NUMBERS,
						opensocial.Person.Field.PROFILE_SONG,
						opensocial.Person.Field.PROFILE_URL,	  // yes
						opensocial.Person.Field.PROFILE_VIDEO,
						opensocial.Person.Field.QUOTES,
						opensocial.Person.Field.RELATIONSHIP_STATUS,
						opensocial.Person.Field.RELIGION,
						opensocial.Person.Field.STATUS,
						opensocial.Person.Field.THUMBNAIL_URL,	 // yes
						opensocial.Person.Field.TIME_ZONE,
						opensocial.Person.Field.URLS
					);
		return fields;
	};
	
	/*
	 * @param callback function
	 * @param bool refresh = re-request the data.
	 */
	network.getViewerData = function(callback, refresh, params) {
		// Already got the data, re-return
		if (network.viewer && ! refresh) {
			if (callback) {
				callback(network.parseUserData(network.viewer));
			}
		} else {
			
			if (typeof(params) == 'undefined' || params === null) {
				params = {};
				params[opensocial.DataRequest.PeopleRequestFields.PROFILE_DETAILS] = network.getAllRequestFields();
			}
			
			var req = opensocial.newDataRequest();
			req.add(req.newFetchPersonRequest(opensocial.DataRequest.PersonId.VIEWER, params), "viewer");
			req.send(function(response) {
				viewerInfo = response.get("viewer");
				if (viewerInfo && viewerInfo.getData) {
					network.viewer = viewerInfo.getData(); // Grab PERSON object
					
					if (callback) {
						callback(network.parseUserData(network.viewer));
					}
				} else {
					callback(null);
				}
			});
		}
	};
	
	/*
	 * @param callback function
	 * @param bool refresh = re-request the data.
	 */
	network.getOwnerData = function(callback, refresh, params) {
		// Already got the data, re-return
		if (network.owner && ! refresh) {
			if (callback) {
				callback(network.parseUserData(network.owner));
			}
		} else {
			
			if (typeof(params) == 'undefined' || params === null) {
				params = {};
				params[opensocial.DataRequest.PeopleRequestFields.PROFILE_DETAILS] = network.getAllRequestFields();
			}
			
			// Make request
			var req = opensocial.newDataRequest();
			req.add(req.newFetchPersonRequest(opensocial.DataRequest.PersonId.OWNER, params), "owner");
			req.send(function(response) {
				// Get PERSON information
				ownerInfo = response.get("owner");
				if (ownerInfo && ownerInfo.getData) {
					network.owner = ownerInfo.getData(); // Grab PERSON object
					
					if (callback) {
						callback(network.parseUserData(network.owner));
					} else {
						callback(null);
					}
				} else {
					callback(null);
				}
			});
		}
	};
	
	// Get both owner and viewer data
	network.getViewerOwner = function(callback, refresh, params) {
		if (typeof(params) == 'undefined' || params === null) {
			params = {};
			params[opensocial.DataRequest.PeopleRequestFields.PROFILE_DETAILS] = network.getAllRequestFields();
		}
		
		var req = opensocial.newDataRequest();
		req.add(req.newFetchPersonRequest(opensocial.DataRequest.PersonId.VIEWER, params), "viewer");
		req.add(req.newFetchPersonRequest(opensocial.DataRequest.PersonId.OWNER, params), "owner");
		req.send(function(response) {
			var ownerInfo = response.get("owner");
			var viewerInfo = response.get("viewer");
			
			if (ownerInfo) {
				network.owner = ownerInfo.getData();
			}
			
			if (viewerInfo) {
				network.viewer = viewerInfo.getData();
			}
			
			var users = {};
			if (network.owner) {
				users.owner = network.parseUserData(network.owner);
			}
			
			if (network.viewer) {
				users.viewer = network.parseUserData(network.viewer);
			}
			
			if (callback) {
				callback(users);
			}
		});
	};
	
	/*
	 * @param array Opensocial id's of people.
	 * @param array Optional parameters
	 *
	 * Will get PEOPLE objects for a single or array of id's.
	 */
	network.getPersons = function(personIds, params, callback) {
		if (typeof(params) == 'undefined' || params === null) {
			params = {};
			params[opensocial.DataRequest.PeopleRequestFields.PROFILE_DETAILS] = network.getAllRequestFields();
		}
		
		var req = opensocial.newDataRequest();
		req.add(req.newFetchPeopleRequest(personIds, params), "people");
		req.send(function(response) {
		var persons = response.get("people").getData();
			network.processPersons(persons, callback);
		});
	};
	
	network.getPeopleSettings = function(filter, max, sortOrder, page) {
		var settings = {};
		
		if (max === null) {
			max = 50;
		}
		
		if (filter && filter.toUpperCase()) {
			// Set filter type
			switch(filter) {
				case 'ALL':
					settings[opensocial.DataRequest.PeopleRequestFields.FILTER] = opensocial.DataRequest.FilterType.ALL;
					break;
				case 'HAS_APP':
					settings[opensocial.DataRequest.PeopleRequestFields.FILTER] = opensocial.DataRequest.FilterType.HAS_APP;
					break;
			}
		}
		
		if (sortOrder && sortOrder.toUpperCase()) {
			switch(sortOrder) {
				case 'NAME':
					settings[opensocial.DataRequest.PeopleRequestFields.SORT_ORDER] = opensocial.DataRequest.SortOrder.NAME;
					break;
				case 'TOP_FRIENDS':
					settings[opensocial.DataRequest.PeopleRequestFields.SORT_ORDER] = opensocial.DataRequest.SortOrder.TOP_FRIENDS;
					break;
			}
		}
		
		if (max) {
			settings[opensocial.DataRequest.PeopleRequestFields.MAX] = max;
		}
		if (page) {
			settings[opensocial.DataRequest.PeopleRequestFields.FIRST] = (max * page);
		}
		
		return settings;
	};
	
	/*
	 *	@param string userType Either request the 'viewer' or 'owner' friends.
	 *	@param params opensocial.DataRequest.PeopleRequestFields -> use network.getPeopleSettings() to easily define them.
	 */
	network.getUserFriends = function(userType, params, callback, iterations) {
		var personId = network.getUserIdSpec(userType);
		
		if (typeof(params) == 'undefined' || params === null) {
			params = network.getPeopleSettings('ALL', 40, 'TOP_FRIENDS', 0);
			params[opensocial.DataRequest.PeopleRequestFields.PROFILE_DETAILS] = network.getAllRequestFields();
		}
		
		// Iterate at least once
		if (typeof(iterations) == 'undefined' || iterations === null) {
			iterations = 1;
		}
		
		if (personId) {
			var req = opensocial.newDataRequest();
			
			// Batch friend requests up based on # of specified iterations
			for (var i = 0; i < iterations; i++) {
				
				var settings = params; // inherit properties
				
				// Need a default max
				if (typeof(settings[opensocial.DataRequest.PeopleRequestFields.MAX]) == 'undefined' || settings[opensocial.DataRequest.PeopleRequestFields.MAX] === null) {
					settings[opensocial.DataRequest.PeopleRequestFields.MAX] = 40;
				}
				
				// Default a FIRST offset
				if (typeof(params[opensocial.DataRequest.PeopleRequestFields.FIRST]) == 'undefined' || params[opensocial.DataRequest.PeopleRequestFields.FIRST] === null) {
					settings[opensocial.DataRequest.PeopleRequestFields.FIRST] = 1;
				}
				
				// Determine next FIRST offset
				settings[opensocial.DataRequest.PeopleRequestFields.FIRST] = (i * settings[opensocial.DataRequest.PeopleRequestFields.MAX]);
				
				// Batch the settings set with unique key
				req.add(req.newFetchPeopleRequest(personId, settings), "friends" + i);
				
				settings = null; // Reset
			}
			
			req.send(function(response) {
				// Parse info in a nice way, then send back...
				network.processFriends(response, iterations, callback);
			});
		}
	};
	
	/*
	 *	@param data response from newFetchPeopleRequest()
	 *
	 *	returns nicely formatted object array of friend data.
	 */
	network.processFriends = function(response, iterations, callback) {
		for (var i = 0; i < iterations; i++) {
			if (response.get("friends" + i) && response.get("friends" + i)) {
				var friendData = response.get("friends" + i).getData();
				
				network.processPersons(friendData, callback);
			}
		}
	};
	
	/*
	 * 	@param personData Raw PERSON object data
	 *	callback will return two results, a nice key : value pair person array and some detail information
	 */
	network.processPersons = function(personData, callback) {
		if (personData && personData.each) {
			var persons = {};
			personData.each(function(person) {
				userData = network.parseUserData(person);
				persons[userData.os_id] = userData;
				network.raw_persons[userData.os_id] = person; // Global person data cache (non-parsed version)
			});
			
			person_detail = {
				'total' : personData.getTotalSize(), // Total friends
				'offset' : personData.getOffset() // Offset in the friends list
			}
			
			callback(persons, person_detail);
		}
	};
	
	/*
	 *	@param PERSON object
	 *	returns nicely formatted user information.
	 */
	network.parseUserData = function(userData) {
		if (userData) {
			var userInfo = network.getUser(userData).aggregate();
			return userInfo;
		} else {
			return null;
		}
	};
	
	/*
	 * @param opensocial.PERSON
	 * @param Specify whether the user is a 'viewer' or 'owner'
	 *
	 * returns a boolean
	 */
	network.hasAppInstalled = function(person, type) {
		if (type) {
			switch (type.toUpperCase()) {
				case 'VIEWER':
					if (person) {
						return person.isOwner();
					}
					break;
				case 'OWNER':
					if (person) {
						return person.isViewer();
					}
					break;
			}
		}
		return false; // Last case
	};
	
	// Post to the activity stream so users can see other users updates/actions.
	// Non-template version
	// priority can be 'HIGH' or 'LOW'
	network.doPostActivityStream = function(title, body, priority, mediaItems, callback) {
		switch (priority.toUpperCase()) {
			case 'HIGH':
				priority = opensocial.CreateActivityPriority.HIGH;
				break;
			case 'LOW':
				priority = opensocial.CreateActivityPriority.LOW;
				break;
			default:
				priority = opensocial.CreateActivityPriority.HIGH;
		}
		
		var params = {};
		
		params[opensocial.Activity.Field.TITLE] = title;
		params[opensocial.Activity.Field.BODY] = body;
		
		var activity = opensocial.newActivity(params);
			
		if (activity && mediaItems) {
			activity.setField(opensocial.Activity.Field.MEDIA_ITEMS, mediaItems);
		}
		opensocial.requestCreateActivity(activity, priority, callback);
	};

	network.buildMediaItem = function(type, mediaURL, params) {
		if (type) {
			var mimeType = network.getMimeType(type);
			
			if (mediaURL && mimeType) {
					return opensocial.newActivityMediaItem(mimeType, mediaURL, params);
			}
		}
	};
	
	network.getMimeType = function(type) {
		switch(type.toUpperCase()) {
			case 'AUDIO':
					return opensocial.Activity.MediaItem.Type.AUDIO;
					break;
			case 'IMAGE':
					return opensocial.Activity.MediaItem.Type.IMAGE;
					break;
			case 'VIDEO':
					return opensocial.Activity.MediaItem.Type.VIDEO;
					break;
		}
	};
	
	// Grabs the domain for a container the application is hosted on.
	network.getContainerHost = function() {
		if (opensocial.getEnvironment()) {
			return opensocial.getEnvironment().getDomain();
		} else {
			return null;
		}
	};
	
	// Do we have the ability to play with the viewer's data?
	network.hasViewerPermission = function() {
		return opensocial.hasPermission(opensocial.Permission.VIEWER);
	};
	
	network.getActivityRequest = function(userType, callback) {
		var personId = network.getUserIdSpec(userType);
		
		var req = opensocial.newDataRequest();
		req.add(req.newFetchActivitiesRequest(personId));
		req.send(function(response) {
			if (callback) {
				callback(response.get());
			}
		});
	};
	
	network.getUserIdSpec = function(userType) {
		switch (userType.toUpperCase()) {
			case 'VIEWER_FRIENDS':
				personId = opensocial.DataRequest.Group.VIEWER_FRIENDS;
				break;
			case 'OWNER_FRIENDS':
				personId = opensocial.DataRequest.Group.OWNER_FRIENDS;
				break;
			case 'OWNER':
				personId = opensocial.DataRequest.PersonId.OWNER;
				break;
			case 'VIEWER':
				personId = opensocial.DataRequest.PersonId.VIEWER;
				break;
		}
		
		return personId;
	};
	
	network.getPossibleSurfaces = function() {
		var views = gadgets.views.getSupportedViews(); // Get supported views from the container.
		return views;
	};
	
	network.gotoSurface = function(surfaceName, params) {
		var surfaces = network.getPossibleSurfaces();
		
		if (typeof(params)	== 'undefined') {
			params = null;
		}
		
		switch (surfaceName.toUpperCase()) {
			case 'PROFILE':
				if (surfaces.profile) {
					gadgets.views.requestNavigateTo(surfaces.profile, params);
				}
				break;
			case 'CANVAS':
				if (surfaces.canvas) {
					gadgets.views.requestNavigateTo(surfaces.canvas, params);
				}
				break;
		}
	};
	
	/*
	 *	@param Map.<String, String> params
	 *	Will return a *string* view params for you to append to your URL to grab them via gadgets.views.getParams()
	 *	Example: url += '&' + network.convertViewParams({'var1' : 'value1', 'var2' : 'value2'});
	 */
	network.convertViewParams = function(params) {
		var strParams = gadgets.json.stringify(params);
		return encodeURIComponent(strParams);
	};
	
	network.getCurrentSurface = function() {
			return gadgets.views.getCurrentView();
	};
	
	// Builds a message object used for many viral API implementations
	network.buildMessage = function(title, body, type) {
		// Build message object
		var params = {};
		
		if (title) {
			params[opensocial.Message.Field.BODY] = body;
		}
		if (body) {
			params[opensocial.Message.Field.TITLE] = title;
		}
		if (type) {
			params[opensocial.Message.Field.TYPE] = network.getMessageType(type);
		}
		
		message = opensocial.newMessage(body, params);
		
		return message;
	};
	
	network.getMessageType = function(type) {
		if (type && type !== null) {
			switch(type.toUpperCase()) {
				case 'NOTIFICATION':
					return opensocial.Message.Type.NOTIFICATION;
				case 'PRIVATE_MESSAGE':
					return opensocial.Message.Type.PRIVATE_MESSAGE;
				case 'PUBLIC_MESSAGE':
					return opensocial.Message.Type.PUBLIC_MESSAGE;
				case 'EMAIL':
					return opensocial.Message.Type.EMAIL;
				default:
					return null;
			}
		}
		
		return null;
	};
	
	network.shareAppOwnerFriends = function(title, body, type, callback) {
		network.shareApp(network.getUserIdSpec('OWNER_FRIENDS'), title, body, type, callback);
	};
	
	network.shareAppViewerFriends = function(title, body, type, callback) {
		network.shareApp(network.getUserIdSpec('VIEWER_FRIENDS'), title, body, type, callback);
	};
	
	/*
	 *	@param mixed recipients UserIdSpec or array of opensocial_id's
	 *	@param string title Title of message to send.
	 *	@param string body Body of the message.
	 */
	network.shareApp = function(recipients, title, body, type, callback) {
		// Build message object
		message = network.buildMessage(title, body, type);
		
		// Send message to recipients
		opensocial.requestShareApp(recipients, message, callback);
	};
	
	network.sendViewerMessage = function(title, body, type, callback) {
		network.sendMessage(network.getUserIdSpec('VIEWER'), title, body, type, callback);	
	};
	
	network.sendOwnerFriendsMessage = function(title, body, type, callback) {
		network.sendMessage(network.getUserIdSpec('OWNER_FRIENDS'), title, body, type, callback);  
	};
	
	/*
	 *	@param mixed recipients UserIdSpec or array of opensocial_id's
	 *	@param string title Title of message to send.
	 *	@param string body Body of the message.
	 *	@param string type Container dependent, ex: NOTIFICATION, EMAIL
	 */
	network.sendMessage = function(recipients, title, body, type, callback) {
		try {
			// Build message object
			message = network.buildMessage(title, body, type);
			
			// Send message to recipients
			opensocial.requestSendMessage(recipients, message, callback);
		} catch (ex) {
			callback(false);
		}
	};
	
	// This depends on the container, some do not support it--be wary about cross compatibility.
	network.getAppId = function() {
		return gadgets.util.getUrlParameters().gadgetId;
	};
	
	network.debug = function(title, data) {
		/*console.log('DEBUG: ' + title);
		
		if (data) {
			console.log(data);
		}
		console.log('===========END DEBUG===========');*/
	};
	
	return network;
};

