/*! 
 * Copyright (c) Day Barr 2009. All rights reserved.
 * By http://www.DayBarr.com for use at http://www.FeedRunner.net
 */
$(function() {
var spectrum = [],
visitedUrls = {},
linkCount = 0,
uniqueLinkCount = 0,
feedCount = 0,
currentDepth = 0,
startUrl = 'http://pipes.yahoo.com/pipes/pipe.run?_id=41e1a853a67617db61914c48b4bbdec6&_render=rss&q=%40feedrunner',
start = function() {
    var $list = $('<ul/>').hide().appendTo($('#content'));
    loadFeedInList(startUrl, $list, "page-link");
},
extractBaseUrl = function(url) {
    return url.replace(/^(https?:\/\/[^\/]+)\/.*/, '$1');
},
loadFeedInList = function(url, $list, linkClass) {
    $list.append(
        $('<p class="loading"/>').text('Loading feed...')
    ).fadeIn();
    linkClass = linkClass || "feed-link";
    $.ajax({
        url: 'http://pipes.yahoo.com/pipes/pipe.run?_id=jLS87ckf3hG8m90APm7D0g&_render=json&url='+encodeURIComponent(url)+'&_callback=?',
        dataType: 'jsonp',
        success: function(data) {
            $list.empty().hide();
            if (!data.value || !data.value.items || !data.value.items.length) {
                $list.append('<div class="error">Dead end</div>');
                return;
            }
            $.each(data.value.items, function(i, item) {
                $list.append(
                    $('<li/>').addClass(linkClass).append(
                        $('<a/>').attr({
                            href: item.link,
                            id: 'link'+linkCount++,
                            title: item.title
                        }).text(item.title)
                    )
                );
            });
            feedCount++;
        },
        error: function() {
            $list.append('<div class="error"><code>:(</code></div>');
        },
        complete: function() {
            afterListLoaded($list);
        }
    });
},
loadPageInList = function(url, $list) {
    var baseUrl = extractBaseUrl(url),
    js = 'javascript'; // Avoid jslint warning of script urls
    $list.append(
        $('<p class="loading"/>').text('Loading page content...')
    ).fadeIn();
    $.ajax({
        url: "http://query.yahooapis.com/v1/public/yql?q="+encodeURIComponent("select * from html where url='")+encodeURIComponent(url)+encodeURIComponent("' and xpath=\"//a[not(starts-with('"+js+":',@href))]\"")+"&format=json&callback=?",
        dataType: 'jsonp',
        success: function(data) {
            $list.empty().hide();
            if (!data.query || !data.query.results || !data.query.results.a || !data.query.results.a.length) {
                $list.append('<div class="error">Dead end</div>');
                return;
            }
            var links = data.query.results.a,
            uniqueUrls = {};

            // Determine uniqueUrls using object with urls as keys
            $.each(links, function(i, link) {
                // Only add URLs that do not begin with the base URL i.e. are external URLs
                if (link.href.substr(0, baseUrl.length) != baseUrl &&
                    link.href.match('https?://') &&
                    !uniqueUrls[link.href]) {
                    uniqueUrls[link.href] = 1;
                    var text = $.trim(link.content) || $.trim(link.title) || $.trim(link.img ? link.img.alt : '') || ((link.href.length < 63) ? link.href : (link.href.slice(0,60)+"..."));
                    $list.append(
                        $('<li class="page-link"/>').append(
                            $('<a/>').attr({
                                href: link.href,
                                id: 'link'+linkCount++,
                                title: text
                            }).text(text)
                        )
                    );
                }
            });
        },
        error: function() {
            $list.append('<div class="error"><code>:(</code></div>');
        },
        complete: function() {
            afterListLoaded($list);
        }
    });
},
afterListLoaded = function($list) {
    var parentDepth = $list.parent('li').data('depth') || 0,
    depth = parentDepth+1;
    
    if (depth > currentDepth) {
        currentDepth = depth;
    }

    $list.children('li').each(function(i, item) {
        $(item).data('depth',depth).
        addClass('depth'+(depth%30)); // mod 30 to get colors to cycle
    });

    $list.find('>li>a').each(function(i, link) {
        // Use favicon as background image for every link.
        // Because in css can't guarantee icon size is 16x16 as we could with an img element.
        // So wrap link content in a span with a background color that will block out any too-big images.
        var $link = $(link);
        $link.before(
            $('<img class="favicon"/>').attr('src',extractBaseUrl($link.attr('href'))+'/favicon.ico'),
            ' '
        );
    });

    if ($list.children('li').length) {
        $list.slideDown(2000, expandNextListItem);
    } else {
        $list.show();
        setTimeout(expandNextListItem,100);
    }
},
expandNextListItem = function() {
    var $notDone = $('li:not(.done)'),
    getNextEl = function() {
        // Choose next item at random from all those that have not yet been done
        return $notDone.eq( Math.floor( Math.random() * $notDone.length ) );

        // Choose first of those not yet done
//        return $notDone.eq(0)
    },
    $next = getNextEl();
    
    $('#current-depth').text(currentDepth);
    $('#link-count').text(linkCount);
    $('#feed-count').text(feedCount);

    if ($next.length) {
        var url = $next.find('>a').attr('href').replace(/#.*$/,''); // Strip off hash fragment for uniquing purposes 
        $next.addClass('done');
        if (visitedUrls[url]) {
            $next.append(' Already visited');
            visitedUrls[url].find('>a').after(' +');
            setTimeout(expandNextListItem,0);
            return;
        }
        var $list = $('<ul/>').hide();
        $next.append($list);
        visitedUrls[url] = $next;
        uniqueLinkCount++;
        var animsDone = 0;
        // Scroll to the next element
        $('html,body').animate({scrollTop: $next.offset().top - 100}, 2000, function() {
            if (++animsDone == 2) {
                if ($next.hasClass('feed-link')) {
                    loadPageInList(url, $list);
                } else {
                    loadFeedInList(url, $list);
                }
            }
        });
    } else {
        if (confirm("Can't find any more feeds. Restart?")) {
            location.reload();
        }
    }
};

// Easter egg. Pass URL of starting feed via url parameter in query string
if (location.search) {
    $.each(location.search.slice(1).split('&'), function(i, pair) {
        pair = pair.split('=');
        if (pair[0] == 'url') {
            startUrl = decodeURIComponent(pair[1]);
        }
    });
}

start();
});

