﻿/// <reference path="../../combo.js" />
/// <reference path="Global.js" />
/// <reference path="Profile.js" />
/// <reference path="Rating.js" />
/// <reference path="WikiParser.js" />
/// <reference path="Edit.js" />

var Search =
{
	SelectedElement: null,
	CurrentRequest: null,
	SearchQuery: null,
	QueryToLoad: null,
	PageSize: 15,
	LoadPremiumOnScroll: false,
	QueryStateDelimeter: '/',
	CommunityResultsOffset: 1000000,
	LastCommunityResultIndex: -1,
	PremiumLastResultIndex: -1,
	PremiumArticleCount: 0,
	CommunityArticleCount: 0,
	FocusItem: null,

	InitHandlers: function()
	{
		var FocusEventDelay = (YAHOO.env.ua.webkit !== 0) ? 250 : 0;

		// Textbox replace
		var elSearchBox = new $EL('txtSearch');
		Search.SetSearchValue('');
		elSearchBox.on('contentReady', function()
		{
			if (this.get('value') == 'Find sermons...')
				this.addClass('searchBoxBlurred');
		});

		elSearchBox.on('focus', function()
		{
			Search.FocusItem = this;
			if (this.value == 'Find sermons...')
			{
				this.value = '';
				var el = new $EL('txtSearch');
				el.removeClass('searchBoxBlurred');
			}
			$D.setStyle('go', 'display', 'inline');
		}, $('txtSearch'), true);

		elSearchBox.on('blur', function()
		{
			Search.FocusItem = null;
			if (this.value === '')
			{
				var el = new $EL('txtSearch');
				el.addClass('searchBoxBlurred');
				this.value = 'Find sermons...';
			}
			setTimeout(function()
			{
				if (Search.FocusItem === null)
					$D.setStyle('go', 'display', 'none');
			}, FocusEventDelay);
		}, $('txtSearch'), true);

		$E.on('go', 'focus', function(e)
		{
			Search.FocusItem = this;
		}, $('go'), true);
		$E.on('go', 'mousedown', function(e)
		{
			Search.FocusItem = this;
		}, $('go'), true);
		$E.on('go', 'blur', function(e)
		{
			Search.FocusItem = null;
			setTimeout(function()
			{
				if (Search.FocusItem === null)
					$D.setStyle('go', 'display', 'none');
			}, FocusEventDelay);
		}, $('go'), true);
		$E.on('go', 'click', Search.OnFormSubmit);

		// Form handler
		var elSearchForm = new $EL('searchForm');
		elSearchForm.on('submit', function(e)
		{
			// Prevent the original submit event.
			$E.stopEvent(e);
			Search.UpdateSearch($('txtSearch').value);
		});

		// Infinite scrolling handler
		var elCommandsPane = new $('commandsPane');
		$E.on(elCommandsPane, 'scroll', Search.OnResultsScroll, elCommandsPane, true);

		var initialSearchResult = '';
		var initialQuery = '';

		var initialQueryResult = '';
		var bookmarkedState = $H.getBookmarkedState('q');
		if (bookmarkedState !== null)
		{
			var state = Search.ParseQueryState(bookmarkedState);

			var bookmarkedQuery = state.Query;
			if (bookmarkedQuery !== null)
				initialQuery = bookmarkedQuery;

			var bookmarkedSearchResult = state.SearchResult;
			if (bookmarkedSearchResult !== null)
				initialSearchResult = bookmarkedSearchResult;

			initialQueryResult = Search.ToQueryState(initialQuery, initialSearchResult);
		}

		$H.register('q', initialQueryResult, function(state) { Search.OnQueryStateChange(state); });
	},

	OnFormSubmit: function(e)
	{
		// Prevent the original submit event.
		$E.stopEvent(e);
		var elTxtSearch = $('txtSearch');
		var query = elTxtSearch.value;
		elTxtSearch.blur();
		$('go').blur();
		if (query != 'Find sermons...' && query !== '')
			Search.UpdateSearch(query);
	},

	OnQueryStateChange: function(state, doForegroundLoad)
	{
		var queryState = Search.ParseQueryState(state);
		var query = queryState.Query;
		var searchResult = queryState.SearchResult;

		Search.SetSearchValue(query);
		var pageSize = Search.PageSize;

		if (query != Search.SearchQuery)
		{
			if (query !== null && query !== '')
			{
				Global.SelectPane('resultsPane');
				Global.SelectTab('paneTabResults');
			}

			// If the selected result is not on the first page, or within 2 results of the bottom of a page, expand the page size
			if (searchResult >= Search.CommunityResultsOffset && (searchResult % Search.CommunityResultsOffset) > Search.PageSize - 2)
				pageSize = Math.ceil(((searchResult % Search.CommunityResultsOffset) + 2) / Search.PageSize) * Search.PageSize;

			Search.UpdateSearchCore(query, 0, pageSize, { 'q': state }, doForegroundLoad);
		}
		else
		{
			if (searchResult >= Search.CommunityResultsOffset && (searchResult % Search.CommunityResultsOffset) > ((Search.CommunityCurrentPage + 1) * Search.PageSize))
			{
				//Load more results
				pageSize = (Math.ceil((searchResult % Search.CommunityResultsOffset) / Search.PageSize) - 1) * Search.PageSize;
				Search.UpdateSearchCore(Search.SearchQuery, Search.LastCommunityResultIndex + 1, pageSize, { 'q': state }, doForegroundLoad);
			}
			else
			{
				// Select result
				Search.SetSelectedElement('Result' + searchResult);
				Search.ScrollToSelection('Result' + searchResult);
			}
		}
	},

	ScrollToSelection: function(result)
	{
		result = result || 'Result' + Search.ParseQueryState($H.getCurrentState('q')).SearchResult;

		var selected = new $EL(result);
		var rgSelection = $D.getRegion(result);

		if (rgSelection === null)
			return;

		var rgCommandsPane = $D.getRegion('commandsPane');

		if (rgCommandsPane.intersect(rgSelection) === null || rgCommandsPane.intersect(rgSelection).getArea() < rgSelection.getArea())
		{
			if (rgSelection.top > rgCommandsPane.top) // scroll down
				$('commandsPane').scrollTop += rgSelection.bottom - rgCommandsPane.bottom + 20;
			else // scroll up
				$('commandsPane').scrollTop -= rgCommandsPane.top - rgSelection.top + 20;
		}
	},

	SetSelectedElement: function(id)
	{
		if (Search.SelectedElement !== null)
			Search.SelectedElement.removeClass('selected');

		if (id !== null && id !== '')
		{
			var el = $(id);
			if (el !== null)
				el.blur();

			var sel = new $EL(id);
			sel.addClass('selected');
			Search.SelectedElement = sel;
		}
		else
		{
			Search.SelectedElement = null;
		}
	},

	// Click handler for search results.
	OnClickResult: function(searchResult, sermonID, states)
	{
		states = states || {};
		states['q'] = Search.ToQueryState(Search.SearchQuery, searchResult.substring(6, searchResult.length));
		if (Search.SelectedElement !== null)
			Search.SelectedElement.removeClass('selected');

		$(searchResult).blur();

		var sel = new $EL(searchResult);
		sel.addClass('selected');
		Search.SelectedElement = sel;
		Global.UpdateSermon(sermonID, states);
		Search.QueryToLoad = Search.SearchQuery;
	},

	SetSearchValue: function(text)
	{
		var elTextField = $('txtSearch');
		if (text === null || text === '')
		{
			$D.addClass(elTextField, 'searchBoxBlurred');
			elTextField.value = 'Find sermons...';
		}
		else
		{
			$D.removeClass(elTextField, 'searchBoxBlurred');
			elTextField.value = text;
		}
	},

	OnResultsScroll: function(e)
	{
		if (Search.CurrentRequest !== null)
			return;

		var rgCommandsPane = $D.getRegion('commandsPane');
		var elLastLink;
		var rgLastLink;

		if (Search.LoadPremiumOnScroll)
		{
			elLastLink = $('premiumFooter').previousSibling;
			rgLastLink = $D.getRegion(elLastLink);

			if (Search.PremiumLastResultIndex + 1 < Search.PremiumArticleCount && rgCommandsPane.intersect(rgLastLink) !== null)
			{
				Search.UpdateSearchCore(Search.SearchQuery, Search.PremiumLastResultIndex + 1, Search.PageSize, null, true, 1);
				$D.setStyle($$('a', 'premiumFooter', true), 'display', 'block');
			}
		}
		else
		{
			elLastLink = $D.getLastChild('results');
			rgLastLink = $D.getRegion(elLastLink);

			if (Search.LastCommunityResultIndex + 1 < Search.CommunityArticleCount && rgCommandsPane.intersect(rgLastLink) !== null)
				Search.UpdateSearchCore(Search.SearchQuery, Search.LastCommunityResultIndex + 1, Search.PageSize, null, true);
		}
	},

	UpdateSearch: function(encodedQuery)
	{
		Search.OnQueryStateChange(Search.ToQueryState(encodedQuery.replace('#$#', "'")), true);
	},

	// AJAX update search
	UpdateSearchCore: function(encodedQuery, start, count, states, doForegroundLoad, mode)
	{
		var query = encodedQuery.replace('#$#', "'");
		if (query === null || query === '' || (query == Search.SearchQuery && states !== null && states.q && Search.ParseQueryState(states.q).SearchResult < ((Search.CommunityCurrentPage + 1) * Search.PageSize)))
			return;

		Search.SetSearchValue(query);
		var el = new $EL('txtSearch');
		el.removeClass('searchBoxBlurred');

		if (Search.CurrentRequest !== null)
		{
			$C.abort(Search.CurrentRequest);
			Search.CurrentRequest = null;
		}

		if (start === null || start < 1)
		{
			start = 0;
			$('results').innerHTML = '';
		}

		if (mode === null || typeof (mode) == 'undefined')
			mode = (start === 0 ? 2 : 0);

		if (doForegroundLoad)
		{
			Global.SelectTab('paneTabResults');
			Global.SelectPane('resultsPane');
		}

		if ($D.hasClass('paneTabResults', 'current') && mode != 1)
			$D.setStyle('resultsLoading', 'display', 'block');

		Search.SearchQuery = query;
		var sRequestUrl = '/search.js?query='
			+ escape(query.replace('/', ' '))
			+ '&start=' + start
			+ '&count=' + count
			+ '&mode=' + mode;

		Global.GAPageTracker._trackPageview(sRequestUrl);

		Search.CurrentRequest = $C.asyncRequest('Get', sRequestUrl,
		{
			success: function(o)
			{
				var viewData = YAHOO.lang.JSON.parse(o.responseText);
				$D.setStyle('resultsLoading', 'display', 'none');
				Search.ProcessViewData(viewData, states, doForegroundLoad);
				Search.CurrentRequest = null;
				Search.OnResultsScroll();
			},
			failure: function(o)
			{
				Logos.Chrome.InfoBar.Show("infoBar", "Sorry, there was an error processing your request.", true, OnResize);
				$D.setStyle('resultsLoading', 'display', 'none');
				Search.CurrentRequest = null;
			}
		});

		if (mode === 0)
			$('commandsPane').scrollTop = $('commandsPane').scrollHeight;
	},
	ScrollWhenReady: null,
	ProcessViewData: function(viewData, states, doForegroundLoad)
	{
		states = states || {};

		if (viewData.ArticleCount > 0)
			Search.CommunityArticleCount = viewData.ArticleCount;

		if (viewData.PremiumArticleCount > 0)
			Search.PremiumArticleCount = viewData.PremiumArticleCount;

		var elResults = $('results');

		if (viewData.Start === 0)
		{
			elResults.innerHTML = '';
			Search.PremiumLastResultIndex = -1;
			Search.LastCommunityResultIndex = -1;
			Search.LoadPremiumOnScroll = false;
		}

		if (viewData.SearchHits.length === 0 && viewData.PremiumSearchHits.length === 0 && viewData.Start === 0)
			elResults.innerHTML += '<em>No search results found.</em>';

		Search.ScrollWhenReady = null;

		if (doForegroundLoad)
		{
			states['tab'] = 'paneTabResults';
			states['pane'] = 'resultsPane';
		}

		// There are premium hits we need to add to the results div
		if (viewData.Mode !== 0 && viewData.PremiumSearchHits.length > 0)
		{
			Search.PremiumLastResultIndex = viewData.PremiumLastResultIndex;

			if (viewData.Start === 0)
			{
				var remaining = viewData.PremiumArticleCount - Search.PremiumLastResultIndex - 1;

				elResults.innerHTML = '<div class="gray" style="margin-bottom:8px;"><img style="vertical-align:top;" src="/Content/Images/PremiumP16.png" /> <strong>Premium</strong> Contributions</div>';
				elResults.innerHTML += '<div id="premiumFooter" style="text-align:center;"><a href="#" class="standardLink">' + remaining + ' more premium results &#9660;</a><hr/></div>';

				$$('a', 'premiumFooter', true).onclick = function()
				{
					$$('a', 'premiumFooter', true).innerHTML = '<img src="' + Global.ContentServerPath + 'images/ajax-loader.gif"/>';
					Search.LoadPremiumOnScroll = true;
					Search.UpdateSearchCore(Search.SearchQuery, Search.PremiumLastResultIndex + 1, Search.PageSize, null, true, 1);
					return false;
				};
			}
			else
			{
				$D.setStyle($$('a', 'premiumFooter', true), 'display', 'none');
				if (Search.PremiumLastResultIndex + 1 >= Search.PremiumArticleCount)
					Search.LoadPremiumOnScroll = false;
			}

			Search.InsertSearchHits(viewData.PremiumSearchHits, viewData.PremiumLastResultIndex - viewData.PremiumSearchHits.length + 1, elResults, $('premiumFooter'), states, doForegroundLoad);

			if (remaining <= 0)
				$D.setStyle($$('a', 'premiumFooter', true), 'display', 'none');
		}

		// There are community hits we need to add to the results div
		if (viewData.Mode != 1 && viewData.SearchHits.length > 0)
		{
			Search.LastCommunityResultIndex = viewData.LastResultIndex;

			var overRideSelect = false;
			if (viewData.Start === 0)
			{
				var communityResultsHeader = document.createElement('div');
				communityResultsHeader.innerHTML = '&#x2756; <strong>Community</strong> Contributions';
				$D.setStyle(communityResultsHeader, 'margin-bottom', '8px');
				$D.addClass(communityResultsHeader, 'gray');
				elResults.appendChild(communityResultsHeader);

				if (viewData.PremiumSearchHits.length <= 0)
					overRideSelect = true;
			}

			Search.InsertSearchHits(viewData.SearchHits, viewData.LastResultIndex + Search.CommunityResultsOffset - viewData.SearchHits.length + 1, elResults, null, states, doForegroundLoad, overRideSelect);
		}

		if (Search.ScrollWhenReady)
			Search.ScrollWhenReady();
	},

	InsertSearchHits: function(searchHits, startId, elParent, elInsertBefore, states, doForegroundLoad, overRideSelect)
	{
		var newFragment = document.createDocumentFragment();
		var selectResult = null;
		var selectSermonId = null;
		var doSelect = false;

		var state = Search.ParseQueryState(states.q);
		var srState = state.SearchResult || '0';

		for (var ixHits = 0; ixHits < searchHits.length; ++ixHits)
			(function()
			{
				var hit = searchHits[ixHits];
				var nResult = (startId + ixHits);
				var elNewLink = document.createElement('a');
				elNewLink.id = 'Result' + nResult;
				elNewLink.href = '/submissions/' + hit.SermonID;

				elNewLink.onclick = function()
				{
					Search.OnClickResult('Result' + nResult, hit.SermonID);
					return false;
				};

				var elSpanTitle = document.createElement('span');
				elSpanTitle.className = 'title';
				elSpanTitle.innerHTML = hit.Title;
				new $EL(elSpanTitle).appendTo(elNewLink);
				elNewLink.innerHTML += ' | ';
				var elSpanPreview = document.createElement('span');
				elSpanPreview.className = 'preview';
				elSpanPreview.innerHTML = hit.Preview;
				new $EL(elSpanPreview).appendTo(elNewLink);

				newFragment.appendChild(elNewLink);

				if (srState !== null && srState !== '' && (nResult == Number(srState) || overRideSelect && nResult == Search.CommunityResultsOffset))
				{
					doSelect = true;
					selectResult = nResult;
					selectSermonId = hit.SermonID;
				}
			})();

		elParent.insertBefore(newFragment, elInsertBefore);

		if (doSelect)
		{
			if (doForegroundLoad)
			{
				Search.OnClickResult('Result' + selectResult, selectSermonId, states);
			}
			else
			{
				if (Search.SelectedElement !== null)
					Search.SelectedElement.removeClass('selected');

				var sel = new $EL('Result' + selectResult);
				sel.addClass('selected');
				Search.SelectedElement = sel;
			}
			Search.ScrollWhenReady = function() { Search.ScrollToSelection(); };
		}
	},

	ToQueryState: function(query, searchResult)
	{
		var state = query;
		if (searchResult !== null)
		{
			state = state + Search.QueryStateDelimeter + searchResult;
		}
		return state;
	},
	ParseQueryState: function(strState)
	{
		if (!strState)
			return { 'Query': '', 'SearchResult': '' };

		var arrParts = strState.split(Search.QueryStateDelimeter);
		var query = arrParts[0];
		var searchResult = arrParts.length > 1 ? Number(arrParts[1]) : null;
		return { 'Query': query, 'SearchResult': searchResult };
	},
	ShowSearchHelp: function()
	{
		var nWidth = Math.min($D.getViewportWidth() - 30, 600);
		var nHeight = Math.min($D.getViewportHeight() - 30, 600);

		if (!Search.SearchHelpPanel)
		{
			Search.SearchHelpPanel = new YAHOO.widget.Panel('searchHelpPanel', { fixedcenter: true,
				constraintoviewport: true,
				draggable: true,
				width: nWidth + 'px',
				height: nHeight + 'px',
				underlay: 'none'
			});
			var success = Search.SearchHelpPanel.render();

			Search.SearchHelpPanel.resizeTo = function(panelWidth, panelHeight)
			{
				$D.setStyle(this.innerElement, 'width', panelWidth);
				$D.setStyle(this.innerElement, 'height', panelHeight);
				this.resizeBody(panelWidth, panelHeight);
			};

			Search.SearchHelpPanel.resizeBody = function(panelWidth, panelHeight)
			{
				// QUIRKS FLAG, FOR BOX MODEL
				var IE_QUIRKS = (YAHOO.env.ua.ie && document.compatMode == 'BackCompat');

				// UNDERLAY/IFRAME SYNC REQUIRED
				var IE_SYNC = (YAHOO.env.ua.ie == 6 || (YAHOO.env.ua.ie == 7 && IE_QUIRKS));

				// PADDING USED FOR BODY ELEMENT (Hardcoded for example)
				var PANEL_BODY_PADDING = (10 * 2); // 10px top/bottom padding applied to Panel body element. The top/bottom border width is 0

				// TODO: width?

				var headerHeight = this.header ? this.header.offsetHeight : 0; // Content + Padding + Border
				var footerHeight = this.footer ? this.footer.offsetHeight : 0; // Content + Padding + Border

				var bodyHeight = (panelHeight - headerHeight - footerHeight);
				var bodyContentHeight = (IE_QUIRKS) ? bodyHeight : bodyHeight - PANEL_BODY_PADDING;

				$D.setStyle(this.body, 'height', bodyContentHeight + 'px');

				this.sizeUnderlay();
				if (IE_SYNC)
				{
					// Syncing the iframe can be expensive. Disable iframe if you
					// don't need it.
					this.syncIframe();
				}
			};
		}
		Search.SearchHelpPanel.resizeTo(nWidth, nHeight);
		Search.SearchHelpPanel.center();
		Search.SearchHelpPanel.show();
	}
};