// FwpConnect API
// Configured to use 1 or more network adapter classes (currently only FacebookAdapter is implemented)
// Configured to use 1 handler handle communication with registration server
// Remote handler depends on JQuery library for ajax call

FwpConnect = {

	init: function() {
		// create adapters for each network
		FwpConnect.adapters = {};
		var facebook = FwpConnect.networks.facebook;
		if (facebook) {
			FwpConnect.adapters.facebook = new FwpConnect.FacebookAdapter(facebook);
		}
	},
	
	connect: function(networkName, callback) {
		//alert('connect called with callback ' + callback);
		FwpConnect.adapters[networkName].connect(callback);
	},
	
	logout: function(callback) {
		// get total count of networks
		var networkCount = 0;
		for (name in FwpConnect.adapters) {
			networkCount++;
		}
		
		// log out of each
		var logoutCount = 0;
		for (name in FwpConnect.adapters) {
			FwpConnect.adapters[name].logout(function(network) {
				// when ALL adapters have completed logout, invoke callback
				logoutCount++;
				//alert('logged out of ' + network + ', ' + logoutCount + '/' + networkCount);
				if (logoutCount == networkCount) {
					//alert('invoking ' + callback);
					callback();
				}
			});
		}
	},
	
	// Delete network cookies without actually logging user out of networks.
	// Synchronous; no callback
	logoutInternal: function() {
	    //alert('FwpConnect.logoutInternal');
		for (name in FwpConnect.adapters) {
			FwpConnect.adapters[name].logoutInternal();
		}
	},
	
	// only call this if the user is logged in and network logged out
	// in that case will check if the user has a linked network account
	getLinkStatus: function(networkName, callback) {
		this.adapters[networkName].getLinkStatus(callback);
	},
	
	logError: function(network, action, message) {
		FwpConnect.handler.logError(network, action, message);
	},

	// private functions
	
	setCookie: function(name,value,expires,path,domain,secure,escapeVal){
		var cookie = name + "=" + ( (escapeVal) ? escape( value ) : value )+
		( ( expires ) ? ";expires=" + expires.toGMTString() : "" ) +
		( ( path ) ? ";path=" + path : "" ) +
		";domain=" + FwpConnect.cookieDomain +
		( ( secure ) ? ";secure" : "" );
		//alert("set cookie " + cookie);
		document.cookie = cookie;
	},
	
	deleteCookie: function(name) {
		FwpConnect.setCookie(name, '', new Date(), "/");
	}
	
};


/////////////////////////////////////////////////////////////////////
// Facebook Adapter /////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////

FwpConnect.FacebookAdapter = function(config) {
	this.networkName = "Facebook";
	for (var name in config) {
		this[name] = config[name];
	}
	var thisRef = this; // handle this scope change in nested functions
	try {
		FB.init(this.apiKey, this.xdReceiverUri, {
			ifUserConnected: function(uid) {
				if (!thisRef.loggedIn) {
					thisRef.login(uid);
				}
			}, 
			ifUserNotConnected: function() {
				if (thisRef.loggedIn) {
					thisRef.logoutInternal();
					thisRef.onDisconnect(thisRef.networkName);
				}
			}
		});
	}
	catch (exception) {
		FwpConnect.logError("Facebook", "init", exception.message || exception);
	} 
};

FwpConnect.FacebookAdapter.prototype.connect = function(callback) {
	this.tempOnLogin = callback;
	try {
		FB.ensureInit ( function (exception) {
			if(exception) {
				FwpConnect.logError("Facebook", "FB.connect:ensureInit", exception);
			}
			try {
				FB.Connect.requireSession();
			}
			catch (exc) {
				FwpConnect.logError("Facebook", "requireSession", exc.message || exc);
			}
		});
	}
	catch (exc) {
		FwpConnect.logError("Facebook", "connect:ensureInit", exc.message || exc);
	}
};

FwpConnect.FacebookAdapter.prototype.login = function(uid) {
	// for some reason facebook likes to call this twice, set logged in flag
	// so we ignore 2nd call
	this.loggedIn = true;
	
	// Cookie status is stale, log in user with facebook info
	var fields = 'birthday,sex,name,first_name,pic_square_with_logo,pic';
	var thisRef = this;
	try {
		FB.Facebook.apiClient.users_getInfo(uid, fields, function(result, exception) {
			if (exception) {
				FwpConnect.logError("Facebook", "FB.login:usersGetInfo", exception);
			}
			var userInfo = result[0];
			var params = {
				product: FwpConnect.product,
				network: thisRef.networkName,
				networkUserId: uid,
				birthday: userInfo.birthday,
				gender: userInfo.sex.toUpperCase(),
				displayName: userInfo.name,
				firstName: userInfo.first_name,
				photoUrlSmall: userInfo.pic_square_with_logo,
				photoUrl: userInfo.pic
			};
			
			// workaround due to fact that same callback is invoked by facebook
			// for initial connected status and user connect action, but we need
			// to invoke different callback handler for apps
			var onLogin = thisRef.tempOnLogin;
			//alert("onLogin: " + thisRef.onLogin);
			//alert("tempOnLogin: " + thisRef.tempOnLogin);
			if (onLogin) {
				thisRef.tempOnLogin = null;
			} else {
				onLogin = thisRef.onLogin;
			}
			FwpConnect.handler.networkLogin(params, function(isFirstTime) {
				onLogin(params, isFirstTime);
			});
		});
	}
	catch (exc) {
		FwpConnect.logError("Facebook", "login:usersGetInfo", exc.message || exc);
	} 
};

