// tokai 11.06.2008
var xparser = {};
// ===================================
// Base classes and functions
// ===================================
xparser.feedType = {
	rss: 1,
	atom: 2
};

xparser.FeedNode = function(oNode){
    try{
	    this.value = (oNode && (oNode.text || oNode.getText())) || null;	
	}
	catch(Error)
	{
	    this.value = null;
	}
}

xparser.BaseFeed = function(iFeedType, fpCallBack, oCallBackScope){
	this.type = iFeedType || null;
	this.title = null;
	this.link = null;
	this.description = null;
	this.copyright = null;
	this.generator = null;
	this.modified = null;
	this.author = null;
	this.items = [];
	
	this.callBack = (typeof fpCallBack == "function") ? fpCallBack : function() {};
	this.callBackScope = (typeof oCallBackScope == "object") ? oCallBackScope : this;
};

xparser.BaseFeed.prototype = {
	parse: function(oContextNode, oElements, oNamespaces){
		for(var sProperty in oElements){
			if(oElements.hasOwnProperty(sProperty)){
				this[sProperty] = new xparser.FeedNode(zXPath.selectSingleNode(oContextNode, oElements[sProperty], oNamespaces));
			}
		}
	}
};

xparser.BaseItem = function(){
	this.title = null;
	this.author = null;
	this.link = null;
	this.description = null;
	this.content = null;
	this.date = null;
};

xparser.BaseItem.prototype = {
	parse: function(oContextNode, oElements, oNamespaces){
		for(var sProperty in oElements){
			if(oElements.hasOwnProperty(sProperty)){
				this[sProperty] = new xparser.FeedNode(zXPath.selectSingleNode(oContextNode, oElements[sProperty], oNamespaces));	
			}
		}
	}
};

// ===================================
// ATOM classes and functions
// ===================================
xparser.AtomFeed = function(oRootNode, fpCallBack, oCallBackScope){
	xparser.BaseFeed.apply(this, [xparser.feedType.atom, fpCallBack, oCallBackScope]);
	
	var oNamespaces = {
	    atom: oRootNode.namespaceURI
	};
	
	var oElements = {
		title: "atom:title",
		link: "atom:link/@href",
		description: "atom:tagline",		
		copyright: "atom:copyright",
		generator: "atom:generator",
		modified: "atom:modified",
		author: "atom:author"
	};
	
	this.parse(oRootNode, oElements, oNamespaces);
	
	var cEntries = zXPath.selectNodes(oRootNode, "atom:entry", oNamespaces);
	
	for(var i = 0, oEntry; oEntry = cEntries[i]; i++){
		this.items.push(new xparser.AtomItem(oEntry, oNamespaces));	
	}
	this.callBack.call(this.callBackScope, this);
};
xparser.AtomFeed.prototype = new xparser.BaseFeed();

xparser.AtomItem = function(oEntryNode, oNamespaces){
	xparser.BaseItem.apply(this, []);
	var oElements = {
		title: "atom:title",
		link: "atom:link/@href",
		description: "atom:content",
		date: "atom:published",
		author: "atom:author",
		summary: "atom:summary"
	};
	
	this.parse(oEntryNode, oElements, oNamespaces)
};
xparser.AtomItem.prototype = new xparser.BaseItem(); 

// ===================================
// RSS classes and functions
// ===================================
xparser.RssFeed = function(oRootNode, fpCallBack, oCallBackScope){
	xparser.BaseFeed.apply(this, [xparser.feedType.rss, fpCallBack, oCallBackScope]);
	
	var oNamespaces = {
	    content: "http://purl.org/rss/1.0/modules/content/"
	};
	
	var oChannelNode = zXPath.selectSingleNode(oRootNode, "channel");
	var oElements = {
		title: "title",
		link: "link",
		description: "description",		
		copyright: "copyright",
		generator: "generator",
		modified: "lastbuilddate",
		author: "managingeditor"
	};
	
	this.parse(oChannelNode, oElements, oNamespaces);
	
	var cItems = zXPath.selectNodes(oChannelNode, "item");
	
	for(var i = 0, oItem; oItem = cItems[i]; i++){
		this.items.push(new xparser.RssItem(oItem, oNamespaces));	
	}
	
	this.callBack.call(this.callBackScope, this);
};
xparser.RssFeed.prototype = new xparser.BaseFeed();

xparser.RssItem = function(oItemNode, oNamespaces){
	xparser.BaseItem.apply(this);
	var oElements = {
		title: "title",
		link: "link",
		description: "description",
		content: "content:encoded",
		date: "pubDate",
		author: "author"
	};
	
	this.parse(oItemNode, oElements, oNamespaces)
};
xparser.RssItem.prototype = new xparser.BaseItem();

// ===================================
// Atom classes and functions
// ===================================
// TODO:

// ===================================
// Fetching methods
// ===================================
xparser.getFeed = function(sUrl, fpCallBack, oCallBackScope){
	var oReq = zXmlHttp.createRequest();
	
	oReq.onreadystatechange = function(){
	
		if(oReq.readyState == 4){
		    
			if(oReq.status == 200 || oReq.status == 304){
				var oFeed = null;
				var oXmlDom = zXmlDom.createDocument();
				oXmlDom.loadXML(oReq.responseText);				
				if(oXmlDom.parseError.errorCode != 0){
					throw new Error("XParser error: the requested feed is not valid XML and could not be parsed");	
			    }
			    else{
				    var oRootNode = oXmlDom.documentElement;
				    var sRootName;
				    if(oRootNode.nodeName.indexOf(":") > -1)
					    sRootName = oRootNode.nodeName.split(":")[1];
				    else
					    sRootName = oRootNode.nodeName;
				    switch(sRootName.toLowerCase()){
					    case "feed": // atom
						    oFeed = new xparser.AtomFeed(oRootNode, fpCallBack, oCallBackScope);
						    break;
					    case "rss": // rss
						    //check version
						    if(parseInt(oRootNode.getAttribute("version")) < 2)
							    throw new Error("XParser error: RSS Feed version not supported!");
						    oFeed = new xparser.RssFeed(oRootNode, fpCallBack, oCallBackScope);    						
						    break;
					    default: // not supported
						    throw new Error("XParser error: Supplied feed is currently not supported!");
						    break;
				    }
				}
								
			}
			else{
				    throw new Error("XParser error: XHR ERROR, STATUS: " + oReq.status);
			}			
		}
	};
	oReq.open("GET", sUrl, true);
	oReq.send(null);
};


