﻿/**
 * Loads the feed on the supplied Url.
 * @param {url} Feed's url
 * @param {limit} Maximum number of entries to read
 * @param {feedLoaderPath} Base path of the folder which contains the page used to read feeds
 * @public
 */
function LoadFeed(url, limit, feedLoaderPath){
	
	var requestedFeed = false
	
	if (window.XMLHttpRequest) 
	{// Mozilla, Safari etc
		requestedFeed = new XMLHttpRequest()
	} 
	else if (window.ActiveXObject)
	{ //IE
		try { requestedFeed = new ActiveXObject("Msxml2.XMLHTTP") } 
		catch (e)
		{ // for old versions
			try { requestedFeed = new ActiveXObject("Microsoft.XMLHTTP") } catch (e){}
		}
	} 
	else
	{
		return false;
	}
	
	try
	{
	    url = feedLoaderPath + '/FeedLoader.aspx?FeedUrl=' + escape(url);
	    requestedFeed.open('GET', url, false); 
	    requestedFeed.send(null);
		//parses and returns the information
		if(requestedFeed.status == 200)
		{
    	    return ProcessFeed(requestedFeed.responseXML, limit);
    	}
    	else
    	{
    	    throw ('Not valid header. Received value: ' + requestedFeed.status);
    	}
    }
    catch(e)
    {
        window.status = 'There was an error while loading feed. Details: ' + e.message;
        var result = new Object();
        result.error = true;
        return result;
    }
}

// process the information received on the Feed and creates a custom
// class object with the information to retrieve
function ProcessFeed(xml, limit)
{
    //creates an object on the fly, and sets there the returned values
    var feedResult = new Object();
    feedResult.entries = new Array();
    	
    try
    {
        if(IsAtom(xml))
        {
            ProcessAtom(xml, feedResult, limit);
        }
        else
        {
            ProcessRSS(xml, feedResult, limit);
        }
        		
		feedResult.error = false;
	}
	catch(e)
	{
	    //if an error occurred, marks the flag
	    feedResult.error = true;
	}
	
	return feedResult;
}

//Determines if the supplied feed belongs to an Atom one
function IsAtom(xml)
{
    var root = xml.getElementsByTagName('feed')[0];
    if(root == null)
        return false;
        
    var att = root.getAttribute('xmlns');
    return (att != null && att.indexOf('Atom') > -1);
}

//Processes the information supplied on "xml" as related to an Atom feed
function ProcessAtom(xml, feedResult, limit)
{
    ProcessFeedInfo(xml, feedResult, limit, true, 'text/html', 'html');
}

//Processes the information supplied on "xml" as related to an RSS feed
function ProcessRSS(xml, feedResult, limit)
{
    ProcessFeedInfo(xml, feedResult, limit, false, null, null);
}

//Processes the information supplied on "xml" based on configuration
//info supplied
function ProcessFeedInfo(xml, feedResult, limit, isAtom, atomLinkType, atomContentType)
{
    //gets only those elements which correspond to feed entries
    xml = xml.getElementsByTagName( (isAtom ? 'entry' : 'item') );
    
    if(xml.length == 0)
        return;
    
    //verifies there are enough element to reach the limit, otherwise,
    //changes it	
    if(xml.length < limit)
        limit = xml.length;
		
	//get feed's information    		
    for (var l=0; l < limit; l++)
    {	
        var feedClass = new Object();
        try
        {
            feedClass.title = xml[l].getElementsByTagName('title').item(0).firstChild.data;
            
            //loads related link
            if(isAtom)
            {
                //for atoms, a value must be provided on atomLinkType, which marks
                //the type of Link for the "replies" element
                var links = xml[l].getElementsByTagName('link')
                if(links.length > 1)
                {
                    for(var counter = 0; counter < links.length; counter++)
                    {
                        var link = links[counter];
                        if( link.getAttribute('type').toLowerCase() == atomLinkType.toLowerCase() && 
                            link.getAttribute('rel').toLowerCase() == 'replies')
                        {
                            feedClass.link = link.getAttribute('href');
                            break;
                        }
                    }
                }
                else if(links.length == 1)
                {
                    feedClass.link = links[0].getAttribute('href');
                }
            }
            else
            {
                var elements = xml[l].getElementsByTagName('link');
                if(elements.length > 0 && elements.item(0).firstChild != null)
                    feedClass.link = elements.item(0).firstChild.data;
            }
	        
	        //publication date
	        var pubElement = null;
	        if(isAtom) 
	        {
	            pubElement = xml[l].getElementsByTagName('updated');
	            //if there is no item with the updated date, then searchs using
	            //the publication one
	            if(pubElement.length == 0) 
	                pubElement = xml[l].getElementsByTagName('published');
	            
	        }
	        else
	        {
	            pubElement = xml[l].getElementsByTagName('pubDate');
	        }
	        if(pubElement != null && pubElement.length > 0)
	            feedClass.publishedDate = pubElement.item(0).firstChild.data;
	        
	        //feed's content
	        if(isAtom)
	        {
	            var elements = xml[l].getElementsByTagName('content');
	            if(elements.length == 0)
	            {
	                elements = xml[l].getElementsByTagName('summary');
	                if(elements.length > 0)
	                {
	                    feedClass.content = elements[0].firstChild.data;
	                }
	            }
	            else
	            {
	                for(var counter = 0; counter < links.length; counter++)
	                {
	                    if(elements[counter].getAttribute('type').toLowerCase() == atomContentType.toLowerCase())
	                    {
	                        feedClass.content = elements[counter].firstChild.data;
	                        break;
	                    }
	                }
	            }
	        }
	        else
	        {
	            feedClass.content = xml[l].getElementsByTagName('description').item(0).firstChild.data;
	        }
	    }
	    catch(ex)
	    {
	        feedClass.error = true;
	    }
	    feedResult.entries.push(feedClass);
    }
}