﻿/// <reference path="jquery-1.4.1.min.js" />
/// <reference path="netqast.functions.js" />
/// <reference path="firebug-vsdoc.js" />

(function($) {

    var imgStarOn = "/content/images/stars/staron.png";
    var imgStarOff = "/content/images/stars/staroff.png";
    var starClicked = false;

    jQuery.extend(
    {
        //Ratify jQuery Extension
        //#region
        ratify: function(event) {
            if (event.type == "mouseenter") {
                onMouseEnter($(this));
            }
            else {
                onMouseLeave($(this));
            }

            function onMouseEnter(rateable) {
                if (typeof (rateable.data("rating")) == "undefined") {
                    var netqastNode = rateable.parents("[netqast]:first");
                    var config = netqast.parseConfig(netqastNode.attr("netqast"));
                    rateable.data("rating", new Rating(config));
                }

                buildRatingControl(rateable);
            };

            function onMouseLeave(rateable) {
                if (starClicked) {
                    $(".noRatingText", rateable).remove();
                    $("a img", rateable).remove();
                    $("a", rateable).append($(".ratingInput img"));
                    rateable.addClass("rated");
                }

                $(".ratingInput").remove();
                $("a", rateable).show();

                starClicked = false;
            };

            function onStarHover() {
                var star = $(this);
                var rating = star.attr("alt");

                $(".ratingInput img:lt(" + rating + ")")
                    .attr("src", imgStarOn);
                $(".ratingInput img:gt(" + (rating - 1) + ")")
                    .attr("src", imgStarOff);
            };

            function onStarClick() {
                starClicked = true;
                $(this).closest(".rateable").data("rating").update($(this).attr("alt"));
            };

            function buildRatingControl(rateable) {
                $("a", rateable).hide();
                var rating = rateable.data("rating");
                var imgDiv = $('<div class="ratingInput" />');

                for (var i = 1; i <= 5; i++) {

                    var imgNode = $("<img />");
                    imgNode.hover(onStarHover);
                    imgNode.click(onStarClick);
                    imgNode.attr("alt", i);
                    imgNode.attr("title", getRatingTitleText(i));

                    if (rating.value() > i) {
                        imgNode.attr("src", imgStarOn);
                    }
                    else {
                        imgNode.attr("src", imgStarOff);
                    }

                    imgDiv.append(imgNode);
                }

                rateable.append(imgDiv);
            };

            function getRatingTitleText(index) {
                if(index == 1)
                    return 'Click to rate as "Really disliked it"';
                if(index == 2)
                    return 'Click to rate as "Disliked it"';
                if(index == 3)
                    return 'Click to rate as "Indifferent"';
                if(index == 4)
                    return 'Click to rate as "Liked it"';
                if (index == 5) 
                    return 'Click to rate as "Loved it"';
            }

            function Rating(config) {

                this.config = config;
                this.rating = null;

                this.value = function() {
                    if (this.rating == null) {
                        this.rating = 0;
                    }

                    return this.rating;
                };

                this.update = function(rating) {
                    this.rating = rating;
                    $.post(this.config.url + "userrating", "rating=" + this.rating);
                };
            };
        },
        //#endregion

        //Hoverify jQuery Extension
        //#region
        hoverify: function(event) {
            var hoverDelay = 650;  //milliseconds

            if (event.type == "mouseenter") {
                onMouseEnter($(this), event);
            }
            else {
                onMouseLeave($(this));
            }

            function onMouseEnter(hoverable, event) {
                var hoverItem = $(".hoverItem", hoverable);
                hoverable.data("hovered", true);

                setTimeout(function() {
                    if (isHovered(hoverable)) {
                        if (hoverItem.length == 0) {
                            var netqastNode = hoverable.parents("[netqast]:first");
                            var config = netqast.parseConfig(netqastNode.attr("netqast"));

                            //Ajax request for hover item html.
                            $.get(config.url + "hover_html", function(data) {
                                hoverable.append(data);
                                var relativeX = event.pageX - $("#PageWrap").offset().left;
                                if (relativeX > 560)
                                    $(".hoverItem", hoverable).addClass("hoverItemLeft");
                                else
                                    $(".hoverItem", hoverable).addClass("hoverItemRight");

                                if (!isHovered(hoverable)) {
                                    $(".hoverItem", hoverable).hide();
                                }
                            });
                        }
                        else {
                            hoverItem.show();
                        }
                    }
                }, hoverDelay);
            };

            function onMouseLeave(hoverable) {
                hoverable.data("hovered", false);
                $(".hoverItem", hoverable).hide();
            };

            /// <summary>Convenience method for testing if the user is still hovering over the hoverable item.</summary>
            /// <param type="jQuery" name="hoverable">The hoverable item.</param>
            /// <returns type="boolean" />
            function isHovered(hoverable) {
                return hoverable.data("hovered");
            };
        }
        //#endregion

    });

    //Browsify jQuery Plugign
    //#region
    $.fn.browsify = function(settings) {

        settings = $.extend({
            "itemContainerClass": "browseContainer",
            "itemContentClass": "browseContent"
        }, settings);

        var eventHandler = {

            onSortBySelectChange: function() {
                var sortSelect = $(this);
                var paginator = sortSelect.data("paginateContainer").data("paginator");
                paginator
                    .sortBy($("option:selected", sortSelect).val())
                    .resetArrows()
                    .current();
            },

            onFooterLinkClick: function(event) {
                event.preventDefault();
                var footerLink = $(this);
                var paginator = footerLink.data("paginateContainer").data("paginator");
                paginator.gotoPage(parseInt(footerLink.text()));
            }
        };

        browsifyThis = function() {
            var paginateContainer = $(this),
                browseContainer;

            //Look up the controls container div and cache it.
            if (netqast.isUndefined(paginateContainer.data("browseContainer"))) {
                var controlType = "browse";
                browseContainer = paginateContainer.closest("." + settings.itemContainerClass);
                if (browseContainer.length == 0) {
                    controlType = "pagingBrowse";
                    browseContainer = paginateContainer.closest("#PagingBrowseContainer");
                }

                paginateContainer.data("controlType", controlType);
                paginateContainer.data("browseContainer", browseContainer);
            }
            else {
                browseContainer = paginateContainer.data("browseContainer");
            }

            var leftArrow, rightArrow, seeAllLink, sortSelect;
            switch (paginateContainer.data("controlType")) {

                case "browse":
                    //Hook up left arrow to the selected paginateContainer
                    leftArrow = browseContainer
                        .find("[id$='_lnkLeftArrow']")
                        .browseArrowLinkify("left", paginateContainer);

                    //Hook up right arrow to the selected paginateContainer
                    rightArrow = browseContainer
                        .find("[id$='_lnkRightArrow']")
                        .browseArrowLinkify("right", paginateContainer);
                    break;

                case "pagingBrowse":
                    //Hook up left arrow to the selected paginateContainer
                    leftArrow = browseContainer
                        .find("#lnkLeftArrow")
                        .browseArrowLinkify("left", paginateContainer);

                    //Hook up right arrow to the selected paginateContainer
                    rightArrow = browseContainer
                        .find("#lnkRightArrow")
                        .browseArrowLinkify("right", paginateContainer);

                    browseContainer
                        .find(".pagingBrowseHeader select")
                        .data("paginateContainer", paginateContainer)
                        .change(eventHandler.onSortBySelectChange);

                    browseContainer
                        .find(".footerLinks a")
                        .data("paginateContainer", paginateContainer)
                        .click(eventHandler.onFooterLinkClick);

                    break;

                default:
                    alert("Invalid browse control detected in jQuery Browsify plugin");

            };

            //Only need to setup the pagination class once for each paginateContainer.
            if (paginateContainer.data("paginator") == null) {
                var itemContainer = browseContainer.find("." + settings.itemContentClass + ":first"),
                    rawConfig = paginateContainer.attr("netqast");

                paginateContainer.data("paginator",
                    new Paginator(
                        netqast.parseConfig(rawConfig),
                        leftArrow,
                        rightArrow,
                        itemContainer,
                        browseContainer
                    )
                );
            }

            //Set the arrows based on the selected genrelink.
            paginateContainer.data("paginator").resetArrows();
        };

        /**
        * This class manages the pagination of the browse control.
        *
        * @param {object} config {itemType:"song", genreName:"alternative", genreId:2}
        * @param {jQuery} leftArrow Reference to the left arrow.
        * @param {jQuery} rightArrow Reference to the right arrow.
        * @param {jQuery} itemContainer Reference to the item container.
        * @param {jQuery} browseContainer Referernce to the browse container.
        */
        function Paginator(config, leftArrow, rightArrow, itemContainer, browseContainer) {

            this.start = 0;
            this.count = parseInt(config.count);
            this.currentItemCount = null;
            this.config = config;
            this.leftArrow = leftArrow;
            this.rightArrow = rightArrow;
            this.itemContainer = itemContainer;
            this.browseContainer = browseContainer;

            this.sortBy = function(sort) {
                this.config.sortby = sort;
                return this;
            };

            this.current = function() {
                this.load();

                return this;
            };

            this.previous = function() {
                if (this.start >= this.count) {
                    this.start -= this.count;
                    this.load();
                }

                return this;
            };

            this.next = function() {
                if (this.currentItemCount >= this.count) {
                    this.start += this.count;
                    this.load();
                }

                return this;
            };

            this.gotoPage = function(pageNumber) {
                this.start = (pageNumber - 1) * this.count;
                this.load();

                return this;
            }

            this.paginatedUrl = function() {
                return this.config.url
                    + "?sortby=" + this.config.sortby
                    + "&start=" + this.start
                    + "&count=" + this.count
                    + "&contenttype=" + this.config.contenttype;
            };

            this.resetArrows = function() {
                //Initialize currentItemCount if this is the first time being loaded.
                if (this.currentItemCount == null) {
                    this.currentItemCount = this.itemContainer.find(".browseListItem").length;
                }

                var url = "/" + this.config.contenttype + "/" + this.config.genre + "?sortby=" + this.config.sortby + "&count=" + this.count;

                if (this.start < this.count) {
                    this.leftArrow.hide();
                }
                else {
                    this.leftArrow
                        .attr("href", url + "&start=" + (this.start - this.count))
                        .show();
                }

                if (this.currentItemCount < this.count) {
                    this.rightArrow.hide();
                }
                else {
                    this.rightArrow
                        .attr("href", url + "&start=" + (this.start + this.count))
                        .show();
                }

                //Updates the "see all" link (just so the hover status displays correctly)
                this.browseContainer
                    .find("[id$='_lnkSeeAll']")
                    .attr("href", "/" + this.config.contenttype + "/" + this.config.genre);

                //Update the footer link page numbers (just so the hover status displays correctly)
                var start = 1;
                var count = this.count;
                this.browseContainer
                    .find(".footerLinks a")
                    .each(function() {
                        $(this).attr("href", url + "&start=" + start);
                        start += count;
                    });

                return this;
            };

            this.load = function() {
                $.ajax({
                    url: this.paginatedUrl(),
                    beforeSend: $.proxy(this, "ajaxBeforeSend"),
                    success: $.proxy(this, "ajaxSuccess"),
                    error: $.proxy(this, "ajaxError"),
                    complete: $.proxy(this, "ajaxComplete")
                });
            };

            this.ajaxBeforeSend = function(xhr) {
                //TODO Add code here to handle starting the browse control Ajax loader image.
            };

            this.ajaxComplete = function(xhr, status) {
                //TODO Add code here to handle stopping the browse control Ajax loader image.
            };

            this.ajaxSuccess = function(data, status) {
                this.itemContainer.html(data).append($("<div/>").addClass("clear"));
                this.currentItemCount = $(".browseListItem", data).length;
                this.resetArrows();
            };

            this.ajaxError = function(xhr, status, exception) {
                //TODO Add Ajax error handling code here if necessary.
            };
        };

        return this.each(browsifyThis);
    };
    //#endregion

    //GenreLinkify jQuery Plugin
    //#region
    $.fn.browseGenreLinkify = function() {
        browseGenreLinkifyThis = function() {
            $(this).click(genreLinkClick);
        };

        function genreLinkClick(event) {
            event.preventDefault();

            var genreLink = $(this);
            var genreListItem = genreLink.parent();
            var genreList = genreListItem.parent();

            genreList
                    .children(".featureGenreLink:first")
                    .removeClass("featureGenreLink")
                    .addClass("genreListItem");

            genreListItem
                    .removeClass("genreListItem")
                    .addClass("featureGenreLink");

            genreLink
                    .browsify()
                    .currentPage();
        }

        return this.each(browseGenreLinkifyThis);
    };

    $.fn.currentPage = function() {
        currentThis = function() {
            var genreLink = $(this);

            if (genreLink.data("paginator") != null) {
                genreLink.data("paginator").current();
            }
            else {
                alert("Current genre link has no associated paginate data.");
            }
        };

        return this.each(currentThis);
    };
    //#endregion

    //BrowseArrowLinkify jQuery Plugin
    //#region
    $.fn.browseArrowLinkify = function(direction, genreLink) {
        browseArrowLinkifyThis = function() {
            var arrow = $(this);

            // Make sure to only register the click event once
            // since this is invoked every time the tab changes.
            if (typeof (arrow.data("clickEventRegistered")) == "undefined") {
                arrow
                    .data("clickEventRegistered", true)
                    .click(arrowClick);
            }

            arrow
                .data("direction", direction)
                .data("genreLink", genreLink);
        };

        function arrowClick(event) {
            event.preventDefault();

            var arrow = $(this);

            if (arrow.data("genreLink") != null) {
                var genreLink = arrow.data("genreLink");
                var direction = arrow.data("direction");

                switch (direction) {
                    case "left":
                        genreLink.data("paginator").previous();
                        break;

                    case "right":
                        genreLink.data("paginator").next();
                        break;

                    default:
                        alert("Invalid arrow direction detected: " + direction);
                }
            }
            else {
                alert("Arrow has no associated genre link.");
            }
        };

        return this.each(browseArrowLinkifyThis);
    };
    //#endregion

})(jQuery);
