/**
 * Add custom Paginator element for use in template
 */
(function () {
    var Paginator = YAHOO.widget.Paginator,
        l         = YAHOO.lang;

    /**
     * Describe the ui Component
     *
     * @namespace YAHOO.widget.Paginator.ui
     * @class ResultInformation
     * @for YAHOO.widget.Paginator
     *
     * @constructor
     * @param p {Pagintor} Paginator instance to attach to
     */
    Paginator.ui.ResultInformation = function (p) {
        this.paginator = p;

        this.initListeners();
    };

    /**
     * Decorates Paginator instances with new attributes. Called during
     * Paginator instantiation.
     * @method init
     * @param p {Paginator} Paginator instance to decorate
     * @static
     */
    Paginator.ui.ResultInformation.init = function (p) {
        p.setAttributeConfig('name', {
            value : 'Unknown',
            validator : l.isString
        });

        p.setAttributeConfig('count', {
            value : null,
            validator : l.isNumber
        });

        p.setAttributeConfig('countType', {
            value : ['Recording','Recordings'],
            validator : l.isArray
        });

        p.setAttributeConfig('filter', {
            value : null,
            validator : l.isString
        });

        p.setAttributeConfig('filterType', {
            value : 'Collection',
            validator : l.isString
        });
    };

    // Instance members and methods
    Paginator.ui.ResultInformation.prototype = {

        // instance members to store the component state and DOM elements that
        // will represent this component's ui

        /**
         * Describe the node that will be stored in this property
         * @property riDiv
         * @type HTMLElement
         * @private
         */
        riDiv : null // null until render()

        // instance methods

        /**
         * Subscribe to the Paginator's events that will affect this component's ui
         * @method initListeners
         */
        , initListeners : function () {
            var p = this.paginator;

            // Subscribe to any of these that are pertinent to your component's ui
            p.subscribe('recordOffsetChange',this.update,this,true);
            //p.subscribe('rowsPerPageChange', this.update,this,true);
            //p.subscribe('totalRecordsChange',this.update,this,true);

            // subscribe to any change events for attributes this component adds
            // to the Paginator
            p.subscribe('nameChange',this.rebuild,this,true);
            p.subscribe('countChange',this.rebuild,this,true);
            p.subscribe('countTypeChange',this.rebuild,this,true);
            p.subscribe('filterChange',this.rebuild,this,true);
            p.subscribe('filterTypeChange',this.rebuild,this,true);

            // Always subscribe to destroy
            p.subscribe('destroy',this.destroy,this,true);
        }

        /**
         * Generate the nodes and return the appropriate node given the current
         * pagination state.
         * @method render
         * @param id_base {string} used to create unique ids for generated nodes
         * @return {HTMLElement}
         */
        , render : function (id_base) {
            var node = this._initUI(id_base);

            return node;
        }

        /**
         * Initialize the DOM nodes managed by this component
         * @method initUI
         * @param id_base {string} used to create unique ids for generated nodes
         * @private
         */
        , _initUI : function (id_base) {
            var name = this.paginator.get('name');
            var count = this.paginator.get('count');
            var countType = this.paginator.get('countType');
            var filter = this.paginator.get('filter');
            var filterType = this.paginator.get('filterType');

            this.riDiv = createElement('div', {
                'id':id_base + '-result-informantion'
                , 'class':'yui-pg-result-informantion'
            });

            var riCollection = createElement('div', {
                'id':id_base + '-result-informantion-collection'
                , 'class':'yui-pg-result-informantion-collection'
            });
            
            if(l.isNull(filter)) {
                riCollection.innerHTML = "&nbsp;("+count+" "+(countType[count==1?0:1])+")"
            } else {
                riCollection.innerHTML = "&nbsp;("+count+" "+(countType[count==1?0:1])+" in "+filterType+": <em>"+filter+"</em>)"
            }

            this.riDiv.innerHTML = "Results for <em class=\"name\">" + name + "</em>";
            this.riDiv.appendChild(riCollection);

            this.update();

            return this.riDiv;
        }

        /**
         * Make any necessary changes to the component nodes
         * @method update
         * @param e {CustomEvent} The calling change event
         */
        , update : function (e) {
            // It's a good idea to check if there actually was a change
            if (e && e.prevValue === e.newValue) {
                return;
            }
        }

        /**
         * Make more substantial changes in a separate method if necessary
         * @method rebuild
         * @param e {CustomEvent} the calling change event
         */
        , rebuild : function (e) {
            // Making sure there actually was a change
            if (e && e.prevValue === e.newValue) {
                return;
            }

            this.riDiv.innerHTML = this.paginator.get('filterType');

            this.update();
        }

        /**
         * Remove the generated DOM structure
         * @method destroy
         * @private
         */
        , destroy : function () {
            YAHOO.util.Event.purgeElement(this.riDiv);
            this.riDiv.parentNode.removeChild(this.riDiv);
            this.riDiv = null;
        }
    };
})();

