(function(window) {
	"use strict";
	
	var
		initCallback = 'searchInit',
	
		// Service server (defaults to //directory.unl.edu)
		directoryServer = null,
		
		unlContext = '015236299699564929946:nk1siew10ie',
		
		transitionDelay = 400,
		
		inputSel = '#search_q',
		formSel = '#searchform form',
		resultSel = '.search-results',
		googleSel = '.google-results',
		
		wrapperMain = '#search_wrapper',
		wrapperWeb = '#search_results',
		wrapperDir = '#directory_results',
		
		dirResults = 'ppl_results',
		unlResults = 'unl_results',
		localResults = 'local_results';
	
	window[initCallback] = function() {
		delete window[initCallback];
		
		require(['jquery', 'analytics'], function($, analytics) {
			// Caching Class
			var Cache = function() {
				this.storage = {};
			};
			Cache.prototype.get = function(key) {
				return this.storage[key] || undefined;
			};
			Cache.prototype.save = function(key, value) {
				this.storage[key] = value;
				return this;
			};
			
			// Directory Controller Class
			var Directory = function(server, containerId) {
				var cntSel = '#' + containerId;
				
				this._server = server || '//directory.unl.edu';
				this._cache = new Cache();
				this._searchCanceled = false;
				this._viewState = 0;
				this._renderTo = cntSel;
				
				$(function() {
					$(cntSel).on('click', '.fn a', function() {
						if (this.target !== '_blank') {
							this.target = '_blank';
						}
					});
				});
			};
			Directory.prototype._render = function(data) {
				if (this._searchCanceled) {
					return;
				}
				
				$(this._renderTo)
					.html(data)
					.addClass('active');
				
				this._renderState(0);
			};
			Directory.prototype._renderState = function(duration) {
				var $innerRes = $('.results', $(this._renderTo)),
					depFilter = '.departments';
			
				$innerRes.slideUp(duration);
				if (this._viewState === 0) {
					$innerRes.not(depFilter).slideDown();
				} else {
					$innerRes.filter(depFilter).slideDown();
				}
			};
			Directory.prototype.cancelSearch = function() {
				this._searchCanceled = true;
				if (this._xhr) {
					this._xhr.abort();
				}
			};
			Directory.prototype.execute = function(q) {
				var cacheData = this._cache.get(q),
					self = this;
				
				this._searchCanceled = false;
				
				if (cacheData) {
					this._render(cacheData);
				} else {
					this._xhr = $.get(this._server + '/service.php?q=' + encodeURIComponent(q), function(data) {
						self._cache.save(q, data);
						self._render(data);
					});
				}
			};
			Directory.prototype.changeViewState = function(state) {
				if (this._viewState == state) {
					return;
				}
				
				this._viewState = state;
				this._renderState();
			};
			Directory.prototype.clearAllResults = function() {
				$(this._renderTo).empty();
			};
			
			var
				// query related
				query = '',
				firstQ = window['INITIAL_QUERY'],
				
				actCls = 'active',
				
				// CustomSearchControl instances and config
				unlSearch,
				localSearch,
				activeSearch,
				directorySearch,
				localContext = window['LOCAL_SEARCH_CONTEXT'],
				drawOp = new google.search.DrawOptions(),
				
				trackQuery = function(q) {
					var loc = window.location,
						qs = loc.search.replace(/(?:(\?)|&)q=[^&]*(?:&|$)/, '$1'),
						page = [
						    loc.pathname,
						    qs || '?',
						    (qs && qs != '?') ? '&' : '',
						    'q=',
						    encodeURIComponent(q)
				        ].join('');
					
					analytics.callTrackPageview(page);
					
					if (window.history.pushState) {
						window.history.pushState({query: q}, '', page);
					}
				},
				queryComplete = function(control) {
					$(control.root).closest(resultSel).addClass(actCls).end()
					.closest(googleSel).slideDown();
				},
				fullQuery = function(q, track) {
					if (track !== false) {
						trackQuery(q);
					}
					activeSearch.execute(q);
					directorySearch.execute(q);
					$(wrapperMain).fadeIn();
				},
				fullStop = function() {
					activeSearch.cancelSearch();
					directorySearch.cancelSearch();
					$(resultSel).removeClass(actCls);
					$(wrapperMain).fadeOut();
					setTimeout(function() {
						activeSearch.clearAllResults();
						directorySearch.clearAllResults();
					}, transitionDelay);
				},
				queryStart = function(control, searcher, q) {
					$(control.root).closest(googleSel).slideUp(0);
					if (q !== query) {
						trackQuery(q);
						directorySearch.execute(q);
					}
				};
			
			drawOp.enableSearchResultsOnly();
			
			unlSearch = activeSearch = new google.search.CustomSearchControl(unlContext);
			unlSearch.setResultSetSize(google.search.Search.FILTERED_CSE_RESULTSET);
			unlSearch.setSearchCompleteCallback(window, queryComplete);
			unlSearch.setSearchStartingCallback(window, queryStart);
			
			if (localContext) {
				localSearch = activeSearch = new google.search.CustomSearchControl(localContext);
				localSearch.setResultSetSize('small');
				localSearch.setSearchCompleteCallback(window, queryComplete);
				localSearch.setSearchStartingCallback(window, queryStart);
			}
			
			directorySearch = new Directory(directoryServer, dirResults);
			
			// Setup DOM on ready
			$(function() {
				var $q = $(inputSel),
					
					tabsSel = '.result-tab',
					selCls = 'selected',
					stateClsPfx = 'state-',
					
					$resTabs = $('.result-tab'),
					
					googleOrigin = /^https?:\/\/www\.google\.com$/,
					
					passiveQuery = function(q, track) {
						if (query === q) {
							return;
						}
						
						query = q;
						$q.val(q);
						
						if (q) {
							fullQuery(q, track);
						} else {
							fullStop();
						}
					};
				
				// draw the Google search controls
				unlSearch.draw(unlResults, drawOp);
				
				if (localContext) {
					localSearch.draw(localResults, drawOp);
				}
				
				// setup the tab-like result filters
				$('li:first-child', $resTabs).addClass(selCls);
				$($resTabs).on('click', 'li', function(e) {
					e.preventDefault(); 
					
					if ($(this).hasClass(selCls)) {
						return;
					}
						
					var i = $(this).index(), 
						j = $(this).siblings('.' + selCls).index(),
						$tab = $(this).closest(tabsSel),
						$par = $(this).parents('.results-group');
					
					$tab.removeClass(stateClsPfx + j);
					$tab.addClass(stateClsPfx + i);
					
					$(this).siblings().removeClass(selCls);
					$(this).addClass(selCls);
					
					if ($par.is(wrapperDir)) {
						directorySearch.changeViewState(i);
					} else if ($par.is(wrapperWeb)) {
						$(activeSearch.root).closest(googleSel).slideUp();
						if (i === 0) {
							activeSearch = localSearch;
						} else {
							activeSearch = unlSearch;
						}
						
						activeSearch.execute(query);
					}
				});
				
				// listen for the submit event
				$(formSel).submit(function(e) {
					e.preventDefault();
					
					var q = $.trim($q.val());
					passiveQuery(q);
				});
				
				// issue an inital query
				if (firstQ) {
					passiveQuery(firstQ, false);
				}
				
				// listen for message from parent frames
				$(window).on('message', function(e) {
					var oEvent = e.originalEvent, q;
					
					if (googleOrigin.test(oEvent.origin)) {
						return;
					}
					
					q = $.trim(oEvent.data);
					passiveQuery(q);
				});
				
				$(window).on('popstate', function(e) {
					var oEvent = e.originalEvent,
						q = firstQ || '';
					
					if (oEvent.state) {
						q = oEvent.state.query || '';
					}
					passiveQuery(q, false);
				});
			});
			
		});
	};
	
	window['pf_getUID'] = function() {
		return true;
	};
}(window));