if (typeof(JSON) == 'undefined') JSON = {};



JSON.Gallery = Class.create();
Object.extend(JSON.Gallery.prototype, Event.Publisher);
Object.extend(JSON.Gallery.prototype, Event.Listener);
Object.extend(JSON.Gallery.prototype, {
	
	sections: null,
	currentSection: null,
	
	initialize: function(viewOptionsContainer) {
		this.sections = new Hash();
	},
	
	addSection: function(section) {
		this.sections.set(section.name, section);
		this.initializeSection(section);
	},
	
	load: function(section, page) {
		if (section == this.currentSection) {
			return;
		}
		this.dispatchEvent('activating', section);

		if (this.currentSection) {
			this.dispatchEvent('deactivating', this.currentSection);
			this.currentSection.hide();
		}
		section.load(page);
		
		this.currentSection = section;
	},

	initializeSection: function(section) {
		this.listenForEvent(this, 'activatingByName', false, function(evt) {
			var section = evt.event_data.data;
			this.activateByName(name);
		});

		this.listenForEvent(this, 'activating', false, function(evt) {
			var section = evt.event_data.data;
			this.indicateActive(section.trigger);
		});

		this.listenForEvent(this, 'deactivating', false, function(evt) {
			var section = evt.event_data.data;
			this.indicateInactive(section.trigger);
		});

		Event.observe(section.trigger, 'click', function() {
			//indicate active as early as possible so it doesn't feel slow
			this.indicateActive(section.trigger);
			this.load(section);
		}.bind(this));
	},

	activateByName: function(evt) {
		var clickedLink = evt.findElement('a');
		var section = clickedLink.href.replace(/.*#/, '').toQueryParams();
		section = section.section;
		
		this.load(this.sections.get(section));
	},

	indicateActive: function(trigger) {
		trigger.addClassName('active');
	},

	indicateInactive: function(trigger) {
		trigger.removeClassName('active');
	}

});



JSON.Navigator = Class.create();
Object.extend(JSON.Navigator.prototype, Event.Listener);
Object.extend(JSON.Navigator.prototype, { 

	container: null,
	section: null,
	
	previousControl: null,
	nextControl: null,

	currentPageControl: null,
	pageControls: null,

	initialize: function(section) {
		
		this.section = section;
		
		this.container = document.createElement('div');
		this.container.appendChild(this.createPreviousControl());
		this.container.appendChild(this.createPageControls());
		this.container.appendChild(this.createNextControl());
		
		this.listenForEvent(section, 'afterShow', false, function() {
			this.indicateCurrentPage();
		}.bind(this));
		
	},
	
	createPreviousControl: function() {
		this.previousControl = document.createElement('a');
		this.previousControl.setAttribute('href', '#');
		Element.addClassName(this.previousControl, 'previous');
		this.previousControl.innerHTML = 'Pr&eacute;c&eacute;dent';
		Event.observe(this.previousControl, 'click', function(evt) {
	
			if(0 == this.section.currentPageIndex) {
				Event.stop(evt);
				return;
			}
	
			this.section.previousPage();

		}.bindAsEventListener(this));
		return this.previousControl;
	},
	
	createNextControl: function() {
		this.nextControl = document.createElement('a');
		this.nextControl.setAttribute('href', '#');
		Element.addClassName(this.nextControl, 'next');
		this.nextControl.innerHTML = 'Suivant';
		Event.observe(this.nextControl, 'click', function(evt) {
	
			if(this.section.pages.length - 1 == this.section.currentPageIndex) {
				Event.stop(evt);
				return;
			}
	
			this.section.nextPage();
		}.bindAsEventListener(this));
		return this.nextControl;
	},
	
	createPageControls: function() {
		
		this.pageControls = [];
		
		var pages = document.createElement('div');
		Element.addClassName(pages, 'pages');
		
		for (var i = 0; i < this.section.pages.length; i++) {
			var pageLink = document.createElement('a');
			pageLink.setAttribute('href', '#section=' + this.section.name + "&page=" + (i+1));
			pageLink.innerHTML = i + 1;
			
			Event.observe(pageLink, 'click', function(evt, section, index) {
				section.showPage(index);
			}.bindAsEventListener(this, this.section, i));
			
			if (i === 0) {
				this.currentPageControl = pageLink;
			} else if ((i + 1) == this.section.pages.length) {
				Element.addClassName(pageLink, 'last');
			}
			this.pageControls.push(pageLink);
			pages.appendChild(pageLink);
		}
		
		return pages;
	},
	
	indicateCurrentPage: function() {
		
		var pageIndex = this.section.currentPageIndex;
		
		if (0 == pageIndex) {
			Element.addClassName(this.previousControl, 'disabled');
		} else {
			Element.removeClassName(this.previousControl, 'disabled');
		}
		
		if ((this.section.pages.length - 1) == pageIndex) {
			Element.addClassName(this.nextControl, 'disabled');
		} else {
			Element.removeClassName(this.nextControl, 'disabled');
		}
		
		if (this.currentPageControl) {
			Element.removeClassName(this.currentPageControl, 'active');
		}
		
		this.currentPageControl = this.pageControls[pageIndex];
		Element.addClassName(this.currentPageControl, 'active');

		var prevPage = '';
		if (0 != pageIndex) {
			prevPage = "&page=" + pageIndex;
		}
		
		var nextPage = '';
		if (pageIndex < this.section.pages.length -1) {
			nextPage = "&page=" + (pageIndex + 2);
		}
	
		//need ot ensure the location bar changes before we alter the link's href
		setTimeout(function() {
			this.previousControl.setAttribute('href', '#section=' + this.section.name + prevPage);
			this.nextControl.setAttribute('href', '#section=' + this.section.name + nextPage);
		}.bind(this), 0);
		
	},
	
	hide: function() {
		this.container.hide();
	},
	
	show: function() {
		Element.show(this.container);
	}

});



JSON.Section = Class.create();
Object.extend(JSON.Section.prototype, Event.Publisher);
Object.extend(JSON.Section.prototype, {
	
	name: null,
	wrapper: null,
	container: null,
	feedUrl: null,
	
	topControls: null,
	bottomControls: null,

	loading: false,
	
	items: null,
	
	pages: [],
	cache: {},
	currentPageIndex: 0,
	
	locked: false,
	
	initialize: function(name, mainTrigger, feedUrl, options) {
		this.name = name;
		
		if (!this.wrapper) return;
		var div = new Element('div');
		this.wrapper.appendChild(div);
		this.container = div;

		this.trigger = $(mainTrigger);

		this.feedUrl = feedUrl;
		this.items = [];
		this.options = options || {};
		if (!this.options.renderList) this.options.renderList = {};
	}, 
	
	load: function(initialPage) {
		if (this.loading) return;
		
		if (this.items.length > 0) {
		   this.show(initialPage);
		   return;
		} else if (this.items.length == 0) {
			this.loading = true;
			Element.addClassName(this.container, 'loading');
	
			new Ajax.Request(this.feedUrl, {
				method: 'GET',
				evalJS: false,
				evalJSON: false,
				evalScripts: false,
				onSuccess: function(request) {
					this._populate(eval('(' + request.responseText + ')'));
					this.afterPopulate();
					this.loading = false;
					Element.removeClassName(this.container, 'loading');
					this.show(initialPage);
				}.bind(this),
		
				onException: function(r,e) {
					throw(e); //TODO probably ignore this once live
				}
			});
		}
	},
	
	_populate: function(data) {
		for (var i=0; i<data.length; i++) {
			this.items.push(data[i]);
		}
	},
	
	afterPopulate: function() {},
	
	clear: function() {
		this.container.addClassName('loading');
		this.container.innerHTML = '';
		this.pages = [];
		this.topControls = null;
		this.bottomControls = null;
	},
	
	render: function() {
		if (!this.getCache()) {
			this.dispatchEvent('beforeRender', this);
			this.pages = JSON.ListRenderStrategy.render(this.items, this.options.renderList);
			this.dispatchEvent('afterRender', this);
		}

		if (this.currentPageIndex >= this.pages.length) this.currentPageIndex = 0;
		this.container.innerHTML = '';

		this.drawControls();
	
		if (this.topControls) {
			this.container.appendChild(this.topControls);
		}

		for (var i=0; i<this.pages.length; i++) {
		   this.pages[i].style.display = 'none';
		   this.container.appendChild(this.pages[i]); 
		}

		if (this.bottomControls) {
			this.container.appendChild(this.bottomControls);
		}

	},
	
	drawControls: function() {
		if (this.pages.length > 1) {
			this.topControls = new JSON.Navigator(this).container;
			Element.addClassName(this.topControls, 'pagination top');
			this.bottomControls = new JSON.Navigator(this).container;
			Element.addClassName(this.bottomControls, 'pagination bottom');
		}
	},
	
	show: function(page) {
		if (this.loading) return;
		
		this.render();
		this.container.show();
		this.showPage(page || 0, true);
	},
	
	hide: function() {
		this.dispatchEvent('beforeHide', this);
		this.container.hide();
		this.dispatchEvent('afterHide', this);
	},
	
	nextPage: function() {
		
		if ((this.pages.length - 1) == this.currentPageIndex) {
			return;
		}
		
		this.showPage(this.currentPageIndex + 1);
	},
	
	previousPage: function() {
		
		if(0 == this.currentPageIndex) {
			return;
		}
		
		this.showPage(this.currentPageIndex - 1);
	},
	
	getCache: function() {
		return this.cache[JSON.currentViewOption];
	},
	
	showPage: function(index, force) {
		if(!force && (this.locked || index == this.currentPageIndex)) {
			return;
		}

		this.track();

		this.locked = true;

		this.dispatchEvent('beforeShow', this);

		if (typeof(this.options.beforeShow) == 'function') {
			this.options.beforeShow(this, this.pages[this.currentPageIndex], this.pages[index], force);
		}
		
		Element.hide(this.pages[this.currentPageIndex]);
		Element.show(this.pages[index]);
		if (this.topControls) Element.show(this.topControls);
		if (this.bottomControls) Element.show(this.bottomControls);

		this.currentPageIndex = index;
		this.locked = false;

		this.dispatchEvent('afterShow', this);

		if (typeof(this.options.afterShow) == 'function') {
			this.options.afterShow(this, this.pages[this.currentPageIndex], this.pages[index], force);
		}
	},

	track: function() {
		var options = {};

		var title = this.trigger.innerHTML.stripTags()
		//document.title = document.title.toString().replace(/(.* - .*) - .*/, '$1') +' - '+ title;
		
		options.pageName = AC.Tracking.pageName();
		options.prop6 = options.pageName;
		
		options.prop4 = document.location;

		options.prop2 = 'www.befr.hotnews.'+this.name;
		
		AC.Tracking.trackPage(options);
	}
});
