/* ===== 
 * @fileoverview RSS feed scroller based on Google Aiax API for feeds fetching
 * @author <a href="mailto:info@pagit.eu">Paolo Geninatti</a>
 * @version 1.0.1
 * =====
 */

var feedfetcher_loading_image="modules/mod_pgt_rssscroller/ajax-loader.gif"

//===== Initializations ===============================================================================================

function PGTFeedControl(feedData, container, options) {
	this.nodes = {};
  	this.feeds = [];
  	this.results = [];

    container = document.getElementById(container);
	container.innerHTML='<img src="'+feedfetcher_loading_image+'" /> Loading RSS feed(s)'

    for (var i=0; i<feedData.length; i++) {
      	var o = {};
        o = feedData[i];
		if (o && o.title) {
	  		var s = o.title;
	  		o.title = s.replace(/</g,'&lt;').replace(/>/g, '&gt;');
		}
      	this.feeds.push(o);
  	}
  	this.parseOptions_(options);
  	this.setup_(container);
}

PGTFeedControl.DEFAULT_TOT_RESULTS = 20;
PGTFeedControl.DEFAULT_DISPLAY_TIME = 5000;
PGTFeedControl.DEFAULT_TRANSITION_TIME = 1000;
PGTFeedControl.DEFAULT_SCROLL_METHOD = "block";

PGTFeedControl.prototype.parseOptions_ = function(options) {
  	this.options = {
    	totResults : PGTFeedControl.DEFAULT_TOT_RESULTS,			// total number of feeds
    	linkTarget : google.feeds.LINK_TARGET_BLANK,				// link target
    	displayTime : PGTFeedControl.DEFAULT_DISPLAY_TIME,			// display time for each feed
    	transitionTime : PGTFeedControl.DEFAULT_TRANSITION_TIME,	// transition time for each feed
		nFeedPage : 1,												// number of feed per page
		scrollMethod : PGTFeedControl.DEFAULT_SCROLL_METHOD,		// scrolling method
																	//  'block'
																	//  'fade'
																	//  'scroll'
																	//  'roll'
		pauseOnHover : true, 										// pause on mouse hover			
		showTitle : false,											// show RSS source title
		showDate : false,											// show RSS feed date			
		showBody : 1,												// show RSS feed body: 0:no, 1:snippet, 2:full			
		instanceId : ""												// univoque instance id														
  	};

  	if (options) {
    	for (var o in this.options) {
      		if (typeof options[o] != 'undefined') {
      			this.options[o] = options[o];
			}
    	}
  	}
	this.started = false;
};

PGTFeedControl.prototype.setup_ = function(container) {
	if (container == null) return;
  	this.nodes.container = container;

	// Browser check
  	if (window.ActiveXObject) {
    	this.ie = this[window.XMLHttpRequest ? 'ie7' : 'ie6'] = true;
  	} else if (document.childNodes && !document.all && !navigator.taintEnabled) {
    	this.safari = true;
  	} else if (document.getBoxObjectFor != null) {
    	this.gecko = true;
  	}
	
  	this.feedControl = new google.feeds.FeedControl();
  	this.feedControl.setLinkTarget(this.options.linkTarget);

  	this.expected = this.feeds.length;
  	this.errors = 0;
	this.saveTransition= false;

  	for (var i = 0; i < this.feeds.length; i++) {
    	var lfeed = new google.feeds.Feed(this.feeds[i].furl);
    	lfeed.setResultFormat(google.feeds.Feed.JSON_FORMAT);
    	lfeed.setNumEntries(this.feeds[i].max);
    	lfeed.load(this.bind_(this.feedLoaded_, i));
  	}
};

PGTFeedControl.prototype.bind_ = function(method) {
  	var self = this;
  	var opt_args = [].slice.call(arguments, 1);
  	return function() {
    	var args = opt_args.concat([].slice.call(arguments));
    	return method.apply(self, args);
  	}
};

