// 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(config) {
		// set product config overwrite existing default values
		for (var name in config) {
			this.config[name] = config[name];
		}
		
		// 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) {
		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++;
				
				if (logoutCount == networkCount && callback) {
					callback();
				}
			});
		}
	},
	
	// Delete network cookies without actually logging user out of networks.
	// Synchronous; no callback
	logoutInternal: function() {
		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.toLowerCase()].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" : "" );
		document.cookie = cookie;
	},
	
	deleteCookie: function(name) {
		FwpConnect.setCookie(name, '', new Date(), "/");
	},
	
	debug: function ( _msg ){
		try {
			console.log( _msg );
		} catch(ERR){}
	},
	
	// Product configuration
	config: {
		userInfoFields:	'birthday,sex,name,first_name,last_name,pic_square_with_logo,pic',
		maxPostCount:	0,
		onUserNotConnected: {
			handler: null
		},
		onNetworkLogin: {
			getUserData: false,
			setCookies: true,
			handler: null
		},
		onLogin: {
			useNetworkLogin: true,
			handler: null
		},
		onLinkStatus: {
			getUserData: false,
			handler: null
		},
		onLogError: {
			logViaAjax: false,
			handler: null
		}
	}
};


/////////////////////////////////////////////////////////////////////
// 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) {
				FB.Facebook.get_sessionWaitable().waitUntilReady( function(status) {
					if (!thisRef.loggedIn && uid && uid != "null") {
						thisRef.login(uid);
					}
				});				
			},
			ifUserNotConnected: function() {
				thisRef.loggedIn = false;
				if (typeof FwpConnect.config.onUserNotConnected.handler == "function") {
					FwpConnect.config.onUserNotConnected.handler(thisRef);
				} else {
					if (thisRef.loggedIn) {
						thisRef.logoutInternal();
						thisRef.onDisconnect(thisRef.networkName);
					}
				}
			}
		});
	}
	catch (exc) {
		FwpConnect.logError("Facebook", "init", exc.message || exc);
	} 
};

FwpConnect.FacebookAdapter.prototype.connect = function(callback) {
	this.tempOnLogin = callback;
	try {
		FB.ensureInit ( function (exc) {
			if (exc) {
				FwpConnect.logError("Facebook", "FB.connect:ensureInit", exc.message || exc);
			}
			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) {	
	// Cookie status is stale, log in user with facebook info
	var fields = FwpConnect.config.userInfoFields;
	var thisRef = this;
	try {
		FB.Facebook.apiClient.users_getInfo(uid, fields, function(result, exception) {			
			if (exception) {
				FwpConnect.logError("Facebook", "FB.login:usersGetInfo", exception.message || exception);
			} else {
				//moved logged state change inside the success callback function and we only need to set it once
				thisRef.loggedIn = FwpConnect.networks.facebook.loggedIn = true;
				
				var userInfo = result[0];
				FwpConnect.fbUserInfo = {
					product: FwpConnect.product,
					network: thisRef.networkName,
					networkUserId: uid,
					birthday: userInfo.birthday,
					gender: userInfo.sex || "MALE",
					displayName: userInfo.name,
					firstName: userInfo.first_name,
					lastName: userInfo.last_name,
					photoUrlSmall: userInfo.pic_square_with_logo,
					photoUrl: userInfo.pic,
					data: userInfo
				};
				// 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
				// Note: onLogin is the function passed as the 2nd parameter to the FwpConnect.connect call
				var onLogin = thisRef.tempOnLogin;
				
				if (onLogin) {
					thisRef.tempOnLogin = null;
				} else {
					onLogin = thisRef.onLogin;
				}
				
				if (FwpConnect.config.onLogin.useNetworkLogin){
					if (onLogin) {
						FwpConnect.handler.networkLogin(FwpConnect.fbUserInfo, function(isFirstTime) {
							onLogin(FwpConnect.fbUserInfo, isFirstTime);
						});
					} else {
						FwpConnect.handler.networkLogin(FwpConnect.fbUserInfo);
					}
				} else if (onLogin) {
					onLogin();
				}
			}
		});
	}
	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() {
	// 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) {
							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 (!FwpConnect.config.onLinkStatus.getUserData ) {
		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);
			});
		}
	} else {
		var thisRef = this;
		FwpConnect.handler.getLinkStatus(thisRef.networkName, function(sData) {
			thisRef.isLinked = sData.isLinked;
			thisRef.hasMatch = sData.hasMatch || false;
			callback(sData);
		});
	}
}

////////////////////////////////////////////////////////////////////////////////
// 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) {
	if (typeof FwpConnect.config.onNetworkLogin.handler == "function") {
		FwpConnect.config.onNetworkLogin.handler(this, params, onLogin);
	} else {
		onLogin( params );
	}
};

FwpConnect.RemoteHandler.prototype.networkLogout = function(networkName) {
	FwpConnect.deleteCookie(networkName + 'UserInfo');// delete the cookie	
};

FwpConnect.RemoteHandler.prototype.getLinkStatus = function(networkName, callback) {
	if (typeof FwpConnect.config.onLinkStatus.handler == "function") {
		FwpConnect.config.onLinkStatus.handler(this, networkName, callback);
	}
};

FwpConnect.RemoteHandler.prototype.setCookies = function(dataObj) {
	this.isLinked = dataObj.isLinked;//store linked status
	
	// 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) {
	if (FwpConnect.config.onLogError.logViaAjax && typeof FwpConnect.config.onLogError.handler == "function") {
		FwpConnect.config.onLogError.handler(network, action, message);
	} 
	//TODO: put this code in IWON onLogError handler
	//urchinTracker( "/clicks/fbconnect/gameplayer/error/"+action.toLowerCase().replace(' ','_')+"/"+ message.toLowerCase().replace(' ','_')  );
}

// use this as default handler
FwpConnect.handler = new FwpConnect.RemoteHandler();