// Copyright (c) 2007 Gregory SCHURGAST (http://www.negko.com, http://prototools.negko.com)
//
// Permission is hereby granted, free of charge, to any person obtaining
// a copy of this software and associated documentation files (the
// "Software"), to deal in the Software without restriction, including
// without limitation the rights to use, copy, modify, merge, publish,
// distribute, sublicense, and/or sell copies of the Software, and to
// permit persons to whom the Software is furnished to do so, subject to
// the following conditions:
//
// The above copyright notice and this permission notice shall be
// included in all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
//
// VERSION 1.2

/********** Modificaciones del original ************/

// Comentados algunos bloques que no queremos utilizar
// Modificados ids de tds para hacer más fácil su uso en css (con index de columna y no nombre de columna)
// Añadido unvisibleColumn
// Añadida paginación
// Añadida ordenación para divisas
// Añadida ordenación para categorías

// -- Eliminar para dejar la clase lista para cualquier uso
// GEvent en Observer de "td" mapa (línea 172)
// Formateos varios en los valores finales (dejar 294 y eliminar switch de linea 309)

/********** Modificaciones del original ************/

var TableOrderer = Class.create();
//defining the rest of the class implementation

TableOrderer.prototype = {
	initialize: function(element,options) {
		this.element = element;
		this.options = options;

		this.options = Object.extend({
			data: false, 				// array of data
			url: false, 				// url to a JSON application containing the data
			allowMultiselect : true, 	// don't work yet
			unsortedColumn : [],		// array of column you don't want to sort
			unvisibleColumn : [],		// array of columns not visible
			dateFormat : 'd', 			// d|m ; d => dd/mm/yyyy; m => mm/dd/yyyy
			filter : false,				// show Filter Option. false | 'top' | 'bottom'
			paginate : 10				// Number of items by table

		}, options || {});

		this.pages = 0;
		this.pagenumber = 1;

		this.container = $(element);
		this.orderField = false;
		this.order = 'asc';
		this.thClickbfx = this.thClick.bindAsEventListener(this);
		this.tdClickbfx = this.tdClick.bindAsEventListener(this);
		this.aClickbfx = this.aClick.bindAsEventListener(this);
		this.thOverbfx = this.thOver.bindAsEventListener(this);
		this.thOutbfx = this.thOut.bindAsEventListener(this);
		this.setData();
	},

	perform : function(){
		this.pages = Math.ceil(this.data.length/this.options.paginate);
		this.setColumnsName()
		this.createTable();
	},

	getData : function(url){
		new Ajax.Request(
			url,
			{
			parameters :
			{
				offset : offset,
				limit  : limit
			},
			onLoading : function(){ $(this.element).update('Loading...'); }.bind(this),
			onSuccess: function(transport) {
				this.data = transport.responseJSON;
				this.perform();
			}.bind(this),
			onFailure : function(){ alert('invalid data'); }
		});
	},

	viewPage : function()
	{
		var line = 1;
		var offset = (this.pagenumber-1)*this.options.paginate;

		var tempdata = this.data;
		if (this.order == 'desc'){tempdata = this.data.reverse(false);}

		for(var index = offset; index < offset+this.options.paginate && index < this.data.length; index++){
			this.table.insert({ bottom: this.createRow(tempdata[index],index) });
			line = (line == 1) ?  2 : 1;
		}

		this.table.insert({ bottom: this.createPaginate()});
	},

	setData : function(){
		if (!this.options.data && !this.options.url){alert('no data');}
		this.data = this.options.data ? this.options.data : false;
		this.data ? this.perform() : this.getData(this.options.url);
	},

	orderRule : function (s){
		var dateRE = /^(\d{2})[\/\- ](\d{2})[\/\- ](\d{4}|\d{2})/;
		var exp=new RegExp(dateRE);
		//match date
		if ( exp.test(s) ){
			s = this.options.dateFormat == 'd' ? s.replace(dateRE,"$3$2$1") : s.replace(dateRE,"$3$1$2");
		}
		var dateRE = /^[£$€][1-9][0-9]{0,2}(.[0-9]{0,2})*(\,[0-9]{2})?$/;
		var dateRE1 = /^[1-9][0-9]{0,2}(.[0-9]{0,2})*(\,[0-9]{2})?[€]$/;
		var exp=new RegExp(dateRE);
		var exp1=new RegExp(dateRE1);
		//match currency
		if ( exp.test(s) ){
			s = parseFloat(s.replace(/[£$€.]/g,'').replace(/,/g,'.'));
    		if (isNaN(s)) s = 0;
		}
		else if( exp1.test(s) ){
			s = parseFloat(s.replace(/[€.]/g,'').replace(/,/g,'.'));
    		if (isNaN(s)) s = 0;
		}
		//category (Modificar según la importancia que quieran)
		if(Object.isString(s)){
			var t = s.substr(0,1);
			var v = s.substr(1,1);

			if(v == "e" && parseInt(t, 10) > 0 && parseInt(t, 10) <= 5){ // Damos más importancia a los hoteles (1e = 101 > a5 = 100)
				s = 100+parseInt(t, 10);
			}
			else if(t == "a" && parseInt(v, 10) > 0 && parseInt(v, 10) <= 5){
				s = 95+parseInt(v, 10);
			}
			else if(s == 'ho' || s == 'ah' || s == 'ro' || s == 'ht' || s == 'ap' || s == 'ca' || s == 'ag'){
				s = 0;
			}
		}

		return s;
	},

	defineOrderField : function(e){
		this.previousOrderField = this.orderField;
		this.orderField = Event.element(e).id.replace(this.table.id+'-','');
	},

	/* if you click on a header for the first time order is ascending else it switches between ascending and descending */
	defineOrder : function(){
		if (this.previousOrderField == this.orderField){ this.order = this.order == 'desc' ? 'asc' : 'desc'; }
		else { this.order = 'asc'; }
	},

	orderData : function(order){
		var order = order;

		this.data = this.data.sortBy(function(s){
			v = Object.values(s)[Object.keys(s).indexOf(order)];
			return this.orderRule(v);
		}.bind(this));

	},

	tdClick : function(e){
		var el = $(Event.element(e));
		GEvent.trigger(markers[el.up('tr').id.substr(17)], 'click');
	},

	aClick : function(e){
		var el = $(Event.element(e));
		if(el.id == 'firstpage') this.pagenumber = 1;
		else if(el.id == 'lastpage') this.pagenumber = this.pages;
		else if(el.id == 'nextpage') this.pagenumber = this.pagenumber+1 <= this.pages ? this.pagenumber+1 : this.pages;
		else if(el.id == 'prevpage') this.pagenumber = this.pagenumber-1 > 1 ? this.pagenumber-1 : 1;
		else this.pagenumber = el.id;

		this.createTable();
	},

	thClick : function(e){
		this.pagenumber = 1;
		this.defineOrderField(e);
		this.defineOrder();
		this.orderData(this.orderField);
		this.createTable();
	},

	thOver : function(e){
		Event.element(e).addClassName('on');
	},
	thOut : function(e){
		Event.element(e).removeClassName('on');
	},

	trClick : function(e){

		this.setSelected(Event.findElement(e,'tr'));
		items = Event.findElement(e,'tr').descendants().pluck('innerHTML');
		var json = '{';
		var keys  = Object.keys(this.model);
		items.each(function(i,index){
			json += index == 0 ? '' : ', ';
			json += '"'+keys[index]+'": "'+i+'"';
		});
		json += '}';
		selected = json.evalJSON();
	},

	trOver : function(e){
		Event.findElement(e,'tr').addClassName('on');
	},

	trOut : function(e){
		Event.findElement(e,'tr').removeClassName('on');
	},

	setSelected : function(elt){
		/*
		if (this.options.allowMultiselect){
			elt.hasClassName('selected') ? elt.removeClassName('selected') : elt.addClassName('selected');
		}
		else{
		}
		*/
	},

	/* Observers */
	addObserver : function(){
		tid = this.table.id;
		$$('#'+tid+' th')
			.invoke('observe','click',this.thClickbfx)
			.invoke('observe','mouseover',this.thOverbfx)
			.invoke('observe','mouseout',this.thOutbfx);

		$$('#'+tid+' td.data-grid-hotels-column-0').invoke('observe','click',this.tdClickbfx);
		$$('#'+tid+' td.paginate a').invoke('observe','click',this.aClickbfx);
		$$('#'+tid+' td.paginate img').invoke('observe','click',this.aClickbfx);

		$$('#'+tid+' tr.data')
			//.invoke('observe','click',this.trClick.bindAsEventListener(this))
			.invoke('observe','mouseover',this.trOver.bindAsEventListener(this))
			.invoke('observe','mouseout',this.trOut.bindAsEventListener(this));

		if (this.options.filter){
			var filterDatakbfx = this.filterData.bindAsEventListener(this);
			Event.observe(tid+'-filter-column','change',filterDatakbfx);
			Event.observe(tid+'-filter-data','keyup',filterDatakbfx);
		}
	},

	filterData : function(e){
		var tid = this.table.id;
			$$('#'+tid+' td.' + tid+'-column-'+$F(tid + '-filter-column')).each(function(i){
				i.ancestors()[1].show();
				if(!i.innerHTML.toUpperCase().include($F(tid + '-filter-data').toUpperCase())){
					i.ancestors()[1].hide();
				}
			});
	},

	makeColumnUnsortable : function(columnId){
		columnId = this.table.id + '-' + columnId;
		$(columnId).setStyle({'backgroundImage' : 'none'});
		Event.stopObserving($(columnId),'click', this.thClickbfx);
		Event.stopObserving($(columnId),'mouseover', this.thOverbfx);
		Event.stopObserving($(columnId),'mouseout', this.thOutbfx);
	},

	makeUnsort : function(){
		this.options.unsortedColumn.each(function(i){
			if($(this.table.id + '-' + i)){ this.makeColumnUnsortable(i);}
		}.bind(this));
	},

	createTable : function(){
		this.container.update();
		this.container.insert({ top: '<table cellspacing="0" cellpadding="0" id="data-grid-'+this.element+'" class="prototools-table"></table>' });
		this.table = $('data-grid-'+this.element);
		this.createRows();
		this.addObserver();
		this.makeUnsort();
	},

	createRow : function(obj,index){
		line = index%2;
		//var row = '<tr class="data line'+line+'" id="'+this.table.id+'-'+index+'">\n';
		var row = '<tr class="data line'+line+'" id="'+this.table.id+'-'+parseInt(obj.index, 10)+'">\n';
		var obj = obj;
		var values = Object.values(obj);
		this.tableColumnsName.each(function(s,index){

			var finalvalue = values[index];

			if(this.options.unvisibleColumn.indexOf(s) == -1)
			{
				switch(index)
				{
					case 0:// Map
						finalvalue = ''; // css data-grid-hotels-column-0
					break;
					case 1:// Name
						finalvalue = '<a href="'+obj.url+'">'+values[index]+'</a>';
					break;
					case 2:// Category
							finalvalue = '<img src="/img/'+values[index]+'.png">';
					break;
					case 3:// Rating
						finalvalue = values[index] == -1 ? strnoavail : values[index].toFixed(1);
					break;
					case 4:// Board
						finalvalue = values[index];
					default:// Prices
						finalvalue = values[index] ==  0 ? strnoavail : values[index];
					break;
				}

			  	row += '\t<td class="'+this.table.id+'-column-'+index+'">'+finalvalue+'</td>\n';
			 }
		}.bind(this));
		row += '\n</tr>';
		return row;
	},

	createFirstRow : function(obj){
		row = '<tr>\n';
		this.tableColumnsName.each(function(i, index){
			if(this.options.unvisibleColumn.indexOf(i) == -1)
			{
				row += '\t<th class="th'+index+'" id="'+this.table.id+'-'+i+'">'+i.replace('_',' ').capitalize()+'</th>';
			}
		}.bind(this));
		row += '\n</tr>';
		this.model = Object.clone(obj);
		return row;
	},

	setColumnsName : function(){
		this.tableColumnsName = Object.keys(this.data[0]);
	},

	createFilter : function(){
		var option = '';
		this.tableColumnsName.each(function(i){
			option += '\t<option value="'+i+'">'+i.replace('_',' ').capitalize()+'</option>\n';
		});
		$(this.table.id+'-options').insert({bottom : 'Filter Column :'})
		.insert({bottom : '<select id="'+this.table.id+'-filter-column">'+option+'</select>'})
		.insert({bottom : Element('input',{'id' : this.table.id+'-filter-data'})});
	},

	createPaginate : function(){
		row = '';
		if(this.pages > 1){
			row = '<tr><td colspan="'+(this.tableColumnsName.length-this.options.unvisibleColumn.length)+'" class="paginate">';
			//Prev page
			if(this.pagenumber!=1)row +='<img src="/img/btn-inicio.jpg" align="absmiddle" id="firstpage">';
			//First page
			if(this.pagenumber!=1)row +='<img src="/img/btn-prev.jpg" align="absmiddle" id="prevpage">\n';

			//Page i
			for(var i=1; i<=this.pages; i++ ){
				i == this.pagenumber ? row += '\t'+i : row += '\t<a href="#" onclick="return false;" id="'+i+'">'+i+'</a>';
			}

			//Next page
			if(this.pagenumber!=this.pages)row += '<img src="/img/btn-mas.jpg" align="absmiddle" id="nextpage">';
			//Last page
			if(this.pagenumber!=this.pages)row += '<img src="/img/btn-fin.jpg" align="absmiddle" id="lastpage">\n</td></tr>';
		}
		return row;
	}
	,
	createRows : function(){

		// Paginación, comento *(1)
		this.viewPage();

		/*(1)
		this.data.each(function(i,index){
			this.table.insert({ bottom: this.createRow(i,index) });
			line = (line == 1) ?  2 : 1;
		}.bind(this));
		*/
		this.table.insert({ top: this.createFirstRow() });

		if (this.options.filter || this.options.paginate) {
			filterDiv = new Element('div' , {'id' : this.table.id+'-options' , 'class':'prototools-options'});
			if (this.options.filter) {
				if (this.options.filter == 'top'){
					this.table.insert({ before :  filterDiv});
					filterDiv.setStyle('border-bottom : none;');
				}
				else {
					this.table.insert({ after :  filterDiv});
					filterDiv.setStyle('border-top : none;');
				}
				this.createFilter();
			}
		}
		if (this.orderField){ $( this.table.id+'-'+this.orderField).addClassName(this.order); }
	}
};
