/// <reference path="../ScriptReference/jquery-1.7.1-vsdoc.js"/>

/*
 * jQuery UI playersearchpanel
 *
 * Depends:
 *   jquery.ui.core.js
 *   jquery.ui.widget.js
 *   jquery.iscroll.js
 *   Mediasite.Player.Localization.js
 *
 */
(function ($) {
    $.widget("ui.playersearchpanel", {
        options: {
            presentation: null,
            ids: {
                header: 'ui-playersearchpanel-header',
                scroll: 'ui-playersearchpanel-scroll',
                scrollWrapper: 'ui-playersearchpanel-scroll-wrapper',
                searchWrapper: 'ui-playersearchpanel-search-wrapper',
                searchBar: 'ui-playersearchpanel-search-bar',
                searchField: 'ui-playersearchpanel-search-field',
                searchButton: 'ui-playersearchpanel-search-button',
                searchResults: 'ui-playersearchpanel-search-results',
                searchResultsWrapper: 'ui-playersearchpanel-search-results-wrapper',
                searchResultsScroll: 'ui-playersearchpanel-search-results-scroll',
                searchTotalResults: 'ui-playersearchpanel-search-total-results',
                modalMask: 'ui-playersearchpanel-modalmask',
                msgDialog: 'ui-playersearchpanel-dialog'
            },
            classes:
			{
			    panel: 'ui-playersearchpanel',
			    header: 'panel-header',
			    searchListItem: 'ui-playersearchpanel-search-list-item',
			    searchHighlight: 'ui-playersearchpanel-search-highlight',
			    searchResultType: 'ui-playersearchpanel-search-list-item-type',
			    searchListItemText: 'ui-playersearchpanel-search-list-item-text',
			    searchListItemTime: 'ui-playersearchpanel-search-list-item-time',
			    inputStretch: 'input-stretch',
			    header: 'panel-header',
			    modalMask: 'panel-modal-mask'
			},
            scrollbarColor: 'rgba(255,255,255,0.5)',
            javascriptResize: true,
            margin: 50,
            onCaptionClick: null,
            onSearch: null,
            disableCaptionDisplay: false,
            scrollbarColor: 'rgba(255,255,255,0.5)',
            searchResultMaxLength: 100   // Suggested maximum length (number of characters) for search result text
        },

        _setOption: function (key, value) {
            this.options[key] = value;
            this._bindCaptions();
            this._super("_setOption", key, value);
        },

        _create: function () {
            var self = this,
                o = self.options;

            this.element.addClass(o.classes.panel);
            var markup =
                        '<p id="' + o.ids.header + '" class="' + o.classes.header + '">' + Mediasite.Player.Localization.Search.Header + '</p>' +
						'<div id="' + o.ids.searchWrapper + '">' +
							'<div id="' + o.ids.searchBar + '">' +
								'<form><input type="text" name="name" id="' + o.ids.searchField + '" class="' + o.classes.inputStretch + '" />' +
								'<input id="' + o.ids.searchButton + '" type="submit" value="' + Mediasite.Player.Localization.Common.Search + '" /></form>' +
							'</div>' +
							'<div id="' + o.ids.searchTotalResults + '">' + Mediasite.Player.Localization.Search.Search + '</div>' +
							'<div id="' + o.ids.searchResultsWrapper + '">' +
								'<div id="' + o.ids.searchResultsScroll + '">' +
									'<ul id="' + o.ids.searchResults + '" /></ul>' +
								'</div>' +
							'</div>' +
						'</div>' +
				        '<div id="' + o.ids.modalMask + '" class="' + o.classes.modalMask + '">' +
					        '<div id="' + o.ids.msgDialog + '" class="' + o.classes.dialog + '">' +
						        '<div id="' + o.ids.dialogTitle + '" class="' + o.classes.dialogTitle + '"/>' +
						        '<div id="' + o.ids.dialogText + '" class="' + o.classes.dialogText + '"/>' +
						        '<button id="' + o.ids.dismissDialog + '" class="' + o.classes.dismissDialog + '">' + Mediasite.Player.Localization.Common.OK + '</button>' +
					        '</div>' +
				        '</div>';

            this.divMarkup = $(markup).appendTo(this.element);
            var doSearch = function doSearch(e) { e.preventDefault(); self._bindCaptions(); }

            $('#' + o.ids.searchButton).click(doSearch);
            $("form", this.element).submit(doSearch);

            $('#' + o.ids.modalMask, self.element).hide();
            $('#' + o.ids.dismissDialog).click(function () { $('#' + o.ids.modalMask, self.element).hide(); });

            $(window).resize(function () {
                self._updateLayout();
            });
        },

        destroy: function () {
            var o = this.options;

            this.element.removeClass(o.classes.panel);
            this.divMarkup.remove();
        },

        _init: function () {

            this._bindCaptions();
            this._updateLayout();
        },

        updateLayout: function () {
            /** Enable updating layout after showing panel; public method
            */

            this._updateLayout();

            /* FUTURE:
            // On open, focus on text box
            var $searchField = $('#' + this.options.ids.searchField);
            if ($searchField.is(":visible")) {
            $searchField.focus();
            }
            */
        },

        _updateLayout: function () {
            var self = this,
                o = self.options;
            var $self = self.element;
            if (!o.javascriptResize) return;

            // Set search box width
            $('.' + o.classes.inputStretch, $self).width($self.innerWidth() - $('#' + o.ids.searchButton).outerWidth() - o.margin);

            // -- Calculate and set height of scroll wrapper
            var $scrollWrapper = $("#" + o.ids.searchResultsWrapper);

            // Calculate height available for scroll wrapper
            var availableHeight = $self.height();

            var offsetFromParent = $scrollWrapper.offset().top;
            offsetFromParent -= $self.offset().top;
            offsetFromParent -= parseInt($self.css('padding-top'), 10) || 0;

            availableHeight -= offsetFromParent;

            // Allow for scroll wrapper's padding and margin
            availableHeight -= parseInt($scrollWrapper.css('margin-top'), 10) || 0;
            availableHeight -= parseInt($scrollWrapper.css('margin-bottom'), 10) || 0;
            availableHeight -= parseInt($scrollWrapper.css('padding-top'), 10) || 0;
            availableHeight -= parseInt($scrollWrapper.css('padding-bottom'), 10) || 0;

            // Set height of scroll wrapper
            $scrollWrapper.height(availableHeight);

            // Reset scrolling feature
            $('#' + o.ids.searchResultsScroll).iscroll({ scrollbarColor: o.scrollbarColor });
        },

        _formatsearchTerm: function (searchTerm) {
            var invalidChars = 0;
            var oldsearchTerm = searchTerm;

            //if first character is subset of { + , * , ? } then remove it
            if (searchTerm.charAt(0) == '+' || searchTerm.charAt(0) == '*' || searchTerm.charAt(0) == '?') {
                searchTerm = searchTerm.substring(1, searchTerm.length);
            }

            //if there contains any character in the subset { ( , ) , \, [, ] } remove it.
            //TODO: escape it/encode it in the future? may still cause tedious problems
            var patternRegExToMatch = /[()\[\]\\]/g;
            searchTerm = searchTerm.replace(patternRegExToMatch, '');
            if (oldsearchTerm != searchTerm && searchTerm == "") { searchTerm = oldsearchTerm; } //if ONLY invalids in this string, return it

            searchTerm = jQuery.trim(searchTerm);

            return searchTerm;
        },

        _containsInvalidChars: function (searchTerm) {
            var patternRegExToMatch = /[()\[\]\\]/g;
            return (searchTerm.charAt(0) == '+' || searchTerm.charAt(0) == '*' || searchTerm.charAt(0) == '?' || searchTerm != searchTerm.replace(patternRegExToMatch, ''));
        },

        _bindCaptions: function () {
            var self = this,
                o = self.options,
                p = o.presentation;

            var searchTerm = $("#" + o.ids.searchField).val();

            //search code

            var $ul = $('#' + o.ids.searchResults, self.element);

            searchTerm = this._formatsearchTerm(searchTerm);

            if (searchTerm != "") {
                $('li', $ul).remove();  // Remove previous search results

                if (this._containsInvalidChars(searchTerm)) {
                    // Search term is invalid, display "no results"
                    $('#' + o.ids.searchTotalResults).html(Mediasite.Player.Localization.Search.SearchTotal
                        .replaceholders(0, '<span class="' + o.classes.searchHighlight + '">' + searchTerm + '</span>'));
                    this._updateLayout();
                }
                else {
                    // Display "loading, please wait" message while results are being fetched
                    $('#' + o.ids.searchTotalResults).html(Mediasite.Player.Localization.Search.CurrentlySearching
                        .replaceholders('<span class="' + o.classes.searchHighlight + '">' + searchTerm + '</span>'));

                    // Initiate search
                    if (jQuery.isFunction(o.onSearch)) {
                        o.onSearch(searchTerm);
                    }
                }
            }
        },
        displayResults: function (searchTerm, results) {
            var self = this,
                o = self.options,
                p = o.presentation;
            var searchTermLower = searchTerm.toLowerCase();

            $('#' + o.ids.searchTotalResults).html(Mediasite.Player.Localization.Search.SearchTotal
                .replaceholders(results.length, '<span class="' + o.classes.searchHighlight + '">' + searchTerm + '</span>'));
            var $ul = $('#' + o.ids.searchResults, self.element);
            $ul.empty();

            if (results.length > 0) {
                var searchHitsText = Mediasite.Player.Localization.Search.SearchHitsInItem;
                if (!(searchHitsText && searchHitsText.length > 0)) {
                    searchHitsText = "%%0%%%";
                }

                // Verify and display search results
                for (var i in results) {
                    var item = results[i];
                    var itemText = item.Text;
                    var itemTime = item.Time;

                    // Format text
                    switch (item.Type) {
                        case Mediasite.TimingEventType.Caption:
                            if (this.options.disableCaptionDisplay) {
                                itemText = Mediasite.Player.Localization.Search.VoiceSearchResult;
                            } else if (itemText) {
                                var regex = new RegExp('(' + searchTerm + ')', 'gi');
                                var regexMatch = itemText.match(regex);

                                itemText = itemText.replace(regex, '<span class="' + o.classes.searchHighlight + '">$1</span>');
                                if (regexMatch && regexMatch.length > 1) {

                                    itemText += '<span class="' + o.classes.searchHighlight + '"> (' + searchHitsText.replaceholders(regexMatch.length) + ")</span>";
                                }
                            }
                            break;
                        case Mediasite.TimingEventType.SlideText:
                            itemText = Mediasite.Player.Localization.Search.SlideSearchResult;
                            break;
                    }

                    // Set result type text
                    var eventTypeText = '';
                    switch (item.Type) {
                        case Mediasite.TimingEventType.Caption:
                            eventTypeText = this.options.disableCaptionDisplay
                                ? Mediasite.Player.Localization.Search.VoiceResult
                                : Mediasite.Player.Localization.Search.CaptionResult;
                            break;
                        case Mediasite.TimingEventType.SlideText:
                            eventTypeText = Mediasite.Player.Localization.Search.OcrTextResult;
                            break;
                    }
                    
                    var resultsNumber = parseInt(i) + 1;
                    var time = Mediasite.Player.TimeHelper.Duration(itemTime);
                    var localizeTimeString = Mediasite.Player.Localization.Common.TimeAriaLabel.replaceholders(time.hours, time.minutes, time.seconds);
                    var ariaLabel = Mediasite.Player.Localization.Common.SearchResultsAriaLabel.replaceholders(resultsNumber, localizeTimeString, item.Text);
                    
                    // Set up search result control
                    var $item = $('<li class="' + o.classes.searchListItem + '" tabindex="0" role="button" aria-label="' + ariaLabel + '" ><div class="' + o.classes.searchListItemText + '">' + itemText + '</div>'
                                + '<span class="' + o.classes.searchResultType + '">' + eventTypeText + '</span>'
                                + '<span class="' + o.classes.searchListItemTime + '">' + Mediasite.Player.TimeHelper.getDisplayFromDuration(itemTime, true) + '</span>'
                                + '</li>');
                    if (o.onCaptionClick) {
                        $item.click({ onCaptionClick: o.onCaptionClick, itemTime: itemTime }, this._onCaptionClick);

                        $item.on('keyup', function (e) {
                            if (e.keyCode == 32 || e.keyCode == 13) {

                                e.stopPropagation();
                                e.preventDefault();

                                $(this).trigger("click", { onCaptionClick: o.onCaptionClick, itemTime: itemTime });
                            }
                        });
                    }

                    $ul.append($item);
                }
            }

            this._updateLayout();
        },
        _onCaptionClick: function onCaptionClick(evt) {
            evt.data.onCaptionClick(evt.data.itemTime);
        },
        displayError: function () {

            var self = this,
                o = self.options;

            var title = Mediasite.Player.Localization.Search.SearchFailureTitle;
            var message = Mediasite.Player.Localization.Search.SearchFailureDetail;

            self._overlayState(true);

            self._killDisplayMessage();
            var messageElement = $('<div id="' + o.ids.msgDialog + '"></div>');
            messageElement.appendTo(self.element);

            var messageOptions =
            {
                title: title,
                message: message,
                allowClose: false,
                dialogClass: 'panelMessage',
                width: o.msgDialogWidth ? o.msgDialogWidth : self.element.innerWidth() - 4,
                modal: false,
                close: function () {
                    self._overlayState(false);
                },
                position:
                {
                    my: "center top",
                    at: "center top+100",
                    of: self.element
                },
                appendTo: self.element
            };
            messageElement.messagedisplay(messageOptions);

            self._msgDialogInterval = setInterval(function () {
                if (!self.element.is(':visible')) {
                    self._overlayState(false);
                    clearInterval(self._msgDialogInterval);
                }
            }, 500);
        },

        _overlayState: function (show) {
            var self = this,
                   o = self.options;

            show ? $('#' + o.ids.modalMask, self.element).show() : $('#' + o.ids.modalMask, self.element).hide();
        },

        _killDisplayMessage: function () {

            var self = this,
                o = self.options;

            var messageElement = $('#' + o.ids.msgDialog, self.element);

            if (messageElement.length > 0) {
                if (messageElement.hasClass('messagedisplayinit')) {
                    messageElement.messagedisplay('destroy');
                }
                messageElement.remove();
            }
        }
    });
})(jQuery);