PGTFeedControl.prototype.createSubContainers_ = function() {
  	var container = this.nodes.container;
  	this.clearNode_(container);

   	var counter = document.getElementsByName("fc-outer").length + 1;
	var el = document.createElement("div");
	el.className = "fc-outer";
	el.id = this.options.instanceId + "outer-0";
	container.appendChild(el);
	this.outer0 = el;
	container = document.getElementById(this.options.instanceId + "outer-0");	
    if (this.options.pauseOnHover) {
       	el.onmouseover = this.bind_(this.mouseOver_);
      	el.onmouseout = this.bind_(this.mouseOut_);
    }
	
	for (var i = 0; i <= this.options.nFeedPage; i++) {
		var el = document.createElement("div");
		el.className = "fc-inner";
		el.id = this.options.instanceId + "inner-"+i;
		container.appendChild(el);
		if (i==0) {
			this.inner0 = el;
			if (this.options.scrollMethod == "fade") {
				var el = document.createElement("div");
				el.className = "fc-overlay";
				el.id = this.options.instanceId + "overlay";
				el.style.top = "0px";
				container.appendChild(el);
				this.overlay = el;
			    this.setOpacity_(this.overlay, 0.0);			
			}
		}
	}
};

PGTFeedControl.prototype.feedLoaded_ = function(index, result) {
  	if (result.error) {
	    if (++this.errors >= this.expected) {
      		this.nodes.container.innerHTML = 'Feed' + ((this.expected > 1)?'s ':' ') + 'could not be loaded.';
    	}
    return;
  	}
  	
	this.results[index]=result;

  	if (!this.started) {
    	this.createSubContainers_();
		this.itemList = new Array();
		var entries = result.feed.entries;
		for (var i = 0; i < entries.length; i++) {
			nitem =  [index, i];
			this.itemList.push(nitem);
		}
		this.curItem = 0;
		this.fadeStep = 0;			
  		this.displayItems_();
  		this.setDisplayTimer_();
  		this.started = true;
  	} 
	else {
		var entries = result.feed.entries;
		for (var i = 0; i < entries.length; i++) {
			nitem =  [index, i];
			this.itemList.push(nitem);
		}		
	}
};

//===== Display items ===============================================================================================

PGTFeedControl.prototype.displayItems_ = function() {
  	var ix = this.curItem;
	var cheight = 0;
	for (var i = 0; i <= this.options.nFeedPage; i++) {
		var nitem = this.itemList[ix];
    	var container = document.getElementById(this.options.instanceId + "inner-"+i);
	  	var entry = this.results[nitem[0]].feed.entries[nitem[1]];		
		container.innerHTML=this.feedFormat_(entry, this.feeds[nitem[0]].title);
		container.style.top = cheight + 'px';
		cheight += container.offsetHeight;
		if (this.options.scrollMethod == "fade" && i==0) {
			this.overlay.style.height = cheight + 'px';
		}
		if (this.options.scrollMethod != "roll") {
			if (i==this.options.nFeedPage-1) {
				this.outerheight = cheight;
				this.outer0.style.height = this.outerheight + 'px';
			}
		}
		else {
			if (i==this.options.nFeedPage) 
				this.outer0.style.height = cheight + 'px';
		}
		if (++ix >= this.itemList.length)
			ix=0;
	}
};

PGTFeedControl.prototype.displayNextEntry_ = function() {
	this.fadeStep = 0;		
    this.setOpacity_(this.overlay, 0.0);		
	this.outer0.style.top = '0px';
	if (++this.curItem >= this.itemList.length)
		this.curItem=0;
	this.displayItems_();
};

PGTFeedControl.prototype.feedFormat_ = function(feed, title) {
	var rssoutput="<ul>\n";
	rssoutput += "<a href=\"" + feed.link + "\" target=\"" + this.options.linktarget + "\" class=\"rsstitle\">" + feed.title + "</a><br />"
	if (this.options.showTitle)
		rssoutput += "<span class=\"rsslabel\">[" + title + "] </span>"
	if (this.options.showDate)
		rssoutput += "<span class=\"rssdate\">" + this.dateFormat_(feed.publishedDate, "datetime") + "</span>" 
	if (this.options.showBody == 1)	
		rssoutput += "<span class=\"rsscontent\">" + feed.contentSnippet + "</span>" 
	else if (this.options.showBody == 2)	
		rssoutput += "<span class=\"rsscontent\">" + feed.content + "</span>" 		
	rssoutput += "</ul>\n"
	return rssoutput
}

PGTFeedControl.prototype.dateFormat_ =function(datestr, showoptions) {
	var itemdate=new Date(datestr);
	var parseddate= isNaN(itemdate.getTime()) ? "" : ((showoptions.indexOf("datetime")!=-1)? itemdate.toLocaleString() : (showoptions.indexOf("date")!=-1)? itemdate.toLocaleDateString() : (showoptions.indexOf("time")!=-1)? itemdate.toLocaleTimeString() : "" );
	if (parseddate.length)
		parseddate += "<br />";
	return parseddate
}

//===== Animations ===============================================================================================

