/*

On page load, the SortableManager:

- Finds the table by its id (sortable_table).
- Parses its thead for columns with a "mochi:format" attribute.
- Parses the data out of the tbody based upon information given in the
  "mochi:format" attribute, and clones the tr elements for later re-use.
- Clones the column header th elements for use as a template when drawing
  sort arrow columns.
- Stores away a reference to the tbody, as it will be replaced on each sort.
- Performs the first sort.


On sort request:

- Sorts the data based on the given key and direction
- Creates a new tbody from the rows in the new ordering
- Replaces the column header th elements with clickable versions, adding an
   indicator (↑ or ↓) to the most recently sorted column.

*/





SortableManager = function () {
    this.thead = null;
    this.tbody = null;
    this.columns = [];
    this.rows = [];
    this.sortState = {};
    this.sortkey = 0;
};





var formatDate = 'dmy';
var formatSeparator = '/';





function setDateFormat(formato, separador){
    formatDate = formato;
    formatSeparator = separador;
}





function isoDate(fecha){
    f = fecha.split(formatSeparator);
    dia = f[formatDate.indexOf('d')];
    if (dia.length < 2) dia = '0' + dia;
    mes = f[formatDate.indexOf('m')];
    if (mes.length < 2) mes = '0' + mes;
    anyo = f[formatDate.indexOf('y')];

    return anyo+'-'+mes+'-'+dia;
}





