(function($) {
    $.fn.basicGrid = function(o) {
        o = o || {};
        o = $.extend({
            // Ajax
            spinner: 'Loading&#8230;',
            cache: false,
            idPrefix: 'ui-basicGrid-',
            ajaxOptions: {},
            paging: false,
            mode: 'local',

            // CSS classes
            hoverClass: 'basicGrid_rowOver',
            selectedClass: 'basicGrid_rowSelected',
            defaultClass: 'basicGrid_rowOut',
            loadingClass: 'basicGrid_loading',
            firstColClass: 'basicGrid_firstColumn',
            lastColClass: 'basicGrid_lastColumn',
            hiddenClass: 'basicGrid_hidden',
            headerClass: 'basicGrid_header',
            headerOverClass: 'basicGrid_header_over',
            headerSelectedClass: 'basicGrid_header_selected'

        }, o);
        
        var $gridObj = $(this);
        if (o.paging == true){
            $pagerObj = $('.basicGrid_pager', $gridObj);
            $pagerObj.currentPage = 1;
            $('#next', $pagerObj).each(function (){
                $(this).unbind('click').click(function (){
                    $gridObj.nextGridPage();
                });
            });
            $('#prev', $pagerObj).each(function (){
                $(this).unbind('click').click(function (){
                    $gridObj.previousGridPage();
                });
            });
        }
        
        $.fn.nextGridPage = function (){
            $pagerObj.currentPage++;
            if (typeof $pagerObj.pages[$pagerObj.currentPage] == 'undefined'){
                $pagerObj.currentPage--;
                return;
            }
            
            $($pagerObj.pages[($pagerObj.currentPage - 1)]).each(function (i, arr){
                $(arr).hide();                
            });
            
            $($pagerObj.pages[$pagerObj.currentPage]).each(function (i, arr){
                $(arr).show();
            });
            
            if (typeof $pagerObj.pages[($pagerObj.currentPage - 1)] != 'undefined'){
                $('#prev', $pagerObj).removeClass('disabled');
            }
            if (typeof $pagerObj.pages[($pagerObj.currentPage + 1)] == 'undefined'){
                $('#next', $pagerObj).addClass('disabled');
            }

            $('tr.basicGrid_rowSelected', this).each(function (){
                $(this).trigger('deselect').removeClass(o.selectedClass);
            });
            
            var pageStart = (($pagerObj.currentPage - 1) * $pagerObj.attr('page_size') + 1);
            var pageEnd = ($pagerObj.currentPage * $pagerObj.attr('page_size'));
            if (pageEnd > $pagerObj.totalRows){
                pageEnd = $pagerObj.totalRows;
            }
            $('#rowCount', $pagerObj).html('Displaying Rows ' + 
                pageStart + 
                ' - ' + 
                pageEnd + 
                ' of (' + 
                $pagerObj.totalRows + 
                ')');
        }
        
        $.fn.previousGridPage = function (){
            $pagerObj.currentPage--;
            if (typeof $pagerObj.pages[$pagerObj.currentPage] == 'undefined'){
                $pagerObj.currentPage++;
                return;
            }
            $($pagerObj.pages[($pagerObj.currentPage + 1)]).each(function (i, arr){
                $(arr).hide();                
            });
            
            $($pagerObj.pages[$pagerObj.currentPage]).each(function (i, arr){
                $(arr).show();
            });

            if (typeof $pagerObj.pages[($pagerObj.currentPage - 1)] == 'undefined'){
                $('#prev', $pagerObj).addClass('disabled');
            }
            if (typeof $pagerObj.pages[($pagerObj.currentPage + 1)] != 'undefined'){
                $('#next', $pagerObj).removeClass('disabled');
            }

            if ($('tr.basicGrid_rowSelected', this).length > 0){
                $('tr.basicGrid_rowSelected', this).removeClass(o.selectedClass);
            }

            var pageStart = (($pagerObj.currentPage - 1) * $pagerObj.attr('page_size') + 1);
            var pageEnd = ($pagerObj.currentPage * $pagerObj.attr('page_size'));
            if (pageEnd > $pagerObj.totalRows){
                pageEnd = $pagerObj.totalRows;
            }
            $('#rowCount', $pagerObj).html('Displaying Rows ' + 
                pageStart + 
                ' - ' + 
                pageEnd + 
                ' of (' + 
                $pagerObj.totalRows + 
                ')');
        }
        
        function attachRowEvents(row, $gridObj){
            $(row).mouseover(function(){
                if (this.className != o.selectedClass){
                    this.className = o.hoverClass;
                }
            }).mouseout(function(){
                if (this.className != o.selectedClass){
                    this.className = o.defaultClass;
                }
            }).click(function(){
                var $selectedRow = $gridObj.getSelected();
                if ($selectedRow.length > 0){
                    $selectedRow.removeClass(o.selectedClass);
                }
                this.className = o.selectedClass;
            });
          return row;
        }
        
        $.fn.addRow = function (row){
            var tr = $('<tr>');
            tr = attachRowEvents(tr, $(this));

            var $gridHeader = $('thead', $(this));
            jQuery.each(row.cols, function (i){
                var column = '<td col="' + i + '" class="basicGrid_column';
                var isHidden = $('th[col="' + i + '"].' + o.hiddenClass, $gridHeader);
                if (isHidden.length > 0){
                    column = column + ' ' + o.hiddenClass;
                }
                var isFirst = $('th[col="' + i + '"].' + o.firstColClass, $gridHeader);
                if (isFirst.length > 0){
                    column = column + ' ' + o.firstColClass;
                }
                var isLast = $('th[col="' + i + '"].' + o.lastColClass, $gridHeader);
                if (isLast.length > 0){
                    column = column + ' ' + o.lastColClass;
                }
                column = column + '">' + (this.text == '' ? '&nbsp;' : this.text) + '</td>';
                $(tr).append(column);
            });
            $('tbody[id!="loading"]', this).append($(tr));
          return $(tr);
        };
        
        $.fn.getSelected = function (){
            return $('tr.basicGrid_rowSelected', this);
        }
        
        $.fn.values = function (array){
            var returnValues = new Array(0);
            var $row = this;
            $(array).each(function (i, id){
                returnValues[id] = $('td[col="' + $('th[id="' + id + '"]', $row.parent().parent()).attr('col') + '"]', $row).html();
                returnValues.length++;
            });
          return returnValues;
        }
        
        $.fn.loadPaging = function (){
            var $grid = $(this);
            var $rows = $('tbody[id!="loading"] > tr', $grid);
            $pagerObj.totalRows = $rows.size();
            $pagerObj.currentPage = 1;
            $pagerObj.pages = new Array();
            var lastPage = $pagerObj.attr('page_size');
            if (lastPage > $pagerObj.totalRows){
                lastPage = $pagerObj.totalRows;
            }
            $('#rowCount', $pagerObj).html('Displaying Rows 1 - ' + lastPage + ' of (' + $pagerObj.totalRows + ')');
               
            var page = 1;
            var index = 0;
            $rows.each(function (i, arr){
                if (typeof $pagerObj.pages[page] == 'undefined'){
                    $pagerObj.pages[page] = new Array();
                }
                if (page > 1){
                    $(this).hide();
                }
                $pagerObj.pages[page].push(this);
                index++;
                if (index > ($pagerObj.attr('page_size') - 1)){
                    index = 0;
                    page++;
                }
            });
            $('#prev', $pagerObj).addClass('disabled');
            if (typeof $pagerObj.pages[2] != 'undefined'){
                $('#next', $pagerObj).removeClass('disabled');
            }else{
                $('#next', $pagerObj).addClass('disabled');
            }
        }
        
        return this.each(function() {
            if (o.paging == true){
                $(this).loadPaging();
            }
            
            $(this).find('tbody[id!="loading"] > tr').each(function (i, arr){
                attachRowEvents(this, $gridObj);
            });
        });
    };
})(jQuery);