var dynposStop = false;
$.fn.dynpos = function(opts) {
	var defaults = {
		header: null,
		footer: null,
		leftElem: null,
		rightElem: null,
		elongation: false,
		padding: [0, 0, 0, 0],
		unitWidth: 190,
		unitMargin: 10,
		auto: false,
		interval: 1500,
		centering: false,
		animation: {
			duration: 500,
			easing: "easeInOutCubic"
		}
	};
	var opts = $.extend(defaults, opts);
	var adjust = function(th) {
		return function() {
			if(dynposStop) return;
			var ww = $(window).width();
			var units = fy = [];
			var l = r = t = b = cnt_w = su = 0;
			if(opts.leftElem) {
				l += opts.leftElem.width() + opts.unitMargin;
			}
			l += opts.padding[3];
			if(opts.rightElem) {
				if(opts.rightElem.css("right").match(/^\d+/)) r += parseInt(opts.rightElem.css("right")) + opts.unitMargin;
			}
			r += opts.padding[1];
			cnt_w = ww - l - r;
			while(su * opts.unitWidth + (su-1 < 0 ? 0 : su-1) * opts.unitMargin < cnt_w) su++;
			su--;
			if(su < 4) su = 4;

			var lp = tw =0;
			if(opts.centering) {
				if(opts.leftElem) tw += opts.leftElem.outerWidth();
				if(opts.rightElem) tw += opts.rightElem.outerWidth();
				tw += opts.padding[3] + (opts.unitWidth + opts.unitMargin) * su + opts.padding[1];
				if(tw < ww) lp = (ww - tw) / 2;
				else lp = 0;
				l += lp;
				if(opts.header) {
					opts.header.animate({ left: lp + "px" }, opts.animate);
				}
				if(opts.leftElem) {
					opts.leftElem.animate({ left: lp + "px" }, opts.animate);
				}
			}


			if(opts.header) {
				if(opts.header.css("top").match(/^\d+/)) t += parseInt(opts.header.css("top"));
				t += opts.header.height() + opts.unitMargin;
			}
			t += opts.padding[0];
			for(var i=0;i<su;i++) fy[i] = t;
			var detU = function (w, unt, mgn) {
				var i=1;
				while(w >= unt * i + mgn * (i - 1)) i++;
				i--;
				return i;
			};
			th.each(function() {
				var p = 0;
				var e = $(this);
				var x = tx = parseInt(e.css('left'));
				var y = ty = parseInt(e.css('top'));
				var u = detU($(this).outerWidth(), opts.unitWidth, opts.unitMargin);
				if(u==1) {
					var m = fy[0];
					for(var i=1; i<su; i++) if(fy[i]<m) m=fy[i];
					for(i--;i>=0;i--) if(m==fy[i]) p=i;
					tx = l + (opts.unitWidth + opts.unitMargin) * p;
					ty = fy[p];
					fy[p] += e.outerHeight() + opts.unitMargin;
				} else if(u < su) {
					var pmax = [];
					for(var i=0; i<=su-u; i++) {
						var pa = [];
						for(var j=0; j<u; j++) pa.push(fy[i+j]);
						pmax[i] = pa[0];
						for(j=1; j<u; j++) if(pa[j] > pmax[i]) pmax[i] = pa[j];
					}
					var m = pmax[0];
					for(i=1; i<=su-u; i++) if(pmax[i] < m) m = pmax[i];
					for(; i>=0; i--) if(m == pmax[i]) p = i;
					tx = l + (opts.unitWidth + opts.unitMargin) * p;
					ty = pmax[p];
					for(i=0; i<u; i++) fy[p+i] = ty + e.outerHeight() + opts.unitMargin;
				} else {
					var m = fy[0];
					for(var i=0; i<su; i++) if(m < fy[i]) m = fy[i];
					tx = l + (opts.unitWidth + opts.unitMargin) * p;
					ty = m;
					for(i=0; i<su; i++) fy[i] = ty + e.outerHeight() + opts.unitMargin;
				}
				if((x != tx) || (y != ty) || e.css('opacity')!=1) {
					e.animate({ left: tx + "px", top: ty + "px", opacity: 1, filter: 'alpha(opacity=100)', '-moz-opacity': 1 }, opts.animation);
				}
			});
			var m = 0;
			for(var i=0; i<su; i++) if(fy[i] > m) m = fy[i];
			m += opts.padding[2];
			if(opts.footer) {
				var opt = { top : m + "px" };
				var ll = l + su * (opts.unitWidth + opts.unitMargin) + r;
				switch(opts.footerAlign) {
				case "region_right" :
					opt["left"] = (l + su * opts.unitWidth + (su - 1) * opts.unitMargin - opts.footer.outerWidth()) + "px";
					break;
				case "region_left" :
					opt["left"] = l + "px";
					break;
				case "right" :
					opt["left"] = (ll - r - opts.footer.outerWidth()) + "px";
					break;
				case "center" :
					opt["left"] = (ll / 2 - opts.footer.outerWidth() / 2) + "px";
					break;
				case "left" :
				default :
					opt["left"] = lp + "px";
					break;
				}
				opts.footer.animate(opt, opts.animation);
			}
			if(opts.elongate) {
				if(opts.leftElem) {
					var lt = (opts.leftElem.css("top").match(/^\d+/) ? parseInt(opts.leftElem.css("top")) : 0);
					opts.leftElem.height(m - lt - 10);
				}
				if(opts.rightElem) {
					var rt = (opts.rightElem.css("top").match(/^\d+/) ? parseInt(opts.rightElem.css("top")) : 0);
					opts.rightElem.height(m - rt);
				}
			}
		};
	};
	adjust(this)();
	if(opts.auto) setInterval(adjust(this), opts.interval);
	return this;
};

