/**
 * Gather list of tags and shows N of them with pagination
 * 
 * @author Angelo Selvini <angelo@exmachina.ch>
 * @requires ch.exmachina.bravofly.ui.Pager
 * @requires ch.exmachina.bravofly.utils
 */


if(!ch){
	var ch = {};
}
if(!ch.exmachina){
	ch.exmachina = {};
}
if(!ch.exmachina.bravofly){
	ch.exmachina.bravofly = {};
}
if(!ch.exmachina.bravofly.ui){
	ch.exmachina.bravofly.ui = {};
}

ch.exmachina.bravofly.ui.Gatherer = function(/* object */ ctorArgs){
	var t;

	this.target = t = ctorArgs["target"];
	if (!t || !t.nodeType || t.nodeType != 1)
		throw new Error("Gatherer requires target");

	// defaults
	this.name      = ctorArgs["name"]   || "gathererWidget";
	this.listening = false;
	this.render    = { show: null, hide: null };

	this.options   =
	{ hasPagerTop    : t.getAttribute("bf:hasPagerTop")    == "true" ? true : false
	, hasPagerBottom : t.getAttribute("bf:hasPagerBottom") == "true" ? true : false
	, entryRender    : t.getAttribute("bf:entryRender")    == "true" ? true : false
	, entrySelector  : t.getAttribute("bf:entrySelector")  || "p"
	};

	this.dict =
	{ next: t.getAttribute("bf:textNext") || "Next"
	, prev: t.getAttribute("bf:textPrev") || "Previous"
	, page: t.getAttribute("bf:textPage") || ""
	, of:   t.getAttribute("bf:textOf")   || "of"
	};

	this._setRender();

	this.entriesInPage = parseInt(t.getAttribute("bf:entries")) || 2;

	this.pagers    =
	{ top    : null
	, bottom : null
	};

	this.list      = [];
};

ch.exmachina.bravofly.ui.Gatherer.prototype = {

	type: "ch.exmachina.bravofly.ui.Gatherer",

	_listening: false,

	render : null,
	list   : null,
	pagers : null,
	params : null,
	target : null,
	options: null,

	currentPage: 1,
	entriesInPage: 5,

	setOptions: function(/* object */ o){
		var i = 0,
			r = 
			c = this.options,
			l = ["hasPagerTop","hasPagerBottom","entrySelector","entryRender"]
		;

		for (i=0;i<l.length;i++){
			if (o.hasOwnProperty(l[i]))
				c[ l[i] ] = o[ l[i] ];
		}

		this._setRender();
	},

	setParams: function(/* object */ p){
		if (p.entries)
			this.entriesInPage = Math.abs(p.entries) || 1;
	},

	markupBuild: function(){
		var d = this.dict,
			s = ''+
			'<div class="vg_pager">'+
				'<div class="vg_prev">'+d.prev+'</div>'+
				'<div class="vg_page">'+d.page+'<span class="vg_current">#{current}</span>'+d.of+'<span class="vg_total">#{total}</span></div>'+
				'<div class="vg_next">'+d.next+'</div>'+
			'</div>';
		return s;
	},

	// DOM
	create: function(){
		// summary: setup gathers and sons

		var i, g,
			t = this.target,
			p = this.pagers,
			o = this.options,
			l = this.list
		;
		
		// Find nodes
		l = $(t).select(o.entrySelector);

		// Remove fixed entries
		for (i=0;i<l.length;i++){
			if (l[i].hasClassName(this.getConstants().CLASS_ENTRY_FIXED))
				l.splice(i,1)
		}

		this.list = l;

		// Setup pagers
		if (o.hasPagerTop){
			g = this._createPager();
			g.setMarkup(this.markupBuild());
			g.create();
			g.setCallback( this.delegate( this, this.changePage, "top" ) );
			p.top = g;
		}
		if (o.hasPagerBottom){
			g = this._createPager();
			g.setMarkup(this.markupBuild());
			g.create();
			g.setCallback( this.delegate( this, this.changePage, "bottom" ) );
			p.bottom = g;
		}
	},

	changePage: function(/* string */ n){
		var v,
			T  = "top",
			B  = "bottom"
			nu = n == T ? B : T,
			p  = this.pagers
		;

		if (n != T && n != B) return;

		v = p[n].getValue();

		if (p[nu])
			p[nu].setValue(v);

		this.displayPage(v);
	},

	draw: function(){
		// summary: evaluate template with parameters
		var pt, pb,
			t = this.target,
			p = this.pagers,
			o = this.options
		;

		pt = this._buildPager(p.top);
		pb = this._buildPager(p.bottom);

		if (pt) t.insertBefore(pt, t.firstChild);
		if (pb) t.appendChild(pb);

		this.displayPage( 1 );
	},

	displayPage: function(p){
		// summary: hide current entries and show the page's ones
		var i, h, s,
			r = this.render,
			C = this.getConstants(),
			l = this.list,
			eip = this.entriesInPage
			min = (p-1)*eip,
			max = p*eip
		;

		for (i=0;i<l.length;i++){
			if (i>= min && i<max)
				l[i].setStyle(r.show);
			else
				l[i].setStyle(r.hide);
		}
	},

	update: function(){
		var v = this.currentPage || 1;
		this.displayPage( v );
	},

	setListening: function(/* boolean */ b){
		if (b && !this._listening)
			this._addListeners();
		else if (!b)
			this._removeListeners();
	},

	_addListeners: function(){
		this._listening = true;
	},
	_removeListeners: function(){
		this._listening = false;
	},

	_getPagination: function(){
		return	{ limit   : this.entriesInPage
				, current : this.currentPage
				, total   : Math.ceil(this.list.length/this.entriesInPage)
				};
	},

	_createPager: function(){
		var p = new ch.exmachina.bravofly.ui.Pager();
		p.setParams(this._getPagination());

		return p;
	},

	_setRender: function(){
		var o = this.options
			r = this.render
		;
		r.hide = o.entryRender ? {visibility:"hidden"}  : {display:"none"};
		r.show = o.entryRender ? {visibility:"visible"} : {display:""};
	},

	_buildPager: function(p){
		if (!p) return;

		p.draw();
		p.update();
		
		return p.getNode();
	},

	getNode: function(){
		// return: dom
		return this.dom;
	},

	getType: function(){
		return this.type;
	},

	destroy: function(){
		var p = this.pagers
		;

		this.setListening(false);

		if (p.top)
			p.top.destroy();

		if (p.bottom)
			p.bottom.destroy();

		this.list = [];
	},
	getConstants: function(){
		return window.ch.exmachina.bravofly.ui.Gatherer.getConstants();
	},

	hasParentNode: ch.exmachina.bravofly.utils.hasParentNode,
	delegate: ch.exmachina.bravofly.utils.delegate
};

ch.exmachina.bravofly.ui.Gatherer.getConstants = function() {
	var cnst =
	{ CLASS_ENTRY_FIXED: "vg_gather_fixed"
	};
	return cnst;
};