SortableManager.prototype = {
	
	
	
    initWithTable: function (table) {

        // Ensure that it's a DOM element
        table = $(table);
        // Find the thead
        this.thead = table.getElementsByTagName('thead')[0];
        // get the mochi:format key and contents for each column header
        var cols = this.thead.getElementsByTagName('th');

        for (var i = 0; i < cols.length; i++) {
            var node = cols[i];
            var attr = null;
			var rowVal = null;
            try {
				// hay que poner en el th el tipo de datos que hay en el campo
                attr = node.getAttribute("format");
				rowVal = node.getAttribute("rowvalue");
            } catch (err) {
                // pass
            }
            var o = node.childNodes;
            this.columns.push({
                "format": attr,
				"row": rowVal,
                "element": node,
                "proto": node.cloneNode(true)
            });
        }
        // scrape the tbody for data
        this.tbody = table.getElementsByTagName('tbody')[0];
        // every row
        var rows = this.tbody.getElementsByTagName('tr');
        for (var i = 0; i < rows.length; i++) {
            // every cell
            var row = rows[i];
            var cols = row.getElementsByTagName('td');
            var rowData = [];
            for (var j = 0; j < cols.length; j++) {
                // scrape the text and build the appropriate object out of it
                var cell = cols[j];
								var obj = cell.innerHTML;
                switch (this.columns[j].format) {
                    case 'isodate':
                        obj = isoDate(obj);
                        break;
                    case 'str':
                        break;
                    case 'istr':
                        obj = obj.toLowerCase();
                        break;
                    // cases for numbers, etc. could be here
                    default:
                        break;
                }
                rowData.push(obj);
            }
            // stow away a reference to the TR and save it
            rowData.row = row.cloneNode(true);
            this.rows.push(rowData);

        }

					// do initial sort on first column
					this.drawSortedRows(this.sortkey, true, false);
    },

	/***********************
	* Acción asiñada al clickar una de las cabeceras de las
	* con nuevas cabeceras con flechas para ordenar
	************************/	


    onSortClick: function (name) {

      	 var order = this.sortState[name];
            if (order == null) {
                order = true;
            } else if (name == this.sortkey) {
                order = !order;
            }
            this.drawSortedRows(name, order, true);
    },



	/***********************
	* Remplaza las cabeceras de la tabla
	* con nuevas cabeceras con flechas para ordenar
	************************/	
	

   drawSortedRows: function (key, forward, clicked, randomize) {

	   this.sortkey = key;
		var ordencrit = (forward)?"A":"D";
		

		var newArray = [];
		for(var i=0; i<this.rows.length; i++){
			var newObj = {value:this.rows[i][key],ref:this.rows[i]};
			newArray.push(newObj);
		}


		if(randomize){
				newArray.sort(function(){return (Math.round(Math.random())-0.5);});
		}else{
			newArray.ordenar('value',ordencrit);
		}

		
		this.rows = newArray.pluck("ref");

    // save it so we can flip next time
    this.sortState[key] = forward;

		var newBody =DOM.Builder.create('tbody',null, this.rows.pluck("row"));


		// remplazamos los estilos
		var cnds = newBody.childNodes;

		for(var u = 0; u<cnds.length; u++){
			Element.removeClassName(cnds[u], 'par');
			Element.removeClassName(cnds[u], 'impar');


			var styl = (u%2 == 0)?'par':'impar';

			Element.addClassName(cnds[u],styl);
		}

        // swap in the new tbody
		this.tbody = DOM.replaceElement(this.tbody,newBody);

		if(randomize)return;
		this.replaceheaders(key);
		
	},
	
	
	/***********************
	* Remplaza las cabeceras de la tabla
	* con nuevas cabeceras con flechas para ordenar
	*
	************************/	
	
	
	
	replaceheaders:function(key){
 			
 			for (var i = 0; i < this.columns.length; i++) {
            var col = this.columns[i];
            var node = col.proto.cloneNode(true);

            // remove the existing events to minimize IE leaks
            col.element.onclick = null;
            col.element.onmousedown = null;
            col.element.onmouseover = null;
            col.element.onmouseout = null;


            // set new events for the new node
            node.onclick = this.onSortClick.bind(this,i);

            node.onmousedown = function (ev) {
						    if (ev && ev.preventDefault) {
						        ev.preventDefault();
						        ev.stopPropagation();
						    } else if (typeof(event) != 'undefined') {
						        event.cancelBubble = false;
						        event.returnValue = false;
						    }
						};
            node.onmouseover = function () {
							Element.addClassName(node, "over");
						};
            node.onmouseout = function () {
							Element.removeClassName(node, "over");
						};
            
            // if this is the sorted column
            if (key == i) {
                // \u2193 is down arrow, \u2191 is up arrow
                // forward sorts mean the rows get bigger going down
                var arrow = (forward ? "\u2193" : "\u2191");
                // add the character to the column header

				var newnode = DOM.Builder.create('span',null, ['string']);
				Element.update(newnode,arrow);
				node.appendChild(newnode);
                if (clicked) {
                    node.onmouseover();
                }
            }
      // swap in the new th
			try{
				col.element = DOM.replaceElement(col.element, node);
			}catch(e){
			}
        }		
		
	},
	
	
	
	
	/***********************
	* Ordena la tabla aleatoriamente
	*
	************************/	
	
	randomize:function(table,columnIndex){

				this.sortkey = columnIndex;
        table = $(table);
        this.thead = table.getElementsByTagName('thead')[0];
        var cols = this.thead.getElementsByTagName('th');
        
        // buscamos los valores
        
        for (var i = 0; i < cols.length; i++) {
            var node = cols[i];
            var attr = null;
						var rowVal = null;
            try {
                attr = node.getAttribute("format");
								rowVal = node.getAttribute("rowvalue");
            } catch (err) {}
            var o = node.childNodes;
            this.columns.push({
                "format": attr,
								"row": rowVal,
                "element": node,
                "proto": node.cloneNode(true)
            });
        }
        
        this.tbody = table.getElementsByTagName('tbody')[0];
        var rows = this.tbody.getElementsByTagName('tr');
        for (var i = 0; i < rows.length; i++) {

            var row = rows[i];
            var cols = row.getElementsByTagName('td');
            var rowData = [];
            for (var j = 0; j < cols.length; j++) {
                var cell = cols[j];
								var obj = cell.innerHTML;
							
				        switch (this.columns[j].format) {
				            case 'isodate':
				                obj = isoDate(obj);
				                break;
				            case 'str':
				                break;
				            case 'istr':
				                obj = obj.toLowerCase();
				                break;
				            // cases for numbers, etc. could be here
				            default:
				                break;
				        }
       
       					rowData.push(obj);
        		}
		        rowData.row = row.cloneNode(true);
		        this.rows.push(rowData);
        }

					this.drawSortedRows(this.sortkey, true, false,true);
		}
	
	
};



Array.prototype.ordenar=function() {
    var param = "return ", dato, orden;
    for (var i = 0; i < arguments.length; i += 2) {
        dato = arguments[i];
        orden = (arguments[i+1] == "D")? 1 : -1;
        param += "(x." + dato + " < y." + dato + ")?" + orden + ":";
        param += "(x." + dato + " > y." + dato + ")?" + (0 - orden) + ":";

    }
    param += "0;";
			this.sort(new Function("x","y",param));
}