(function ($) {

AblePlayer.prototype.populateChaptersDiv = function() {

        var headingLevel, headingType, headingId, $chaptersHeading,
                $chaptersList;

        if ($('#' + this.chaptersDivLocation)) {
                this.$chaptersDiv = $('#' + this.chaptersDivLocation);
                this.$chaptersDiv.addClass('able-chapters-div');

                // add optional header
                if (this.chaptersTitle) {
                        headingLevel = this.getNextHeadingLevel(this.$chaptersDiv);
                        headingType = 'h' + headingLevel.toString();
                        headingId = this.mediaId + '-chapters-heading';
                        $chaptersHeading = $('<' + headingType + '>', {
                                'class': 'able-chapters-heading',
                                'id': headingId
                        }).text(this.chaptersTitle);
                        this.$chaptersDiv.append($chaptersHeading);
                }

                this.$chaptersNav = $('<nav>');
                if (this.chaptersTitle) {
                        this.$chaptersNav.attr('aria-labelledby',headingId);
                }
                else {
                        this.$chaptersNav.attr('aria-label',this.tt.chapters);
                }
                this.$chaptersDiv.append(this.$chaptersNav);

                // populate this.$chaptersNav with a list of chapters
                this.updateChaptersList();
        }
};

AblePlayer.prototype.updateChaptersList = function() {

        var thisObj, cues, $chaptersList, c, thisChapter,
                $chapterItem, $chapterButton, buttonId, hasDefault,
                getClickFunction, $clickedItem, $chaptersList, thisChapterIndex;

        thisObj = this;

        if (!this.$chaptersNav) {
                return false;
        }

        if (typeof this.useChapterTimes === 'undefined') {
                if (this.seekbarScope === 'chapter' && this.selectedChapters.cues.length) {
                        this.useChapterTimes = true;
                }
                else {
                        this.useChapterTimes = false;
                }
        }

        if (this.useChapterTimes) {
                cues = this.selectedChapters.cues;
        }
        else if (this.chapters.length >= 1) {
                cues = this.chapters[0].cues;
        }
        else {
                cues = [];
        }
        if (cues.length > 0) {
                $chaptersList = $('<ul>');
                for (c = 0; c < cues.length; c++) {
                        thisChapter = c;
                        $chapterItem = $('<li></li>');
                        $chapterButton = $('<button>',{
                                'type': 'button',
                                'val': thisChapter
                        }).text(this.flattenCueForCaption(cues[thisChapter]));

                        // add event listeners
                        getClickFunction = function (time) {
                                return function () {
                                        thisObj.seekTrigger = 'chapter';
                                        $clickedItem = $(this).closest('li');
                                        $chaptersList = $(this).closest('ul').find('li');
                                        thisChapterIndex = $chaptersList.index($clickedItem);
                                        $chaptersList.removeClass('able-current-chapter').attr('aria-selected','');
                                        $clickedItem.addClass('able-current-chapter').attr('aria-selected','true');
                                        // Need to updateChapter before seeking to it
                                        // Otherwise seekBar is redrawn with wrong chapterDuration and/or chapterTime
                                        thisObj.updateChapter(time);
                                        thisObj.seekTo(time);
                                }
                        };
                        $chapterButton.on('click',getClickFunction(cues[thisChapter].start)); // works with Enter too
                        $chapterButton.on('focus',function() {
                                $(this).closest('ul').find('li').removeClass('able-focus');
                                $(this).closest('li').addClass('able-focus');
                        });
                        $chapterItem.on('hover',function() {
                                $(this).closest('ul').find('li').removeClass('able-focus');
                                $(this).addClass('able-focus');
                        });
                        $chapterItem.on('mouseleave',function() {
                                $(this).removeClass('able-focus');
                        });
                        $chapterButton.on('blur',function() {
                                $(this).closest('li').removeClass('able-focus');
                        });

                        // put it all together
                        $chapterItem.append($chapterButton);
                        $chaptersList.append($chapterItem);
                        if (this.defaultChapter === cues[thisChapter].id) {
                                $chapterButton.attr('aria-selected','true').parent('li').addClass('able-current-chapter');
                                this.currentChapter = cues[thisChapter];
                                hasDefault = true;
                        }
                }
                if (!hasDefault) {
                        // select the first chapter
                        this.currentChapter = cues[0];
                        $chaptersList.find('button').first().attr('aria-selected','true')
                                .parent('li').addClass('able-current-chapter');
                }
                this.$chaptersNav.html($chaptersList);
        }
        return false;
};

AblePlayer.prototype.seekToChapter = function(chapterId) {

        // step through chapters looking for matching ID
        var i=0;
        while (i < this.selectedChapters.cues.length) {
                if (this.selectedChapters.cues[i].id == chapterId) {
                        // found the target chapter! Seek to it
                        this.seekTo(this.selectedChapters.cues[i].start);
                        this.updateChapter(this.selectedChapters.cues[i].start);
                        break;
                }
                i++;
        }
};

AblePlayer.prototype.updateChapter = function (now) {

        // as time-synced chapters change during playback, track changes in current chapter
        if (typeof this.selectedChapters === 'undefined') {
                return;
        }

        var chapters, i, thisChapterIndex, chapterLabel;

        chapters = this.selectedChapters.cues;
        for (i = 0; i < chapters.length; i++) {
                if ((chapters[i].start <= now) && (chapters[i].end > now)) {
                        thisChapterIndex = i;
                        break;
                }
        }
        if (typeof thisChapterIndex !== 'undefined') {
                if (this.currentChapter !== chapters[thisChapterIndex]) {
                        // this is a new chapter
                        this.currentChapter = chapters[thisChapterIndex];
                        if (this.useChapterTimes) {
                                this.chapterDuration = this.getChapterDuration();
                                this.seekIntervalCalculated = false; // will be recalculated in setSeekInterval()
                        }
                        if (typeof this.$chaptersDiv !== 'undefined') {
                                // chapters are listed in an external container
                                this.$chaptersDiv.find('ul').find('li').removeClass('able-current-chapter').attr('aria-selected','');
                                this.$chaptersDiv.find('ul').find('li').eq(thisChapterIndex)
                                        .addClass('able-current-chapter').attr('aria-selected','true');
                        }
                }
        }
};

AblePlayer.prototype.getChapterDuration = function () {

        // called if this.seekbarScope === 'chapter'
        // get duration of the current chapter

        var lastChapterIndex, chapterEnd;

        if (typeof this.currentChapter === 'undefined') {
                return 0;
        }
        if (typeof this.duration === 'undefined') {
                return 0;
        }
        lastChapterIndex = this.selectedChapters.cues.length-1;
        if (this.selectedChapters.cues[lastChapterIndex] == this.currentChapter) {
                // this is the last chapter
                if (this.currentChapter.end !== this.duration) {
                        // chapter ends before or after video ends, adjust chapter end to match video end
                        chapterEnd = this.duration;
                        this.currentChapter.end = this.duration;
                }
                else {
                        chapterEnd = this.currentChapter.end;
                }
        }
        else { // this is not the last chapter
                chapterEnd = this.currentChapter.end;
        }
        return chapterEnd - this.currentChapter.start;
};

AblePlayer.prototype.getChapterElapsed = function () {
        // called if this.seekbarScope === 'chapter'
        // get current elapsed time, relative to the current chapter duration

        if (typeof this.currentChapter === 'undefined') {
                return 0;
        }

        if (this.elapsed > this.currentChapter.start) {
                return this.elapsed - this.currentChapter.start;
        }
        else {
                return 0;
        }
};

AblePlayer.prototype.convertChapterTimeToVideoTime = function (chapterTime) {

        // chapterTime is the time within the current chapter
        // return the same time, relative to the entire video
        if (typeof this.currentChapter !== 'undefined') {
                var newTime = this.currentChapter.start + chapterTime;
                if (newTime > this.currentChapter.end) {
                        return this.currentChapter.end;
                }
                else {
                        return newTime;
                }
        }
        else {
                return chapterTime;
        }
};

AblePlayer.prototype.getChapterClickFunction = function (time) {

        // Returns the function used when a chapter is clicked in the chapters menu.
        var thisObj = this;
        return function () {
                thisObj.seekTrigger = 'chapter';
                thisObj.seekTo(time);
                // stopgap to prevent spacebar in Firefox from reopening popup
                // immediately after closing it (used in handleChapters())
                thisObj.hidingPopup = true;
                thisObj.chaptersPopup.hide();
                // Ensure stopgap gets cancelled if handleChapters() isn't called
                // e.g., if user triggered button with Enter or mouse click, not spacebar
                setTimeout(function() {
                        thisObj.hidingPopup = false;
                }, 100);
                thisObj.$chaptersButton.focus();
        }
};

})(jQuery);