//

// new SortingTable( 'my_table', {

//   zebra: true,                        // Stripe the table, also on initialize

//   details: false,                     // Has details every other row

//   paginator: false,                   // Pass a paginator object

//   dont_sort_class: 'nosort',          // Class name on th's that don't sort

//   forward_sort_class: 'forward_sort', // Class applied to forward sort th's

//   reverse_sort_class: 'reverse_sort'  // Class applied to reverse sort th's

// });

//

// The above were the defaults.  The regexes in load_conversions test a cell

// begin sorted for a match, then use that conversion for all elements on that

// column.

//

// Requires mootools Class, Array, Function, Element, Element.Selectors,

// Element.Event, and you should probably get Window.DomReady if you're smart.

//



var SortingTable = new Class({



  Implements: Options,

  

  options: {

    zebra: true,

    details: false,

    paginator: false,

    dont_sort_class: 'nosort',

    forward_sort_class: 'forward_sort',

    reverse_sort_class: 'reverse_sort'

  },



  initialize: function( table, options ) {

    this.table = $(table);

    this.setOptions(options);

    

    this.tbody = this.table.getElement('tbody');

    if (this.options.zebra) {

      SortingTable.stripe_table(this.tbody.getChildren());

    }



    this.headers = this.table.getElement('thead').getElements('th');

    this.headers.each(function( header, index ) {

      if (header.hasClass( this.options.dont_sort_class )) { return }

      header.store( 'column', index )

      header.addEvent( 'mousedown', function(evt){

        this.sort_by_header( evt.target );

        if ( this.options.paginator) this.options.paginator.to_page( 1 );

      }.bind( this ) );

    }, this);



    this.load_conversions();

  },



  sort_by_header: function( header ){

    var rows = [];

    

    var before = this.tbody.getPrevious();

    this.tbody.dispose();

    

    var trs = this.tbody.getChildren();

    while ( row = trs.shift() ) {

      row = { row: row.dispose() };

      if ( this.options.details ) {

        row.detail = trs.shift().dispose();

      }

      rows.unshift( row );

    }

    

    if ( this.sort_column >= 0 &&

         this.sort_column == header.retrieve('column') ) {

      // They were pulled off in reverse

      if ( header.hasClass( this.options.reverse_sort_class ) ) {

        header.removeClass( this.options.reverse_sort_class );

        header.addClass( this.options.forward_sort_class );

      } else {

        header.removeClass( this.options.forward_sort_class );

        header.addClass( this.options.reverse_sort_class );

      }

    } else {

      this.headers.each(function(h){

        h.removeClass( this.options.forward_sort_class );

        h.removeClass( this.options.reverse_sort_class );

      }, this);

      this.sort_column = header.retrieve('column');

      if (header.retrieve('conversion_function')) {

        this.conversion_matcher = header.retrieve('conversion_matcher');

        this.conversion_function = header.retrieve('conversion_function');

      } else {

        this.conversion_function = false;

        rows.some(function(row){

          var to_match = $(row.row.getElementsByTagName('td')[this.sort_column]).get('text');

          if (to_match == '') return false;

          this.conversions.some(function(conversion){

            if (conversion.matcher.test( to_match )){

              this.conversion_matcher = conversion.matcher;

              this.conversion_function = conversion.conversion_function;

              return true;

            }

            return false;

          }, this);

          return !!(this.conversion_function);

        }, this);

        header.store('conversion_function', this.conversion_function );

        header.store('conversion_matcher', this.conversion_matcher );

      }

      header.addClass( this.options.forward_sort_class );

      rows.each(function(row){

        var compare_value = this.conversion_function( row );

        row.toString = function(){

          return compare_value;

        };

      }, this);

      rows.sort();

    }



    var index = 0;

    while ( row = rows.shift() ) {

      this.tbody.appendChild(row.row);

      if (row.detail) this.tbody.appendChild(row.detail);

      if ( this.options.zebra ) {

        row.row.className = row.row.className.replace( this.removeAltClassRe, '$1').clean();

        if (row.detail)

          row.detail.className = row.detail.className.replace( this.removeAltClassRe, '$1').clean();

        if (index % 2) {

          row.row.addClass( 'alt' ); 

          if (row.detail) row.detail.addClass( 'alt' );

        }

      }

      index++;

    }

   this.tbody.inject(before, 'after');

  },



  load_conversions: function() {

    this.conversions = $A([

      // 1.75 MB, 301 GB, 34 KB, 8 TB

      { matcher: /([0-9.]{1,8}).*([KMGT]{1})B/,

        conversion_function: function( row ) {

          var cell = $(row.row.getElementsByTagName('td')[this.sort_column]).get('text');

          cell = this.conversion_matcher.exec( cell );

          if (!cell) { return '0' }

          if (cell[2] == 'M') {

            sort_val = '1';

          } else if (cell[2] == 'G') {

            sort_val = '2';

          } else if (cell[2] == 'T') {

            sort_val = '3';

          } else {

            sort_val = '0';

          }

          var i = cell[1].indexOf('.')

          if (i == -1) {

            post = '00'

          } else {

            var dec = cell[1].split('.');

            cell[1] = dec[0];

            post = dec[1].concat('00'.substr(0,2-dec[1].length));

          }

          return sort_val.concat('00000000'.substr(0,2-cell[1].length).concat(cell[1])).concat(post);

        }

      },

      // 1 day ago, 4 days ago, 38 years ago, 1 month ago

      { matcher: /(\d{1,2}) (.{3,6}) ago/,

        conversion_function: function( row ) {

          var cell = $(row.row.getElementsByTagName('td')[this.sort_column]).get('text');

          cell = this.conversion_matcher.exec( cell );

          if (!cell) { return '0' }

          var sort_val;

          if (cell[2].indexOf('month') != -1) {

            sort_val = '1';

          } else if (cell[2].indexOf('year') != -1) {

            sort_val = '2';

          } else {

            sort_val = '0';

          }

          return sort_val.concat('00'.substr(0,2-cell[1].length).concat(cell[1]));

        }

      },

      // Currency

      { matcher: /((\d{1}\.\d{2}|\d{2}\.\d{2}|\d{3}\.\d{2}|\d{4}\.\d{2}|\d{5}\.\d{2}|\d{6}\.\d{2}))/,

        conversion_function: function( row ) {

          var cell = $(row.row.getElementsByTagName('td')[this.sort_column]).get('text');

          cell = cell.replace(/[^\d]/g, "");

          return '00000000000000000000000000000000'.substr(0,32-cell.length).concat(cell);

        }

      },

      // YYYY-MM-DD, YYYY-m-d

      { matcher: /(\d{4})-(\d{1,2})-(\d{1,2})/,

        conversion_function: function( row ) {

          var cell = $(row.row.getElementsByTagName('td')[this.sort_column]).get('text');

          cell = this.conversion_matcher.exec( cell );

          return cell[1]+

                 '00'.substr(0,2-cell[2].length).concat(cell[2])+

                 '00'.substr(0,2-cell[3].length).concat(cell[3]);

        }

      },

      // Numbers

      { matcher: /^\d+$/,

        conversion_function: function( row ) {

          var cell = $(row.row.getElementsByTagName('td')[this.sort_column]).get('text');

          return '00000000000000000000000000000000'.substr(0,32-cell.length).concat(cell);

        }

      },

      // Fallback 

      { matcher: /.*/,

        conversion_function: function( row ) {

          return $(row.row.getElementsByTagName('td')[this.sort_column]).get('text');

        }

      }

    ]);

  }



});



SortingTable.removeAltClassRe = new RegExp('(^|\\s)alt(?:\\s|$)');

SortingTable.implement({ removeAltClassRe: SortingTable.removeAltClassRe });



SortingTable.stripe_table = function ( tr_elements  ) {

  var counter = 0;

  tr_elements.each( function( tr ) {

    if ( !tr.hasClass('collapsed') ) counter++;

    tr.className = tr.className.replace( this.removeAltClassRe, '$1').clean();

    if (counter % 2) tr.addClass( 'alt' );

  });

}



