var Facebook = function(){
	// UI elements specific to facebook must be put in a bucket begining with this string
	// eg: <div class="bf_dom" rel:bf_bucket="facebook-logged-in" />
	this.SIGNIN_FOR_EXTRA_FEATURES = new Template('<div class="facebook-like-login-pane"> \
		<h3>Add Your Reactions to BuzzFeed!</h3> \
		<fb:login-button perms="publish_stream,email" length="long" autologoutlink="false"></fb:login-button> \
		<a href="#" onclick="return false" class="bf_dom no-thanks" rel:bf_bucket="event_handler" rel:actions="click:facebook.squelch_extra_features_prompt">No Thanks</a> \
		<a href="#" onclick="return false" class="bf_dom have-account" rel:bf_bucket="event_handler" rel:actions="click:facebook.show_signin_tab" rel:data="{buzz_id:#{buzz_id}}">More Sign In Options</a>\
	</div>');
	
	this.social_element_key = 'facebook';
	this.auto_register_enabled = true;
	this.auto_register_enabled = true;
	this.link_accounts_enabled = false;
	this.cache = {};
	
	// Facebook-specific quiz result handler
	this.quiz_result = function(obj) {
		if ( facebook.is_logged_in() ) {
			facebook.publish_quiz_result(obj);
		}
	}
	
	// Facebook-specific quickpost handler
	this.quickpost = function(obj) {
		if ( obj.draft ) return;
		var fb_post = $('facebook_post_contribution_checkbox');
		var fb_fan_page = $('facebook_post_to_fanpage_checkbox') || {checked:false};
		if ( fb_post && fb_post.checked ) {
			if ( facebook.is_logged_in() ) {
				facebook.publish_quickpost(obj);
			}
		}
		if ( fb_fan_page.checked ) {
			var base_data = facebook._get_quickpost_base_data(obj);
			facebook._publish_to_fan_page(base_data);
		}
	}

	// Facebook-specific contribution handler
	this.contribute = function(obj) {
		var post_checkbox = $('facebook_post_contribution_checkbox');
		if ( post_checkbox && post_checkbox.checked == false ) return;
		if ( facebook.is_logged_in() ) {
			facebook.publish_contribution(obj);
		}
	}

	this.publish_quiz_result = function(obj) {
		FB.ui({
			method: 'stream.publish',
			message: obj.quiz_description,
			attachment: {
				name: ' took the ' + unescape(obj.quiz_name) + ' quiz on BuzzFeed and got ' + unescape(obj.result) + '.',
				caption: '',
				description: (
					obj.quiz_description
				),
				href: obj.uri
			},
			action_links: [
				{ text: 'Take The Quiz!', href: obj.uri }
			],
			user_prompt_message: 'What\'s on your mind'
		},
		function(response) {
			if (response && response.post_id) {
				//alert('Post was published.');
			} else {
				//alert('Post was not published.');
			}
		});
	}
	
	this._get_quickpost_base_data = function(obj) {
		if ( !obj.thumb && obj.image_src ) obj.thumb = obj.image_src
		if ( obj.thumb ) {
			if(! obj.thumb.match(/http:\/\//)) {
				obj.thumb = BF_STATIC.fb_server_root + obj.image_src;
			}
			obj.images = new Array({
				src : obj.thumb,
				href: 'http://buzzfeed.com/'+obj.username+'/'+obj.uri
			});
			obj.images.each( function(el){
				el.src = el.src.replace('http://dev.buzzfeed.com','http://facebook-dev.buzzfeed.com:8080');
				el.type = 'image';
			});
		}
		var base_data = {
			message: 'just posted ' + obj.title + ' to BuzzFeed!',
			attachment: {
				name: obj.title,
				caption: obj.text,
				media: obj.images,
				href: 'http://buzzfeed.com/' + obj.username + '/' + obj.uri
			},
			action_links: [
				{ text: 'Respond', href: 'http://buzzfeed.com/'+obj.username+'/'+obj.uri }
			]
		}
		return base_data;
	}
	
	this.publish_quickpost = function(obj) {
		if ( obj.draft ) return;
		var base_data = facebook._get_quickpost_base_data(obj);
		base_data.method = 'stream.publish';
		base_data.user_prompt_message = '(Promote Your Post)'
		FB.ui(base_data,
		function(response) {
			if (response && response.post_id) {
				//alert('Post was published.');
			} else {
				//alert('Post was not published.');
			}
		});
	}
	
	this._publish_to_fan_page = function(data) {
		var obj = {};
		for ( var each in data ) {
			obj[each] = data[each];
		}
		delete obj.action_links ;
		obj.attachment = FB.JSON.stringify(obj.attachment);
		obj.uid = facebook.cache.user_page_id;
		obj.action = 'like_publish';
		// If no user page ID, get one; the callback re-invokes this method when ready
		if ( !obj.uid ) {
			facebook.cache_data = obj;
			facebook._get_user_page_id();
		}
		else {
			facebook.request('/buzzfeed/_facebook',{
				method : 'get',
				parameters : obj,
				onComplete: function(){}
			});
		}
	}
	
	this._get_user_page_id = function() {
		var user_info = (new BF_User()).getUserInfo();
		var url = 'http://www.buzzfeed.com/' + user_info.username;
		facebook.user_page_id_handler = function(result) {
			var obj = eval(result);
			if ( typeof obj != 'undefined' && obj.length > 0 ) {
				facebook.cache.user_page_id = (obj.shift()).id;
				facebook._publish_to_fan_page(facebook.cache_data);
			}
			else {
				// No FB page found
			}
		}
		facebook.request('https://api.facebook.com/method/fql.query',{
			inject : true,
			method:'get',
			parameters : {
				query : 'SELECT id FROM object_url WHERE url=\'' + url + '\'',
				format : 'JSON',
				callback : 'facebook.user_page_id_handler'
			}
		});
	}
	
	this.publish_contribution = function(obj) {
		var user_info = (new BF_User()).getUserInfo();
		var username = user_info.username;
		if( obj.image_src ) {
			if(! obj.image_src.match(/http:\/\//)) {
				obj.image_src = BF_STATIC.fb_server_root + obj.image_src;
			}
			obj.images = new Array({
				src : obj.image_src,
				href: obj.username ? 'http://buzzfeed.com/'+username+'/'+obj.uri : 'http://buzzfeed.com/' + obj.uri
			});
			obj.images.each( function(el){
				el.src = el.src.replace('http://dev.buzzfeed.com','http://facebook-dev.buzzfeed.com:8080');
				el.type = 'image';
			});
		}
		FB.ui({
			method: 'stream.publish',
			message: obj.text,
			attachment: {
				name: obj.parent_title,
				caption: '',
				description: (
					obj.parent_blurb
				),
				media: obj.images,
				href: obj.images[0].href
			},
			action_links: [
				{ text: 'Respond', href: 'http://www.buzzfeed.com/'+obj.parent_username+'/'+obj.parent_uri }
			],
			user_prompt_message: ''
		},
		function(response) {
			if (response && response.post_id) {
				//alert('Post was published.');
			} else {
				//alert('Post was not published.');
			}
		});
	}

	// Callback when someone likes something
	this.liked_something = function(href, widget) {
		facebook.track_like(widget.dom);
		var user = new BF_User();
		var buzz_id = widget.dom.getAttribute('rel:buzz_id');
		var uri = widget._attr.href;
		var idx = uri.lastIndexOf('/',uri.lastIndexOf('/')-1);
		uri = uri.substring(idx);
		if ( user.isLoggedIn() ) {
			if ( buzz_id ) {
				badge_vote_manager.simple_love_vote(uri, buzz_id);
			}
		}
		else {
			// extra features signin box
			if ( buzz_id ) {
				facebook.signin_for_extra_features_box({
					append_to:widget.dom.parentNode,
					buzz_id:buzz_id,
					uri:uri
				});
			}
		}
	}
	
	this.track_like = function(el){
		if ( typeof facebook.like_count == 'undefined' ) facebook.like_count = 1;
		else facebook.like_count++;
		var like_count = facebook.like_count < 5 ? facebook.like_count : '5+';
		var position = el.getAttribute('rel:page_type') || 'unknown';
		position = position.toLowerCase();
		var track_url = '/_ga/click/facebook-like/' + position + '/' + like_count;
		Tracker.gClick(track_url);
	}
	
	this.squelch_extra_features_prompt = function(){
		createCookie('squelch_fb_features_prompt', 'true', 30);
		facebook.squelch_extra_features_promo = true;
	}
	
	this.show_signin_tab = function(args){
		var el = $('tab1-signin_special-' + args.buzz_id);
		if ( el ) el.addClassName('hidden');
		el = $('tab2-signin_special-' + args.buzz_id);
		if ( el ) el.removeClassName('hidden');
		$('login-submit').value='Sign In';
		$('register-submit').value='Register';
		if ($('preview-again-from-registration')) $('preview-again-from-registration').hide();
		if ($('preview-again-from-login')) $('preview-again-from-login').hide();
		bf_login.args = { action: 'fb_like' };
		var reg = new BF_Register();
		reg.register_handler(false,{action:'fb_like'});
		reg.fb_register_handler(false,{action:'fb_like'});
		$('registration-div').show();
		el.parentNode.appendChild($('registered-success').cloneNode(true));
	}
	
	this.signin_for_extra_features_box = function(args) {
		if ( facebook.squelch_extra_features_promo ) return;
		var id = 'signin_special-' + (args.buzz_id || (new Date()).getTime());
		var uri = args.uri || '/';
		var el = args.append_to || document.getElementsByTagName('BODY')[0];
		
		if ( $(id) ) {
			var obj = $(id);
			$(id).parentNode.removeChild($(id));
			el.appendChild(obj);
			obj.removeClassName('hidden');
			tab1.removeClassName('hidden');
			tab2.addClassName('hidden');
		}
		else {
			var div = document.createElement('div');
			div.id = id;
			var tab1 = document.createElement('div');
			tab1.id = 'tab1-' + id;
			var tab2 = document.createElement('div');
			tab2.id = 'tab2-' + id;
			tab1.removeClassName('hidden');
			tab2.addClassName('hidden');
			div.appendChild(tab1);
			div.appendChild(tab2);
			tab1.innerHTML = facebook.SIGNIN_FOR_EXTRA_FEATURES.evaluate({buzz_id:args.buzz_id});
			var registration_div = $('registration-div');
			if ( registration_div ) {
				registration_div.parentNode.removeChild(registration_div);
				tab2.appendChild(registration_div);
			}
			el.appendChild(div);
			FB.XFBML.parse(el);
			universal_dom.update(el);
			if (args.buzz_id) bf_login.loggedInCallbacks.push(function(){try{$(id).addClassName('hidden')}catch(e){};badge_vote_manager.simple_love_vote(uri, args.buzz_id)});
		}
	}
	
	this.load_friends = function() {
		if ( facebook.access_token ) {
			if ($('not-logged-in')) $('not-logged-in').addClassName('hidden');
			facebook.request('https://graph.facebook.com/me/friends',{
				inject : true,
				method:'get',
				parameters : {
					access_token:facebook.access_token,
					callback : 'facebook._load_friends',
					format: 'JSON'
				}
			});
		}
		else {
			if ($('not-logged-in')) $('not-logged-in').removeClassName('hidden');
		}
	}
	
	this._load_friends = function(r) {
		var fb_friend_ids = [];
		r.data.each( function(obj){
			fb_friend_ids.push(obj.id);
		});
		facebook.request('/buzzfeed/_facebook', {
			method:'post',
			parameters : {
				action:'follow_page',
				friends:fb_friend_ids.join(',')
			},
			onSuccess : facebook._load_friends_ok
		});
	}
	
	this._load_friends_ok = function(r) {
		$('content').update(r.responseText);
	}
	
	// Add the fb-root div and loads the facebook library
	this.init = function() {
		FB.init({appId:BF_STATIC.fb_app_id,xfbml:true,cookie:true,status:true});
		FB.getLoginStatus(facebook.handle_session_change);
		FB.Event.subscribe('auth.sessionChange', facebook.handle_session_change);
		FB.Event.subscribe('edge.create', facebook.liked_something);
		social.observe('contribute', facebook.contribute);
		social.observe('quickpost', facebook.quickpost);
		social.observe('quiz_result', facebook.quiz_result);
		facebook.squelch_extra_features_promo = readCookie('squelch_fb_features_prompt') == 'true';
		// hack for bug in posting attachments with media
		origPostTarget = FB.Content.postTarget;
		FB.Content.postTarget = function(opts) {
			opts.params.action_links = FB.JSON.stringify(opts.params.action_links);
			opts.params.attachment  = FB.JSON.stringify(opts.params.attachment);
			origPostTarget(opts);
		};
	}
	
	this.is_logged_in = function() {
		return typeof facebook.session != 'undefined';
	}
	
	// Log out of facebook and also run the specified logout function (eg buzzfeed logout)
	this.logout = function(fn) {
		facebook.logged_out();
		if ( facebook.is_logged_in() ) FB.logout(fn);
		else fn();
	}
	
	// Update page to reflect FB logged-out state
	this.logged_out = function() {
		facebook.hide_ui_elements('logged-in');
		facebook.show_ui_elements('logged-out');
	}
	
	// Update page to reflect FB logged-in state; if user isn't logged into BF try to log them in
	this.logged_in = function() {
		facebook.show_ui_elements('logged-in');
		facebook.hide_ui_elements('logged-out');
		facebook.update_ui_elements();
		var user = new BF_User();
		if ( !user.isLoggedIn() ) {
			facebook.auto_log_into_buzzfeed();
		}
		facebook.fire_event('user_logged_in');
	}
	
	// Handle changes in user's FB state
	this.handle_session_change = function(response) {
		if ( response.session ) {
			facebook.session = response.session;
			facebook.access_token = response.session.access_token;
			document.cookie='fb_session_key=' + facebook.session.session_key;
			FB.api('/me', function(r){
				facebook.user_data = r;
				facebook.logged_in();
			})
		}
		else {
			delete facebook.session;
			document.cookie='fb_session_key=';
			facebook.logged_out();
		}
	}
	
	// Log an FB user into BF; creating a new BF user record for them if necessary
	this.auto_log_into_buzzfeed = function(){
		if ( !facebook.is_logged_in() || facebook.block_login ) return;
		facebook.block_login = true;
		var buzzfeed_login = function(session){
			var params = {
				method:'post',
				parameters:{
					facebook_uid : session.uid,
					fb_username : facebook.user_data.name
				},
				onSuccess:function(r){
					var obj = eval('('+r.responseText+')');
					// if login succeeded, update the cookie as usual
					if ( obj.login ) {
						bf_login.loggedIn(r);
						facebook.block_login = false;
					}
					// if login failed, register a new user or offer link accounts dialog
					else {
						if ( !facebook.tried_to_register ) facebook.auto_register(obj);
						if ( facebook.link_accounts_enabled ) bf_login.switch_to_link_accounts(obj);
					}
				},
				onFailure:function(){
					//console.warn('Unable to log into BuzzFeed');
				}
			};
			facebook.request( '/bfcgi/_www_login?cb=' + (new Date()).getTime(), params );
		}
		FB.getLoginStatus( function(response){
			if ( response.session ) buzzfeed_login(response.session);
			else {
				var fn = function(){
					FB.getLoginStatus( function(response){
						buzzfeed_login(response.session);
					})
				}
				var perms = 'publish_stream,email'
				FB.login( fn, {perms:perms} );
			}
		});
	}
	
	this.link_accounts = function() {
		if ( !facebook.link_accounts_enabled ) return;
		try{
			new Ajax.Request( '/buzzfeed/_edit_user', {
				method : 'get',
				asynchronous : false,			
				parameters : { 
					action: 'link_facebook_account' ,
					facebook_uid : facebook.session.uid,
					onSuccess : function( r ) { },
					onFailure : function( r ) { }
				}
			});
		} catch(e){}
	}

	this.__events = {};
	this.observe = function(ev, fn) {
		var listeners = facebook.__events[ev] || [];
		listeners.push(fn);
		facebook.__events[ev] = listeners;
	}
	
	this.fire_event = function(ev) {
		if ( typeof facebook.__events[ev] != 'undefined' ) {
			facebook.__events[ev].each(function(fn){
				fn();
			}); 
		}
	}
	
	this.auto_register = function(obj) {
		if ( !facebook.auto_register_enabled ) return;
		var email = 'get_from_facebook@buzzfeed.com';
		try {
			email = facebook.user_data.email;
		} catch(e){}
		if ( typeof email == 'undefined' || email.length == 0 ) email = 'get_from_facebook@buzzfeed.com';
		var params = {
			name: obj.username,
			username: obj.username,
			pw: obj.password,
			email: email,
			contribute: 1,
			allow_email_updates: 1,
			facebook_uid: facebook.session.uid,
			import_fb_profile : 'true',
			facebook_session_key : facebook.session.session_key
		} 
		facebook.request('/buzzfeed/_contribute_register', {
			method: 'post',
			parameters: params,
			onSuccess: function(e) {
				Tracker.gClick('/_facebook_registered');
				facebook.block_login = false;
				facebook.tried_to_register = true;
				facebook.auto_log_into_buzzfeed();
			},
			onFailure: function(e){
				facebook.block_login = false;
			}
		});
	}
	
	this.request = function(url,params) {
		if ( params.inject ) {
			var e = document.createElement('script');
			e.src = url;
			e.async = true;
			if ( params.parameters ) {
				var list_params = [];
				for ( var p in params.parameters ) {
					list_params.push( p + '=' + escape(params.parameters[p]));
				}
				e.src += '?' + list_params.join('&');
			}
			document.getElementById('fb-root').appendChild(e);
		}
		else {
			var ajax = new BF_Request();
			ajax.request(url,params);
		}
	}
	
	// Add fb-root element
	this._add_fb_root = function() {
		if ( !$('fb-root') ) {
			var div = document.createElement('div');
			div.id = 'fb-root';
			document.getElementsByTagName('BODY')[0].appendChild(div);
		}
	}
	
	// Helper for getting facebook elements from universal_dom
	this.get_ui_elements = function(type,opts) {
		return social._get_ui_elements(this.social_element_key,type,opts);
	}
	
	// Hide facebook elements en masse
	this.hide_ui_elements = function(type) {
		this.get_ui_elements(type).each(function(el){
			el.addClassName('hidden');
		});
	}
	
	// Show facebook elements en masse
	this.show_ui_elements = function(type) {
		this.get_ui_elements(type).each(function(el){
			el.removeClassName('hidden');
		});
	}

	// Update facebook elements en masse
	this.update_ui_elements = function() {
		this.get_ui_elements('update',{with_data:true}).each(function(el){
			el.element.update(eval(el.data.value));
		});
	}
}
var facebook = new Facebook();
window.fbAsyncInit = facebook.init;
if ( typeof BuzzLoader != 'undefined' ) {
BuzzLoader.register(function(){
	facebook._add_fb_root();
	var e = document.createElement('script');
	e.src = document.location.protocol + '//connect.facebook.net/en_US/all.js';
	e.async = true;
	document.getElementById('fb-root').appendChild(e);
} ,2);
}