// facebook status is already logged out, need to delete the cookie and invoke callback
FwpConnect.FacebookAdapter.prototype.logoutInternal = function() {
	//alert('logoutInternal');

	// set loggedin flag
	this.loggedIn = false;
	
	// call handler which will delete cookie
	// call is syncrhonous, no callback
	FwpConnect.handler.networkLogout(this.networkName);
};

// user initiates logout, make facebook api call to log out
FwpConnect.FacebookAdapter.prototype.logout = function(callback) {
	var thisRef = this;
	try {
		FB.ensureInit ( function (exception) {
			if (exception) {
				FwpConnect.logError("Facebook", "FB.logout:ensureInit", exception);
			}
			if (thisRef.loggedIn) {
				// Log out of facebook
				try {
					FB.Connect.logout(function(complete, exception) {
						if (exception) {
							FwpConnect.logError("Facebook", "FB.logout", exception);
						}
						if (complete) {
							//alert('complete');
							thisRef.logoutInternal();
							callback(thisRef.networkName);
						} 
					});
				}
				catch (exc) {
					FwpConnect.logError("Facebook", "logout", exc.message || exc);
				}
			} else {
				// If not logged in to facebook then need to invoke callback now
				callback(thisRef.networkName);
			}
		}); 
	}
	catch (exc) {
		FwpConnect.logError("Facebook", "logout:ensureInit", exc.message || exc);
	}
};

FwpConnect.FacebookAdapter.prototype.getLinkStatus = function(callback) {
	if (this.loggedIn) {
		callback();
	} else if (this.isLinked) {
		callback(this.isLinked);
	} else {
		var thisRef = this;
		FwpConnect.handler.getLinkStatus(this.networkName, function(isLinked) {
			thisRef.isLinked = isLinked;
			callback(isLinked);
		});
	}
}

////////////////////////////////////////////////////////////////////////////////
// Remote Handler  /////////////////////////////////////////////////////////////
// This is used to handle remote ajax calls and cookie management,
// Other handlers could be substituted - use FwpConnect.handler = <your handler>
////////////////////////////////////////////////////////////////////////////////

FwpConnect.RemoteHandler = function() {
	this.remoteHost = '';
};

FwpConnect.RemoteHandler.prototype.networkLogin = function(params, onLogin) {
	var thisRef = this;
	$.post(this.remoteHost + "/networkLogin.jhtml", params, function (data, status) {
		if (status == "success") {
			// parse JSON response
			var dataObj = eval("(" + data + ")");
			thisRef.setCookies(dataObj);
			
			// invoke callback
			onLogin(dataObj.firstTime);
		}
	});
};

FwpConnect.RemoteHandler.prototype.networkLogout = function(networkName) {
	// delete the cookie
	FwpConnect.deleteCookie(networkName + 'UserInfo');
};

FwpConnect.RemoteHandler.prototype.getLinkStatus = function(networkName, callback) {
	var thisRef = this;
	$.post(this.remoteHost + "/getLoggedOutCookie.jhtml", {network: networkName}, function (data, status) {
		if (status == "success") {
			// parse JSON response
			var dataObj = eval("(" + data + ")");
			thisRef.setCookies(dataObj);
			
			// invoke callback
			callback(dataObj.isLinked);
		}
	});
};

FwpConnect.RemoteHandler.prototype.setCookies = function(dataObj) {
	// set the cookie
	for (var index in dataObj.cookies) {
		var cookie = dataObj.cookies[index];
		var expiry = new Date(new Date().getTime() + cookie.expiry * 1000);
		FwpConnect.setCookie(cookie.name, cookie.value, expiry, "/", null, null, false);
	}
}

FwpConnect.RemoteHandler.prototype.logError = function(network, action, message) {
	action = FwpConnect.page + " - " + action;
	$.post(this.remoteHost + "/logError.jhtml", {network:network, action:action, message:message}, function (data, status) {});
}

// use this as default handler
FwpConnect.handler = new FwpConnect.RemoteHandler();

