jQuery.recipePage = (function ($) {
    function itemFactory(page, index) {
        var item = {
                recipePage: page,
                song: page.songs[index],
                prev: null,
                next: null
            },
            deferredPrevPage,
            deferredNextPage;

        // Set the previous item function if applicable.
        if (index > 0) {
            item.prev = function () {
                return itemFactory(page, index - 1);
            };
        }
        else if (page.prev) {
            deferredPrevPage = page.prev();
            if (deferredPrevPage) {
                item.prev = function () {
                    return deferredPrevPage.pipe(function (prevPage) {
                        if (prevPage && prevPage.songs && prevPage.songs.length > 0) {
                            return itemFactory(prevPage, prevPage.songs.length - 1);
                        }
                        else {
                            return null;
                        }
                    });
                };
            }
        }

        // Set the next item function if applicable.
        if (index < page.songs.length - 1) {
            item.next = function () {
                return itemFactory(page, index + 1);
            };
        }
        else if (page.next) {
            deferredNextPage = page.next();
            if (deferredNextPage) {
                item.next = function () {
                    return deferredNextPage.pipe(function (nextPage) {
                        if (nextPage && nextPage.songs && nextPage.songs.length > 0) {
                            return itemFactory(nextPage, 0);
                        }
                        else {
                            return null;
                        }
                    });
                };
            }
        }

        return item;
    }; // itemFactory

    function pageFactory(url) {

        if (!url) {
            return null;
        }

        return $.ajax({
            url: url,
            dataType: 'json'
        })
        .pipe(buildPage);
    }

    function buildPage(result) {
        var page = {
            songs: result.data,
            title: result.title,
            linkParams: result.linkParams,
            self: function () {
                return pageFactory(result.links.self);
            },
            beginning: function () {
                return pageFactory(result.links.beginning);
            },
            end: function () {
                return pageFactory(result.links.end);
            },
            firstItem: function () {
                return itemFactory(page, 0);
            },
            items: function () {
                var items = [],
                    deferredItems = $.Deferred(),
                    i;

                if (page.songs.length === 0) {
                    deferredItems.resolve([]);
                }
                else {
                    for (i = 0; i < page.songs.length; i++) {
                        items[i] = itemFactory(page, i);
                    }
                    deferredItems.resolve(items);
                }
                
                return items;
            }
        };

        if (result.links.prev) {
            page.prev = function () {
                return pageFactory(result.links.prev);
            }
        }

        if (result.links.next) {
            page.next = function () {
                return pageFactory(result.links.next);
            }
        }

        return page;
    } // buildPage

    return function (url) {
        return pageFactory(url);
    };

})(jQuery);