var performances = {
    "el":null
    , "pag":null
    , "itemListEl":null
    , "bodyEl":null
    , "containerEls":null
    , "data":null
    , "cs":null
    , "ss":null
    , "performerPerformances":null
    , "totalRecords":0
    , "rowsPerPage":3
    , "pagTemplate":"{ResultInformation} {FirstPageLink} {PreviousPageLink} {PageLinks} {NextPageLink} {LastPageLink}"
    , "init":function(itemListEl, el, data, cs, ss){
        if (YAHOO.lang.isString(itemListEl)) {
            itemListEl = document.getElementById(itemListEl);
        }
        this.itemListEl = itemListEl;

        if (YAHOO.lang.isObject(el)) {
            this.el = el;
            this.bodyEl = $(this.el.id+"Body");
            this.containerEls = [$(this.el.id+"PagTop"), $(this.el.id+"PagBot")]
        } else {
            throw "Missing output element."
        }
        if (YAHOO.lang.isObject(data)) {
            this.data = data;
        } else {
            throw "Missing data object."
        }
        if (YAHOO.lang.isObject(cs) || YAHOO.lang.isNull(cs)) {
            this.cs = cs;
        } else {
            throw "Missing collection selector object."
        }
        if (YAHOO.lang.isObject(ss)) {
            this.ss = ss;
        } else {
            throw "Missing sort selector object."
        }

        YAHOO.util.Event.onDOMReady(function() {
            this.selectPerformer = function(extPerformerID) {
                if (YAHOO.lang.isNull(extPerformerID) || YAHOO.lang.isUndefined(extPerformerID)) {
                    throw "Missing Person ID.";
                }

                var pcs = this.data.performances;
                var prspcs = this.data.performersPerformances;
                this.performerPerformances = prspcs[extPerformerID];
                this.totalRecords = this.performerPerformances.length;
                var performer = this.data.performers["id_"+extPerformerID];
                var count = 0;
                for (var key in this.performerPerformances) {
                    var pid = this.performerPerformances[key];
                    var p = pcs["id_"+pid];
                    count += p.tracks;
                }

                this.pag = new YAHOO.widget.Paginator({
                    'rowsPerPage':this.rowsPerPage
                    , 'totalRecords':this.totalRecords
                    , 'containers':this.containerEls
                    , 'pageLinks': 10 // configure the PageLinks UI Component
                    , 'template':this.pagTemplate
                    , 'name':(performer.name.length > 32 ? performer.name.substring(0,29)+"..." : performer.name)
                    , 'count':count
                    , 'filter':YAHOO.lang.isNull(this.cs) ? null : this.cs.getSelectionByID(this.cs.getState().selection).label
                });
                this.pag.subscribe('changeRequest', this.handlePagination, this, true);
                this.pag.render();
                this.updateContent();
            }
        }, this, true);
    }
    , "selectPerformer":function(extPerformerID) { // Keep call alive until everything is initialized.
        var tmpThis = this;
        setTimeout(function(){tmpThis.selectPerformer(extPerformerID);}, 500);
    }
    , "handlePagination":function(newState) { // Keep call alive until everything is initialized.
        this.updateContent(newState);
        this.pag.setState(newState);
    }
    , "getPageData":function(page) {
        var pageData = [];
        var pageRowBottom = (this.rowsPerPage * (page-1));
        var pageRowTop = (this.rowsPerPage * (page-1)) + this.rowsPerPage;
        if (pageRowTop > this.totalRecords) {
            pageRowTop = this.totalRecords;
        }
        for (var i = pageRowBottom; i < pageRowTop; i++) {
            pageData[i-pageRowBottom] = this.performerPerformances[i];
        }
        return pageData;
    }
    , "updateContent":function(newState) {
        var page = 1;
        var recordOffset = 0;
        var pagePerformances = null;
        if (YAHOO.lang.isObject(newState)) {
            page = newState.page;
            recordOffset = newState.recordOffset;
        }
        pagePerformances = this.getPageData(page);

        var pc = {};
        var dcs = this.data.collections;
        var csSel = YAHOO.lang.isNull(this.cs) ? "all" : this.cs.getState().selection;
        var ssSel = this.ss.getState().selection;
        var p = dcs[csSel][ssSel];
        for (var pKey in p) {
            var performers = p[pKey];
            for (var property in performers) {
                var performer = performers[property];
                var pps = this.data.performersPerformances[performer.type+"_"+performer.id];
                for (var ppKey in pps) {
                    var pp = pps[ppKey];
                    var ps = this.data.performances["id_"+pp];
                    for (var cKey in ps.collections) {
                        var type = ps.collections[cKey];
                        if (type == csSel) {
                            pc["id_"+pp] = type;
                        }
                    }
                }
            }
        }

        this.bodyEl.innerHTML = "";
        for (var key in pagePerformances) {
            var performanceID = pagePerformances[key];
            var performance = this.data.performances["id_"+performanceID];
            if (YAHOO.lang.isString(pc["id_"+performanceID])) {
                this.outputPerformance(performance);
            }
        }
        YAHOO.CMA.AjaxHeader.doCartOutput();
    }
    , "getPerformer":function(key){
        return this.data.performers[key];
    }
    , "outputPerformance":function(performance){
        var work = this.data.works[performance.work];
        var composer = this.data.composers[performance.composer];
        var album = this.data.albums[performance.album];

        if(YAHOO.lang.isObject(performance)) {
            var perfBlockEl = createElement("div", {
                "class":"performance"
            });
            var perfBodyEl = createElement("div", {
                "class":"details"
            });
            var perfPlayEl = createElement("div", {
                "class":"play"
            });
            var perfBuyEl = createElement("div", {
                "class":"buy"
            });
            var performersBlockEl = createElement("div", {
                "class":"performers"
            });
            var perfClearEl = createElement("div", {
                "class":"clearSm"
            });

            /* Album Output */
            if (album) {
                var link = createElement("a", {
                    "class":"album"
                    , "style":"width:"+album.imageWidth+"px;height:"+album.imageHeight+"px;"
                    , "title":"View Album Page"
                    , "href":"/album/"+album.upc+".html"
                });
                var img = createElement("img", {
                    "class":"ca caSm ca3D"
                    , "src":album.imagePath
                    , "width":album.imageWidth
                    , "height":album.imageHeight
                    , "alt":album.title
                    , "id":"p_" + performance.id + "_mo_" + album.upc
                });
                img.onmouseover = function(){qaa.show(this.id, '/ajax/qai/' + album.upc + '.json',null,'tl:tl', {x:-120,y:0})};
                link.appendChild(img);
                perfBodyEl.appendChild(link);
            }

            /* Composer Output */
            if (composer.show) {
                var head = createElement("h5");
                var name = createElement("a", {
                    "href":"/composer/" + composer.id + ".html"
                });
                var info = createElement("span", {"class":"inst"});
                name.appendChild(document.createTextNode(composer.name));
                head.appendChild(name);
                info.appendChild(document.createTextNode(" Composer"));
                head.appendChild(info);
                perfBodyEl.appendChild(head);
            }

            /* Work Output */
            if (work.show) {
                var head = createElement("h5");
                var name = createElement("a", {
                    "href":"/work/" + work.id + ".html"
                });
                var info = createElement("span", {"class":"inst"});
                name.appendChild(document.createTextNode(work.name));
                head.appendChild(name);
                info.appendChild(document.createTextNode(" Work"));
                head.appendChild(info);
                perfBodyEl.appendChild(head);
            }

            var primaryPerformerIDs = "";
            /* Primary Artist Output */
            if (performance.artist) {
                primaryPerformerIDs += performance.artist.id;
                if (!composer.show && !work.show) {
                    var p = this.getPerformer(performance.artist.id);
                    var head = createElement("h5");
                    var name = createElement("a", {
                        "href":"/artist/" + p.id + ".html"
                    });
                    var info = createElement("span", {"class":"inst"});
                    name.appendChild(document.createTextNode(p.name));
                    head.appendChild(name);
                    info.appendChild(document.createTextNode(" "+performance.artist.info));
                    head.appendChild(info);
                    perfBodyEl.appendChild(head);
                }
            }

            /* Primary Ensemble Output */
            if (performance.ensemble) {
                primaryPerformerIDs += performance.ensemble.id;
                if (!composer.show && !work.show) {
                    var p = this.getPerformer(performance.ensemble.id);
                    var head = createElement("h5");
                    var name = createElement("a", {
                        "href":"/ensemble/" + p.id + ".html"
                    });
                    var info = createElement("span", {"class":"inst"});
                    name.appendChild(document.createTextNode(p.name));
                    head.appendChild(name);
                    info.appendChild(document.createTextNode(" "+performance.ensemble.info));
                    head.appendChild(info);
                    perfBodyEl.appendChild(head);
                }
            }

            /* Primary Contributor Output */
            if (performance.contributor) {
                primaryPerformerIDs += performance.contributor.id;
                if (!composer.show && !work.show) {
                    var p = this.getPerformer(performance.contributor.id);
                    var head = createElement("h5");
                    var name = createElement("a", {
                        "href":"/contributor/" + p.id + ".html"
                    });
                    var info = createElement("span", {"class":"inst"});
                    name.appendChild(document.createTextNode(p.name));
                    head.appendChild(name);
                    info.appendChild(document.createTextNode(" "+performance.contributor.info));
                    head.appendChild(info);
                    perfBodyEl.appendChild(head);
                    var p = this.getPerformer(performance.contributor.id);
                    var head = createElement("h5");
                    var name = createElement("a", {
                        "href":"/contributor/" + p.id + ".html"
                    });
                    var info = createElement("span", {"class":"inst"});
                    name.appendChild(document.createTextNode(p.name));
                    head.appendChild(name);
                    info.appendChild(document.createTextNode(" "+performance.contributor.info));
                    head.appendChild(info);
                    perfBodyEl.appendChild(head);
                }
            }

            if (album && (YAHOO.lang.isString(album.label) || YAHOO.lang.isString(album.releaseDate))) {
                var head = createElement("h6");
                if (YAHOO.lang.isString(album.label)) {
                    head.appendChild(document.createTextNode(album.label));
                    head.appendChild(createElement("br"));
                }
                if (YAHOO.lang.isString(album.releaseDate)) {
                    head.appendChild(document.createTextNode("Rel. " + album.releaseDate));
                    head.appendChild(createElement("br"));
                }
                perfBodyEl.appendChild(head);
            }
            perfBlockEl.appendChild(perfBodyEl);

            if (performance.tracks > 1) {
                var para = document.createElement("p");
                var ftClass = "add"+performance.fileType.toUpperCase();
                if (performance.canDownload === true) { // SHOW DOWNLOAD VIEW
                    para.appendChild(document.createTextNode(performance.tracks+" track" + (performance.tracks==1?"":"s") + " for "+(performance.price == 0?"FREE":"$"+dollarFormat(performance.price))));
                    addItems = createElement("div", {
                        "class":"additemstodl"
                    });
                    link = createElement("a", {
                        "class":"add"
                        , "href":"javascript:void(0)"
                    });
                    link.appendChild(document.createTextNode("Download"));
                    addItems.appendChild(link);
                    perfBuyEl.appendChild(addItems);
                    perfBuyEl.appendChild(para);
                    link.onclick = function(){mload(12, performance.id, this);};
                } else if (performance.canBuy === true) {
                    if ((!album && YAHOO.lang.isNumber(performance.price)) || (YAHOO.lang.isNumber(album.displayPrice) && YAHOO.lang.isNumber(performance.price) && performance.price < album.displayPrice)) { // SHOW PERFORMANCE VIEW
                        para.appendChild(document.createTextNode(performance.tracks+" track" + (performance.tracks==1?"":"s") + " for"));

                        boldPrice = createElement("strong", {
                            "class":"price"
                        });
                        boldPrice.appendChild(document.createTextNode((performance.price == 0?"FREE":"$"+dollarFormat(performance.price))));
                        para.appendChild(boldPrice);

                        addItems = createElement("div", {
                            "class":"btnBuy" + performance.fileType.toUpperCase() + "Tracks"
                        });
                        link = createElement("a", {
                            "href":"javascript:void(0)"
                        });
                        mediaBuyImg = createElement("img", {
                            "src":"/images/b_buy_" + performance.fileType.toLowerCase() + "_tracks.gif"
                            , "alt":"Add to Cart"
                        });
                        link.appendChild(mediaBuyImg);
                        addItems.appendChild(link);
                        perfBuyEl.appendChild(addItems);
                        perfBuyEl.appendChild(para);
                        link.onclick = function(){this.blur(); apc(this, performance.id, work.id);};
                    } else if (
                            (album && YAHOO.lang.isNumber(album.displayPrice) && YAHOO.lang.isNumber(performance.price) && performance.price >= album.displayPrice)
                            || (album && YAHOO.lang.isNull(performance.price) && YAHOO.lang.isNumber(album.displayPrice))
                        ) { // SHOW ALBUM VIEW
                        addItems = createElement("div", {
                            "class":"btnBuy" + performance.fileType.toUpperCase() + "Album"
                        });
                        link = createElement("a", {
                            "id":"bt_a_"+album.upc
                            , "href":"javascript:void(0)"
                        });
                        mediaBuyImg = createElement("img", {
                            "src":"/images/b_buy_" + performance.fileType.toLowerCase() + "_album.gif"
                            , "alt":"Add to Cart"
                        });
                        link.appendChild(mediaBuyImg);
                        addItems.appendChild(link);
                        perfBuyEl.appendChild(addItems);
                        link.onclick = function(){this.blur(); aac(this, album.upc);};

                        var boldPrice = createElement("strong", {
                            "class":"price"
                        });
                        boldPrice.appendChild(document.createTextNode("$" + dollarFormat(album.displayPrice)));
                        para.appendChild(boldPrice);
                        if(YAHOO.lang.isNumber(album.displayPrice) && YAHOO.lang.isNumber(performance.price) && performance.price > album.displayPrice) { // SAVE $$ VIEW
                            var boldSavings = createElement("strong", {
                                "class":"msg"
                            });
                            boldSavings.appendChild(document.createTextNode("Album savings: $" + dollarFormat(performance.price - album.displayPrice)));
                            para.appendChild(boldSavings);
                            perfBuyEl.appendChild(para);
                        }
                    } else {
                        throw "Exception in display logic for performance header."
                    }
                }

                /* Can Play Output */
                if (performance.canPlay === true && performance.tracks > 1) {
                    var playLinks = createElement("div", {
                        "class":"link"
                    });
                    time = createElement("div", {
                        "class":"time"
                    });
                    play = createElement("div", {
                        "class":"btnPlay"
                    });
                    link = createElement("a", {
                        "href":"javascript:void(0)"
                    });
                    mediaPlayImg = createElement("img", {
                        "src":"/images/b_play.gif"
                        , "alt":"Play"
                    });
                    link.appendChild(mediaPlayImg);
                    play.appendChild(link);
                    time.appendChild(document.createTextNode(performance.playTime));
                    playLinks.appendChild(play);
                    var playlistDiv = createElement("div", {
                      "class":"btnPlaylist"
                    });
                    var playlist = createElement("a", {
                      "href":"javascript:void(0)"
                    });
                    var mediaPlaylistImg = createElement("img", {
                        "src":"/images/b_playlist.gif"
                        , "alt":"Add to Playlist"
                    });
                    playlist.appendChild(mediaPlaylistImg);
                    playlist.onclick = function() {
                        showPlaylists(playlist, "perf", performance.id);
                    };
                    playlistDiv.appendChild(playlist);
                    playLinks.appendChild(playlistDiv);
                    perfPlayEl.appendChild(playLinks);
                    perfPlayEl.appendChild(time);
                    play.onclick = function(){mload(3, performance.id);};
                }
            }

            var collectedInfo = {};
            for (var key in performance.performers) {
                var performancePerformer = performance.performers[key];
                var performer = this.getPerformer(performancePerformer.id);
                collectedInfo[performancePerformer.id] = (YAHOO.lang.isUndefined(collectedInfo[performer.id]) ? performancePerformer.info : collectedInfo[performer.id] + ", " + performancePerformer.info);
            }

            var firstPerformerDisplayed = false;
            for (var property in collectedInfo) {
                if ((composer.show && work.show) || primaryPerformerIDs.indexOf(property) == -1) {
                    if (firstPerformerDisplayed) {
                        performersBlockEl.appendChild(document.createTextNode(", "));
                    } else if (!composer.show && !work.show) {
                        performersBlockEl.appendChild(document.createTextNode("Other performers: "));
                    }
                    var performer = this.getPerformer(property);
                    var performerInfo = collectedInfo[property];

                    var info = createElement("span", {
                        "class":"inst"
                    });

                    var performerLinkInit = {};
                    if (primaryPerformerIDs.indexOf(property) != -1) {
                        performerLinkInit = {"class":"txtBold txtRed"};
                    }
                    var link = createElement("a", performerLinkInit);
                    if (performer.type == "a") {
                        link.href = "/artist/" + performer.id + ".html";
                    } else if (performer.type == "e") {
                        link.href = "/ensemble/" + performer.id + ".html";
                    } else if (performer.type == "c") {
                        link.href = "/contributor/" + performer.id + ".html";
                    } else {
                        link = null;
                    }
                    link.appendChild(document.createTextNode(performer.name));
                    info.appendChild(document.createTextNode(performerInfo));
                    performersBlockEl.appendChild(link);
                    performersBlockEl.appendChild(document.createTextNode(" "));
                    performersBlockEl.appendChild(info);
                    firstPerformerDisplayed = true;
                }
            }

            perfBlockEl.appendChild(perfBuyEl);
            perfBlockEl.appendChild(perfPlayEl);
            perfBlockEl.appendChild(perfClearEl);
            perfBlockEl.appendChild(performersBlockEl);
            this.bodyEl.appendChild(perfBlockEl);

            var perfDetailEl = createElement("div", {
                "id":"p_"+performance.id
                , "class":"tracks"
            });
            this.bodyEl.appendChild(perfDetailEl);


            if (performance.trackData) {
                perfDetailEl.innerHTML = performance.trackData;
            } else {
                this.loadPerformanceDetail(perfDetailEl, performance);
            }
        }
    }
    , "loadPerformanceDetail":function(content, performance) {
        content.innerHTML = '<div class="loading">' + YAHOO.CMA.loadImg + 'Loading info...</div>';

        YAHOO.util.Connect.asyncRequest('GET', '/performance/' + performance.id + '.html', {
            success: function(o) {
                if(YAHOO.lang.isObject(o.argument) && YAHOO.lang.isObject(o.argument.content)) {
                    o.argument.performance.trackData = o.responseText.replace(/%%uid%%/g, "").replace(/__/g, "_");
                    o.argument.content.innerHTML = o.argument.performance.trackData;
                }
                if (YAHOO.lang.isObject(YAHOO.CMA.AjaxHeader)) {
                    YAHOO.CMA.AjaxHeader.refresh();
                }
            },
            failure: function(o) {
                if (o.status > 0) { // Allow Reload via Link
                    o.argument.content.innerHTML = "";
                    var errorRetry = document.createElement("a");
                    errorRetry.href = "javascript:void(0);";
                    errorRetry.onclick = function(){o.argument.parentObj.loadPerformanceDetail(o.argument.performance);};
                    errorRetry.appendChild(document.createTextNode("Unable to retrieve performance details, please try again"));
                    var slArrow = document.createElement("img");
                    slArrow.className = 'arrow lm';
                    slArrow.src = '/images/b_red-arrow.gif';
                    errorRetry.appendChild(slArrow);
                    o.argument.content.appendChild(errorRetry);
                }
            },
            argument:{"content":content,"performance":performance,"parentObj":this}
        }, '');
    }
}
