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

/*
 * jQuery UI playerccsearchpanel
 *
 * Depends:
 *   jquery.ui.core.js
 *   jquery.ui.widget.js
 *   jquery.iscroll.js
 *   Mediasite.Player.Localization.js
 *
 */
(function ($) {
    $.widget("ui.playerccsearchpanel", {
        options: {
            presentation: null,
            ids: {
                scroll: 'ui-playerccsearchpanel-scroll',
                scrollWrapper: 'ui-playerccsearchpanel-scroll-wrapper',
                searchWrapper: 'ui-playerccsearchpanel-search-wrapper',
                searchBar: 'ui-playerccsearchpanel-search-bar',
                searchField: 'ui-playerccsearchpanel-search-field',
                searchButton: 'ui-playerccsearchpanel-search-button',
                searchResults: 'ui-playerccsearchpanel-search-results',
                searchResultsWrapper: 'ui-playerccsearchpanel-search-results-wrapper',
                searchResultsScroll: 'ui-playerccsearchpanel-search-results-scroll',
                searchTotalResults: 'ui-playerccsearchpanel-search-total-results'
            },
            classes:
			{
			    searchListItem: 'ui-playerccsearchpanel-search-list-item',
			    searchHighlight: 'ui-playerccsearchpanel-search-highlight',
			    roundedCorner: 'ui-corner-all',
			    ccsearchResultType: 'ui-playerccsearchpanel-search-list-item-type'
			},
            scrollbarColor: 'rgba(255,255,255,0.5)',
            margin: 50,
            onCaptionClick: null,
            notifier: null,
            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("ui-playerccsearchpanel");
            var markup =
                        '<p id="ui-playerccsearchpanel-header">' + Mediasite.Player.Localization.ccSearch.Header + '</p>' +
						'<div id="' + o.ids.searchWrapper + '">' +
							'<div id="' + o.ids.searchBar + '">' +
								'<form><input type="text" name="name" id="' + o.ids.searchField + '" class="input-stretch" />' +
								'<input id="' + o.ids.searchButton + '" type="submit" value="' + Mediasite.Player.Localization.Common.Search + '" /></form>' +
							'</div>' +
							'<div id="' + o.ids.searchTotalResults + '">' + Mediasite.Player.Localization.ccSearch.Search + '</div>' +
							'<div id="' + o.ids.searchResultsWrapper + '">' +
								'<div id="' + o.ids.searchResultsScroll + '">' +
									'<ul id="' + o.ids.searchResults + '" /></ul>' +
								'</div>' +
							'</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);


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

        destroy: function () {
            this.element.removeClass("ui-playerccsearchpanel");
            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;

            // Set search box width
            $('.input-stretch', $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('0 ' + Mediasite.Player.Localization.ccSearch.SearchTotal + ' "<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.ccSearch.CurrentlySearching
                        + ' "<span class="' + o.classes.searchHighlight + '">' + searchTerm + '</span>"');

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

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

            if (results.length > 0) {
                var regex = new RegExp('(' + searchTerm + ')', 'gi');

                var searchHitsText = Mediasite.Player.Localization.ccSearch.SearchHitsInItem;
                if (searchHitsText && searchHitsText.length > 0) {
                    searchHitsText = " " + searchHitsText;
                } else {
                    searchHitsText = "";
                }

                // 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 (itemText) {
                                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 + '"> (' + regexMatch.length + searchHitsText + ")</span>";
                                }
                            }
                            break;
                        case Mediasite.TimingEventType.OcrText:
                            itemText = Mediasite.Player.Localization.ccSearch.SlideSearchResult;
                            break;
                    }

                    // Set result type text
                    var eventTypeText = '';
                    switch (item.Type) {
                        case Mediasite.TimingEventType.Caption:
                            eventTypeText = Mediasite.Player.Localization.ccSearch.CaptionResult;
                            break;
                        case Mediasite.TimingEventType.OcrText:
                            eventTypeText = Mediasite.Player.Localization.ccSearch.OcrTextResult;
                            break;
                    }

                    // Set up search result control
                    var $item = $('<li class="' + o.classes.roundedCorner + '" ><div>' + itemText + '</div>'
                                + '<span class="' + o.classes.ccsearchResultType + '">' + eventTypeText + '</span>'
                                + Mediasite.Player.TimeHelper.getDisplayFromDuration(itemTime, true)
                                + '</li>');
                    if (o.onCaptionClick) {
                        $item.click({ onCaptionClick: o.onCaptionClick, itemTime: itemTime }, this._onCaptionClick);
                    }

                    $ul.append($item);
                }
            }

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