/*
 * jGrid for jQuery
 * Copyright (c) 2009 Paul Amelin
 */

(function($){
    $.fn.extend({
        jTable: function(options, clickCallback, callback) {
            var resizerProxy = '<div class="jResizer"></div>';
            var draggerProxy = '<div class="jDragger"></div>';
            var dragProxy = '<div id="jDrag"></div>';
            var defaults = {
                sortable: true,
                resizable : true,
                draggable : true,
                hideShow : true,
                scroll: true
            }

            options =  $.extend(defaults, options);

            return this.each(function() {
                var positionLeft = $(this).position().left;
                var jTable = $(this);
                var action = 'none';
                var dragFrom = null;
                var dragTo = null;
                var drag = null;

                if(options.hideShow){
                    $("#hideShowColumns input").bind('click', function(e){
                        var col = $("th[title='" + $(this).val() + "']", jTable)[0];
                        var n = $('th', jTable).index(col);
                        $('tr', jTable).each(function () {
                            $('td:eq(' + n + ')', this).toggle();
                        });
                        $(col).toggle();
                        if (callback){
                            callback(e, $(this));
                        }                        
                    });
                }

                $('th', this).bind('mousemove', function (e){
                    if (action == 'none'){
                        $(this).removeClass('jOver jResize');                        
                        if (e.clientX > $(this).offset().left + $(this).outerWidth(true) - 7
                                && e.clientX < $(this).offset().left + $(this).outerWidth(true)){
                            $(this).addClass('jResize');
                        } else if((options.sortable || options.draggable) && e.clientX <= $(this).offset().left + $(this).outerWidth(true) - 7) {
                            $(this).addClass('jOver');
                        }
                    } else if (action == 'dragging' && options.draggable){
                        if ($(this).position().left != $(dragFrom).position().left){
                            $(drag).show();
                            $(drag).css('left', $(this).position().left + $(jTable).scrollLeft());
                            $(drag).css('background-position', 'top');
                            if ($(this).position().left > $(dragFrom).position().left){
                                $(drag).css('left', $(this).position().left + $(this).outerWidth(true) - 6 + $(jTable).scrollLeft());
                                $(drag).css('background-position', 'bottom');
                            }
                            dragTo = $(this);
                        } else {
                            dragTo = null;
                            $(drag).hide();
                        }
                    }
                });
                $('th', this).bind('mouseout', function (){
                    $('.jDrag', this).remove();
                    $(this).removeClass('jOver jResize jBefore jAfter');
                });


                $('th',this).bind('dragstart', function(e){
                    $('div.jResizer', jTable).remove();
                    //if ($(this).hasClass('jResize')){
                    if (options.resizable && e.clientX > $(this).offset().left + $(this).outerWidth(true) - 7
                            && e.clientX < $(this).offset().left + $(this).outerWidth(true) + 1){                        
                        action = 'resizing';
                        $('body').css({cursor:'col-resize'});
                        return $(resizerProxy).prependTo(jTable);
                    }
                    if (options.draggable && e.clientX <= $(this).offset().left + $(this).outerWidth(true) - 7){
                        dragFrom = $(this);
                        action = 'dragging';
                        $('body').css({cursor:'move'});
                        var dragger = $(draggerProxy).prependTo(jTable);
                        drag = $(dragProxy).prependTo(jTable);
                        $(dragger).html($(this).html());
                        if ($(dragger).width() < $(this).width()){
                            $(dragger).css({width:$(this).width()});
                        }
                        $(dragger).css('opacity',.85);
                        return dragger;
                    }
                    return false;
                })
                .bind('drag', function(e){
                    if (action == 'resizing' && options.resizable){
                        //var x =  e.offsetX - positionLeft + $(this).outerWidth() + $(jTable).scrollLeft();
                        var x =  e.offsetX - $(jTable).offset().left + $(this).outerWidth() + $(jTable).scrollLeft();
                        $(e.dragProxy).css({left: x});
                    }
                    if (action == 'dragging' && options.draggable){
                        var x =  e.offsetX - $(jTable).offset().left + 10 + $(jTable).scrollLeft();
                        var y =  e.pageY - $(jTable).offset().top + 20;
                        $(e.dragProxy).css({left: x, top: y});
                    }
                })
                .bind('dragend', function(e){
                    if (action == 'resizing' && options.resizable){
                        var w = $(e.dragProxy).position().left - $(this).position().left + $(this).width() - $(this).outerWidth(true);
                        $(this).width(w);
                        if (callback){
                            callback(e, $(this));
                        }
                    }
                    if (action == 'dragging' && options.draggable){
                        if (drag != null){
                            $(drag).remove();
                            drag = null;
                        }
                        if (dragTo != null){
                            $(dragTo).removeClass('jOver jResize jBefore jAfter');
                
                            var cdrag = $('thead th',jTable).index(this);
                            var cdrop = $('thead th',jTable).index(dragTo);
								if (cdrag>cdrop)
									$(dragTo).before($(this));
								else
									$(dragTo).after($(this));
                            $('tbody tr', jTable).each(function(){
								if (cdrag>cdrop)
									$('td:eq('+cdrop+')',this).before($('td:eq('+cdrag+')',this));
								else
									$('td:eq('+cdrop+')',this).after($('td:eq('+cdrag+')',this));
                            });
                            dragTo = null;
                            if (callback){
                                callback(e, $(this));
                            }
                        }
                    }
                    $(e.dragProxy).remove();
                    //$(this).removeClass('jOver').removeClass('jResize');
                    $('body').css({cursor:'auto'});
                    action = 'none';
                });


                if (options.sortable){
                    $('th', this).bind('click', function(){
                        if (action == 'none' && $(this).hasClass('jOver') && !$(this).hasClass('jNoOrder')){
                            var sortOrder = "ASC";
                            if ($(this).hasClass('asc')) sortOrder = "DESC";
                            if(clickCallback) clickCallback($(this), sortOrder);
                            else{                               
                                $('th', jTable).removeClass('asc').removeClass('desc');
                                $(this).addClass(sortOrder.toLowerCase());
                            }
                        }
                    });
                }

                if (options.scroll){
                    var previousX = 0;
                    $('tbody', jTable).mouseover(function(){
                        $('body').css('cursor', 'move');
                    }).mouseout(function(){
                        $('body').css('cursor', 'auto');
                    }).mousewheel(function(e, delta){
                        var offset = jTable.scrollLeft();
                        jTable.scrollLeft(offset - delta * 30);
                        return false;
                    }).bind('dragstart', function() {
                        previousX = 0;
                    }).bind('drag', {distance:5}, function(e){
                        var offset = jTable.scrollLeft();
                        var x =  e.offsetX - jTable.position().left + offset;
                        jTable.scrollLeft(offset - x-previousX);
                        previousX = x;
                    });
                }



            });

        }
    });
})(jQuery);