PGTFeedControl.prototype.setDisplayTimer_ = function() {
  	if (this.displayTimer) {
    	this.clearDisplayTimer_();
  	}
	if (this.options.scrollMethod == "roll")
		// in "roll" mode displayTimer is not used;	
		this.setTransitionTimer_();	
	else {
	  	var cb = this.bind_(this.outDisplayTimer_);
  		this.displayTimer = setInterval(cb, this.options.displayTime);
	}
};

PGTFeedControl.prototype.setTransitionTimer_ = function() {
  	this.clearTransitionTimer_();
  	var cb = this.bind_(this.outTransitionTimer_);
	if (this.options.scrollMethod != "roll") 
	  	this.transitionTimer = setInterval(cb, (this.options.transitionTime / 100));
	else
	  	this.transitionTimer = setInterval(cb, (this.options.transitionTime));
};

PGTFeedControl.prototype.clearDisplayTimer_ = function() {
  	if (this.displayTimer) {
    	clearTimeout(this.displayTimer);
    	this.displayTimer = null;
  	}
};

PGTFeedControl.prototype.clearTransitionTimer_ = function() {
  	if (this.transitionTimer) {
    	clearInterval(this.transitionTimer);
    	this.transitionTimer = null;
  	}
};

PGTFeedControl.prototype.outDisplayTimer_ = function() {
	if (this.options.scrollMethod == "block")
  		this.displayNextEntry_();
	else if (this.options.scrollMethod == "fade") { 
		this.setTransitionTimer_();	
	} else if ( this.options.scrollMethod == "scroll" || this.options.scrollMethod == "scroll2" ) {
		this.setTransitionTimer_();	
	}	
};

PGTFeedControl.prototype.outTransitionTimer_ = function() {
	if (this.options.scrollMethod == "fade") {
		this.inner0.style.top = -Math.round((this.inner0.offsetHeight/100.0) * this.fadeStep) + 'px';
		this.setOpacity_(this.overlay, this.fadeStep/100.0);
		if (++this.fadeStep >= 100) {
			this.displayNextEntry_();			
			this.clearTransitionTimer_();
		}		
	} else if (this.options.scrollMethod == "scroll") {
		var delta = Math.round((this.inner0.offsetHeight/100.0) * this.fadeStep);
		this.outer0.style.top = -delta + 'px';
		this.outer0.style.height = (this.outerheight + delta) + 'px';
		if (++this.fadeStep >= 100) {
			this.displayNextEntry_();			
			this.clearTransitionTimer_();
		}
	} else if (this.options.scrollMethod == "scroll2") {
		var delta = Math.round((this.inner0.offsetHeight/10.0) * Math.sqrt(this.fadeStep));
		this.outer0.style.top = -delta + 'px';
		this.outer0.style.height = (this.outerheight + delta) + 'px';
		if (++this.fadeStep >= 100) {
			this.displayNextEntry_();			
			this.clearTransitionTimer_();
		}
	} else if (this.options.scrollMethod == "roll") {
		this.fadeStep++;
		this.outer0.style.top = -this.fadeStep + 'px';
		if (this.fadeStep == this.inner0.offsetHeight) {
			this.fadeStep = 0;
			this.displayNextEntry_();			
		}
	}
};

//===== Utilities ===============================================================================================

PGTFeedControl.prototype.setOpacity_ = function(node, opacity) {
  	if (node == null) 
		return;
  	opacity = Math.max(0, Math.min(1, opacity));
  	if (opacity == 0) {
    	if (node.style.visibility != 'hidden') {
      		node.style.visibility = 'hidden';
    	}
  	} else {
    	if (node.style.visibility != 'visible') {
      		node.style.visibility = 'visible';
    	}
  	}
  	if (this.ie) {
    	var normalized = Math.round(opacity*100);
    	node.style.filter = 'alpha(opacity=' + normalized + ')';
  	}
  	node.style.opacity = node.opacity = opacity;
};

PGTFeedControl.prototype.clearNode_ = function(node) {
  	if (node == null) 
		return;
  	var child;
  	while ((child = node.firstChild)) {
    	node.removeChild(child);
  	}
};

PGTFeedControl.prototype.mouseOver_ = function() {
	this.saveTransition = (this.transitionTimer != null);
  	this.clearTransitionTimer_();
  	this.clearDisplayTimer_();
}

PGTFeedControl.prototype.mouseOut_ = function() {
    this.setDisplayTimer_();
	if (this.saveTransition)
		this.setTransitionTimer_();
}

