(function($) {
	function FacebookFeed(obj, opts) {
		var defaults = {
			sels: {
				template: {
					parent:   ".element_template",
					username: ".username",
					backlink: ".backlink",
					message:  ".message"
				}
			},
			classes: {
				altern: "altern",
				loader: "loader"
			},
			message_max_length: 50,
			message_add_text: "...",
			uri: null
		};
		this.obj = obj;
		this.opts = $.extend(defaults, opts);
		this.feeds = [];
		this.init();
	}

	FacebookFeed.prototype.extend = function(opts) {
		this.opts = $.extend(this.opts, opts);
	}

	FacebookFeed.prototype.init = function() {
		this.template = $(this.obj).find(this.opts.sels.template.parent).clone(false);
	}

	FacebookFeed.prototype.load = function(count, callback) {
		var instance = this;
		
		var current_uri = parseUri(this.opts.uri);
		if(current_uri.protocol == "" || current_uri.host == "") {
			return;
		}
		var current_params = current_uri.queryKey;
		current_params.limit = count;
		current_params.callback = "?";
		var params = decodeURIComponent($.param(current_params));
		var go_uri = current_uri.protocol + "://" + current_uri.host + current_uri.path + "?" + params;

		$.ajax({
			url: go_uri,
			type: "get",
			dataType: "jsonp",
			success: function (json) {
				if(!json.paging) {
					instance.opts.uri = "";
					return;
				}

				//start http://bugs.developers.facebook.net/show_bug.cgi?id=17514
				//TODO: delete after facebook fix bug
				if(json.data[json.data.length - 1].id == instance.last_id) {
					instance.opts.uri = "";
					return;
				}
				instance.last_id = json.data[json.data.length - 1].id;
				//end http://bugs.developers.facebook.net/show_bug.cgi?id=17514
				
				instance.feeds = instance.feeds.concat(json.data);
				instance.opts.uri = json.paging.next;
				instance.render(json.data);

				if($.isFunction(callback)) {
					callback.call(instance);
				}
			},
			error: function (jqXHR, textStatus, errorThrown) {
				if($.isFunction(callback)) {
					callback.call(
						instance,
						{
							jqXHR: jqXHR,
							textStatus: textStatus,
							errorThrown: errorThrown
						});
				}
			}
		});
	}

	FacebookFeed.prototype.render = function(feeds) {
		$(this.obj).removeClass(this.opts.classes.loader);

		var save_scroll_top = $(this.obj).scrollTop();

		for(var index in feeds) {
			var current_template = this.template.clone(false);
			var feed = feeds[index];

			current_template.find(this.opts.sels.template.username)
			.attr("href", "http://www.facebook.com/profile.php?id=" + feed.from.id)
			.html(feed.from.name);

			if(feed.message) {
				if(feed.message.length > this.opts.message_max_length) {
					current_template.find(this.opts.sels.template.message)
					.html(feed.message.substring(0, this.opts.message_max_length) + this.opts.message_add_text);
				} else {
					current_template.find(this.opts.sels.template.message)
					.html(feed.message);
				}
			}

			feed.ids = feed.id.split("_");
			current_template.find(this.opts.sels.template.backlink)
			.attr("href", "http://www.facebook.com/permalink.php?story_fbid=" + feed.ids[1] + "&id=" + feed.ids[0]);

			current_template
			.appendTo($(this.obj))
			.show();

			if(current_template.index() % 2) {
				current_template.addClass(this.opts.classes.altern);
			}
		}

		$(this.obj).scrollTop(save_scroll_top);
	}

	$.fn.extend({
		FacebookFeed: function(opts) {
			return this.each(
				function() {
					this.ff = new FacebookFeed(this, opts);
				});
		},
		FacebookFeedLoad: function(count, callback) {
			return this.each(
				function() {
					if(!this.ff) {
						return;
					}
					this.ff.load(count, callback);
				});
		},
		FacebookFeedExtend: function(opts) {
			return this.each(
				function() {
					if(!this.ff) {
						return;
					}
					this.ff.extend(opts);
				});
		}
	});
})(jQuery);
