(function($){
$.p8_sortable = function(options){


this.options = $.extend(options, {
	selector: {
		range: options.selector.range ,
		drag: options.selector.drag || '',
		container: options.selector.container || ''
	},
	sort: options.sort || null,
	sorted: options.sorted || null,
	beforeSort: options.beforeSort || null,
	holder_css: options.holder_css || '',
	type: options.type || 'all'
});

this.drag_selector = this.options.selector.drag.length ? true : false;
this.container_selector = this.options.selector.container.length ? true : false;
this.holder = null;
this.container_timeout = null;
var _this = this;


this.refresh = function(){
	this.range = $(this.options.selector.range);
	
	this.range.each(function(){
		
		var item = $(this);
		
		item.data('position', item.css('position').toLowerCase());
		var handle = _this.drag_selector ? $(_this.options.selector.drag, item) : item;
		
		if(!item.data('p8_sortable')){
			item.jqDrag(
				handle,//.unbind('mousedown', _this.drag_mousedown).bind('mousedown', {item: item}, _this.drag_mousedown),
				{
					drag: _this.drag,
					dragging: _this.dragging,
					stop: _this.item_stop,
					lock: _this.options.type == 'x' ? 'y' :
						_this.options.type == 'y' ? 'x' : ''
				}
			);
			
			item.data('p8_sortable', true);
		}
	});
};

this.drag = function(e, item){
	_this.item = item;
	
	item.data('width', item.width());
	item.data('height', item.height());
	item.data('x', item.offset().left);
	item.data('y', item.offset().top);
	
	var css = {height: item.data('height') +'px'};
	if(_this.options.holder_css){
		css.border = _this.options.holder_css;
	}else{
		css.visibility = 'hidden';
	}
	_this.holder = item.clone().attr('id', '').empty().insertAfter(item).css(css);
	
	item.css({position: 'absolute', width: item.data('width') +'px', height: item.data('height') +'px', left: item.data('x'), top: item.data('y')});
};


this.dragging = function(e, element){
	clearTimeout(_this.container_timeout);
	
	var w = _this.item.data('width'), h = _this.item.data('height');
	
	var found = false;
	_this.range.not(_this.item).not(_this.holder).each(function(){
		var _item = $(this), pos;
		
		var offset = _this.item.offset(), _offset = _item.offset();
		
		var x = offset.left, y = offset.top,
			_w = _item.width(), _h = _item.height(),
			_x = _offset.left, _y = _offset.top,
			u, d, l, r;
		
		if(y <= _y + _h/2 && y >= _y){
			//up, before
			u = true;
		}else if(y + h >= _y + _h/2 && y + h <= _y + _h){
			//down, after
			d = true;
		}
		
		if(x <= _x + _w/2 && x >= _x){
			//left
			l = true;
		}else if(x + w >= _x + _w/2 && x + w <= _x + _w){
			//right
			r = true;
		}
		
		if(_this.options.type == 'x'){
			if(r) pos = 1;
			if(l) pos = -1;
		}else if(_this.options.type == 'y'){
			if(d) pos = 1;
			if(u) pos = -1;
		}else if(u && l){
			pos = -1;
		}else if(u && r){
			pos = -1;
		}else if(d && l){
			pos = 1;
		}else if(d && r){
			pos = 1;
		}
		
		if(pos){
			//current.insertAfter(_item);
			pos == 1 ? _this.holder.insertAfter(_item) : _this.holder.insertBefore(_item);
			_this.holder.data('to', _item);
			
			if(_this.options.beforeSort)
				_this.options.beforeSort(_item);
			
			found = true;
			return false;
		}
	});
	
	if(!_this.container_selector || found){
		return;
	}
	
	_this.container_mousemove();
	//_this.container_timeout = setTimeout(function(){_this.container_mousemove();}, 500);
	
};

this.container_mousemove = function(){
	clearTimeout(_this.container_timeout);
	$(_this.options.selector.container).each(function(){
		var container = $(this);
		//var _range = $(_this.options.selector.range, container);
		
		//if(_range.length) return;
		
		var offset = _this.item.offset(), _offset = container.offset();
		var w = _this.item.data('width'), h = _this.item.data('height');
		
		var x = offset.left, y = offset.top,
			_w = container.width(), _h = container.height(),
			_x = _offset.left, _y = _offset.top,
			u, d, l, r;
		
		if(x > _x && y > _y && x < _x + _w && y < _y + _h){
			return false;
		}
		
		if(y < _y + _h/2 && y > _y){//up
			u = true;
		}
		
		if(x < _x + _w/2 && x > _x){//left
			l = true;
		}
		
		if(l && u || x - _x < _x + _w / 10){
			_this.holder.appendTo(container);
			
			return false;
		}
		
	});
};


this.item_stop = function(e, element){
	
	if(element.data('position') != 'absolute'){
		element.css({left: '', top: '', position: '', width: '', height: ''});
	}
	
	element.insertAfter(_this.holder);
	
	if(_this.options.sorted && _this.holder.data('to')){
		_this.options.sorted(element, _this.holder.data('to'));
		_this.holder.removeData('to');
	}
	
	_this.holder.remove();
};


//init
this.refresh();


};
})(jQuery);