(function($) {
	function Testimonials(obj, opts, callback) {
		var defaults = {
			url: "/xml/testimonials_homepage.xml",
			sels: {
				blockquote:          ".testimonial-content blockquote",
				text:                ".testimonial-content blockquote p",
				img:                 ".testimonial-content .icon",
				author_name:         ".testimonial-username strong",
				author_position:     ".testimonial-username .position",
				author_organization: ".testimonial-username .organization",
				testimonial_content: ".testimonial-content",
				template:            ".testimonial-template",
				roller:              ".roller",
				prev_testimonial:    ".prev-testimonial",
				next_testimonial:    ".next-testimonial"
			},
			classes: {
				roller:   "roller",
				template: "testimonial-template",
				super_line: "super_line",
				border_line: "border_line"
			},
			text_max_length:   200,
			text_overflow_add: "...",
			prev_duration: 300,
			next_duration: 300,
			move: "left",
			animate: {
				duration: 800
			}
		};
		this.obj = obj;
		this.opts = $.extend(defaults, opts);
		this.tms = [];
		this.init(callback);
	}

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

	Testimonials.prototype.init = function(callback) {
		var instance = this;

		$("<div></div>")
		.addClass(this.opts.classes.roller)
		.css({
			marginLeft: (- $(this.obj).width()) + "px",
			width:      $(this.obj).width() * 3 + "px",
			height:     $(this.obj).height() + "px",
			"overflow": "hidden"
		})
		.appendTo($(this.obj));

		this.template = $(this.obj).find(this.opts.sels.testimonial_content).clone(false);
		$(this.obj).find(this.opts.sels.testimonial_content).remove();

		for(var i = 0; i < 3; i++) {
			this.template.clone(false)
			.appendTo($(this.obj).find(this.opts.sels.roller))
			.wrap(
				$("<div></div>")
				.addClass(this.opts.classes.template)
				);
		}
		$(this.obj).find(this.opts.sels.template)
		.show()
		.css({
			"width": $(this.obj).width() + "px",
			"height": $(this.obj).height() + "px",
			"float": "left",
			"visibility": "hidden"
		});

		$.ajax({
			async: true,
			type: "get",
			url:  this.opts.url + "?time=" + new Date().valueOf(),
			dataType: "xml",
			success: function (xml) {
				$(xml).find("item").each(
					function() {
						if($(this).find("visible").size() != 0) {
							if($(this).find("visible").text() == "false") {
								return;
							}
						}
						var index = instance.tms.length;
						instance.tms[index] = {
							order:               Number($(this).attr("order")),
							author_name:         $.trim($(this).find("authorName").text()),
							author_position:     $.trim($(this).find("authorPosition").text()),
							author_organization: $.trim($(this).find("authorOrganization").text()),
							text:                $.trim($(this).find("text").eq(0).text()),
							image_url:           $.trim($(this).find("imageUrl").text())
						};
						if($(this).find("forceClass").size() != 0) {
							instance.tms[index].force_class = $.trim($(this).find("forceClass").text());
						}
					});

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

	Testimonials.prototype.render = function(index, pos, tm) {
		var template = $(this.obj).find(this.opts.sels.template).eq(index);

		if(template.css("visibility") != "visible") {
			/*
			if(tm.text.length > this.opts.text_max_length) {
				var old_text = tm.text;
				tm.text = new RegExp("^[\\S\\s]{" + this.opts.text_max_length + "}\\S*", "g").exec(tm.text)[0];
				if(old_text != tm.text) {
					tm.text += this.opts.text_overflow_add;
				}
			}
			*/

			template.find(this.opts.sels.text).html(tm.text);
			if(tm.force_class != undefined) {
				template.find(this.opts.sels.text).addClass(tm.force_class);
			} else {
				if(pos == 0 || pos == this.tms.length) {
					template.find(this.opts.sels.text).addClass(this.opts.classes.border_line);
				} else {
					template.find(this.opts.sels.text).removeClass(this.opts.classes.border_line);
				}
				if(tm.text.length < this.opts.text_max_length) {
					template.find(this.opts.sels.text).addClass(this.opts.classes.super_line);
				} else {
					template.find(this.opts.sels.text).removeClass(this.opts.classes.super_line);
				}
			}
			template.find(this.opts.sels.img).attr("src", tm.image_url);
			if($.trim(tm.author_name) != "") {
				template.find(this.opts.sels.author_name).html(tm.author_name);
				template.find(this.opts.sels.author_position).html(tm.author_position);
				template.find(this.opts.sels.author_organization).html(tm.author_organization);
			} else {
				if($.trim(tm.author_position) != "") {
					template.find(this.opts.sels.author_name).html(tm.author_position);
					template.find(this.opts.sels.author_position).html("");
					template.find(this.opts.sels.author_organization).html(tm.author_organization);
				} else {
					template.find(this.opts.sels.author_name).html(tm.author_organization);
					template.find(this.opts.sels.author_position).html("");
					template.find(this.opts.sels.author_organization).html("");
				}
			}
			template.find(this.opts.sels.blockquote).show();
			template.css({
				"visibility": "visible"
			});
		}
	}

	Testimonials.prototype.set_current_testimonial = function(index) {
		if(index == 0) {
			var prev = $(this.obj).find(this.opts.sels.prev_testimonial).filter(":visible");
			prev.animate({
				marginLeft: "-" + prev.outerWidth() + "px"
			}, {
				duration: this.opts.prev_duration,
				complete: function() {
					$(this).hide();
				}
			});
		} else if(index == (this.tms.length - 1)) {
			var next = $(this.obj).find(this.opts.sels.next_testimonial).filter(":visible");
			next.animate({
				marginRight: "-" + next.outerWidth() + "px"
			}, {
				duration: this.opts.next_duration,
				complete: function() {
					$(this).hide();
				}
			});
		} else {
			var prev = $(this.obj).find(this.opts.sels.prev_testimonial).filter(":not(:visible)");
			prev.show().css({
				marginLeft: "-" + prev.outerWidth() + "px"
			}).animate({
				marginLeft: 0
			}, {
				duration: this.opts.prev_duration
			});
			var next = $(this.obj).find(this.opts.sels.next_testimonial).filter(":not(:visible)")
			next.show().css({
				marginRight: "-" + next.outerWidth() + "px"
			}).animate({
				marginRight: 0
			}, {
				duration: this.opts.next_duration
			});
		}
		if(index < 0 || index > (this.tms.length - 1)) {
			return;
		}

		this.current_index = index;
		this.render(1, index, this.tms[index]);
	}

	Testimonials.prototype.animate_buttons = function(index) {
		if(index == 0) {
			var prev = $(this.obj).find(this.opts.sels.prev_testimonial).filter(":visible");
			prev.animate({
				marginLeft: "-" + prev.outerWidth() + "px"
			}, {
				duration: this.opts.prev_duration,
				complete: function() {
					$(this).hide();
				}
			});
		} else if(index == (this.tms.length - 1)) {
			var next = $(this.obj).find(this.opts.sels.next_testimonial).filter(":visible");
			next.animate({
				marginRight: "-" + next.outerWidth() + "px"
			}, {
				duration: this.opts.next_duration,
				complete: function() {
					$(this).hide();
				}
			});
		} else {
			var prev = $(this.obj).find(this.opts.sels.prev_testimonial).filter(":not(:visible)");
			prev.show().css({
				marginLeft: "-" + prev.outerWidth() + "px"
			}).animate({
				marginLeft: 0
			}, {
				duration: this.opts.prev_duration
			});
			var next = $(this.obj).find(this.opts.sels.next_testimonial).filter(":not(:visible)")
			next.show().css({
				marginRight: "-" + next.outerWidth() + "px"
			}).animate({
				marginRight: 0
			}, {
				duration: this.opts.next_duration
			});
		}
	}

	Testimonials.prototype.set_next_testimonial = function(index) {
		this.animate_buttons(index);
		if(index < 0 || index > (this.tms.length - 1)) {
			return;
		}

		this.next_index = index;
		this.render(2, index, this.tms[index]);
	}

	Testimonials.prototype.animate = function(callback) {
		var instance = this;

		if(this.opts.move == "left") {
			$(this.obj).find(this.opts.sels.roller).find(this.opts.sels.template).css("float", "left");
		} else {
			$(this.obj).find(this.opts.sels.roller).find(this.opts.sels.template).css("float", "right");
		}

		//static variant

		$(this.obj).find(this.opts.sels.roller).find(this.opts.sels.template).eq(0)
		.appendTo($(instance.obj).find(instance.opts.sels.roller))
		.width($(instance.obj).width());
		$(instance.obj).find(instance.opts.sels.roller).find(instance.opts.sels.template).eq(0)
		.css("visibility", "hidden");

		instance.set_current_testimonial(instance.next_index);

		if($.isFunction(callback)) {
			callback.call(instance);
		}

	/*
		//moving variant

		$(this.obj).find(this.opts.sels.roller).find(this.opts.sels.template).eq(0)
		.animate({
			width: 0
		}, {
			duration: instance.opts.animate.duration,
			complete: function() {
				$(this).appendTo($(instance.obj).find(instance.opts.sels.roller));
				$(this).width($(instance.obj).width());
				$(instance.obj).find(instance.opts.sels.roller).find(instance.opts.sels.template).eq(0)
				.css("visibility", "hidden");

				instance.set_current_testimonial(instance.next_index);

				if($.isFunction(callback)) {
					callback.call(instance);
				}
			}
		});
		*/
	}

	$.fn.extend({
		Testimonials: function(opts, callback) {
			return this.each(
				function() {
					this.tm = new Testimonials(this, opts, callback);
				});
		},
		TestimonialsExtend: function(opts) {
			return this.each(
				function() {
					if(!this.tm) {
						return;
					}
					this.tm.extend(opts);
				});
		},
		TestimonialsSetCurrent: function(index) {
			return this.each(
				function() {
					if(!this.tm) {
						return;
					}
					this.tm.set_current_testimonial(index);
				});
		},
		TestimonialsSetNext: function(index) {
			return this.each(
				function() {
					if(!this.tm) {
						return;
					}
					this.tm.set_next_testimonial(index);
				});
		},
		TestimonialsAnimate: function(callback) {
			return this.each(
				function() {
					if(!this.tm) {
						return;
					}
					this.tm.animate(callback);
				});
		},
		TestimonialsGet: function() {
			return this.get(0).tm.current_index;
		},
		TestimonialsSize: function() {
			return this.get(0).tm.tms.length;
		}
	});
})(jQuery);
