var nhhs = angular.module('nhhs', ['ui.bootstrap', 'wu.masonry', 'localytics.directives', 'ngSanitize']);

var REMOVE_SESSION_ITEM_URL = '~/SessionService.asmx/RemoveSearchSessionItem',
   SET_SESSION_ITEM_URL = '~/SessionService.asmx/SetSearchSessionItem',
   GET_SESSION_ITEM_URL = '~/SessionService.asmx/GetSearchSessionItem',
   NHHS_SOCIETY_SITE_ID = 1;

nhhs.directive('ngEnter', function () {
     return function (scope, elem, attrs) {
          elem.on('keypress', function (event) {
               if (event.which === 13) {
                scope.event = event;
                   scope.$apply(attrs.ngEnter);

                   event.preventDefault();
               }
          });
     };
});

nhhs.directive('shareThis', function () {
    return {
        restrict: 'A',
        scope: { url: "@url"},
        link: function (scope, elem, attrs) {
            var stElem = elem[0];

            var buttonType = attrs.type;
            var text = attrs.text;
            var summary = attrs.summary;
            var image = attrs.image;

            createButtons = function () {
                if (typeof stWidget !== 'undefined') {
                    stWidget.addEntry({
                        "service": "sharethis",
                        "element": stElem,
                        "url": scope.url,
                        "type": buttonType ? buttonType : "chicklet",
                        "text": text,
                        "summary": summary,
                        "image": image
                    });
                }
            };
            
            createButtons();

            scope.$watch('url', function (newValue) {
              buttonType = attrs.type;
              text = attrs.text;
              summary = attrs.summary;
              image = attrs.image;

              var button = elem.find('.stButton');

                if(button)
                {
                  button.remove();
                  createButtons();
                }
            });
        }
    };
});

nhhs.directive('repeatDone', function(){
  return function(scope, elem, attrs){
    if(scope.$last){
      scope.$eval(attrs.repeatDone);
    };
  };
});

nhhs.directive('goBack', ['$window', function($window){
  return {
    restrict: 'AE',
    link: function(scope, elem, attrs){
      elem.on('click', function(){
        $window.history.back();
      });
    }
  };
}]);

nhhs.directive('imageonload', ['$rootScope', function($rootScope) {
    return {
        restrict: 'A',
        link: function(scope, element, attrs) {
            element.bind('load', function() {
                element.hide().stop(true, true).fadeIn();
                $rootScope.$broadcast('onImageLoaded', element.attr('gallery-name'));
            });
        }
    };
}]);

nhhs.directive('pdf', function(){
  return {
    restrict: 'E',
    link: function(scope, element, attrs)
    {
      var url = scope.$eval(attrs.src);

      var html = '<object type="application/pdf" data="' + url + '">';
      html += '<p>It appears you don\'t have Adobe Reader, PDF support in this web browser, or the file could not be found.'
      html += '<br /><a href="' + url + '" target="_blank">Click here to download the PDF.</a></p>'

      element.replaceWith(html);
    }
  };
});
var catalog = angular.module('catalog', ['ui.bootstrap', 'wu.masonry', 'localytics.directives', 'ngSanitize', 'ngRoute', 'nhhs']);

catalog.config(['$routeProvider', function ($routeProvider) {
    $routeProvider
        .when("/", {
            controller: 'collectionsSearchController',
            templateUrl: '/App/Templates/AngularCatalogView.aspx'
        });
}])
    .run(['$rootScope', '$location', 'siteIdService', function ($rootScope, $location, siteIdService) {
        var NHHS_SOCIETY_SITE_ID = 1;
        // register listener to watch route changes
        // Because there are links to the search pages in the menu, the path will sometimes be an empty string,
        // so set the path to the root '/'
        $rootScope.$on("$routeChangeStart", function () {
            if ($location.path() === '') {
                $location.path('/');
            }
        });
    }]);
nhhs.factory('requestFactory', ['$http', '$q', function ($http, $q) {
    
    var get = function (url, params, qs, headers) {
        if (qs && qs.length > 0) {
            url = url + '?';
            for (x in qs) {   
                url = url + qs[x].name + '=' + qs[x].value;
                if (x != (qs.length - 1)) {
                    url = url + '&';
                }
            }  
        }
        return $http({
            method: 'GET',
            url: url,
            headers: headers,
            params: params
        })
        .then(function (response) {
            if (typeof response.data === 'object' || typeof response.data === 'string') {
                if (response && response.data && response.data.exception) {
                    alert('There was an error processing your request.');
                }
                return response.data;
            } else {
                console.log(typeof response.data);
                return $q.reject(response.data);
            }
        }, function (response) {
            return $q.reject(response.data);
        });
    };

    var post = function (url, data, headers) {
        if (!headers) {
            headers = {};
        }

        //headers['Content-Type'] = 'application/x-www-form-urlencoded';
        
        return $http({
            method: 'POST',
            url: url,
            data: data,
            //transformRequest: function(obj) {
            //    var str = [];
            //    for(var p in obj)
            //        str.push(encodeURIComponent(p) + "=" + encodeURIComponent(obj[p]));
            //    return str.join("&");
            //},
            headers: headers
        })
        .then(function (response) {
            if (typeof response.data === 'object' || typeof response.data === 'string') {
                if (response && response.data && response.data.exception) {
                    alert('There was an error processing your request.');
                }
                return response.data;
            } else {
                console.log(typeof response.data)
                return $q.reject(response.data);
            }
        }, function (response) {
            return $q.reject(response.data)
        });
    };

    return {
        get: get,

        post: post
    }
}]);

nhhs.directive('imageGallery', ['$rootScope', 'autoScrollSvc', 'siteIdService', function($rootScope, autoScrollSvc, siteIdService){
    return {
        restrict: 'AE', // Attribute or Element
        scope: { images: '=images', hasTranscription: '=', showImageInfo: '=', galleryName: '@', isZoom: '=', transcriptUrl: '=' },
        templateUrl: '/App/Content/library/js/angular/views/imageGallery.html',
        link: function (scope, elem, attrs) {
            var NHHS_SOCIETY_SITE_ID = 1;
            var baseGifUrl = '/App/Content/library/img/icons/';
            var SOCIETY_DISCLAIMER_TEXT = 'This image is owned by the New Hampshire Historical Society.'
            var NETWORK_DISCLAIMER_TEXT = 'This image is owned by a participating organization of the New Hampshire History Network.'

            scope.currentIndex = 0;
            scope.imageNumber = 1;
            scope.currentImage = {};
            scope.currentRotationIndex = 0;
            scope.showLoading = true;

            var gif = siteIdService.siteId === NHHS_SOCIETY_SITE_ID ? 'society_loading.gif' : 'network_loading.gif'
            scope.loadingGifUrl = baseGifUrl + gif;
            var baseImgUrl = '/App/Classes/Helpers/GetAzureImage.ashx?guid=';

            scope.disclaimerText = siteIdService.siteId === NHHS_SOCIETY_SITE_ID ? SOCIETY_DISCLAIMER_TEXT : NETWORK_DISCLAIMER_TEXT;

            var rotations = [0, 90, 180, 270];

            var section = elem.find('section');
            var panzoomElem = {};


            var lrgImgElem = section.find('.large-image');
            var requestedImg = {};
            var downloadLink = {};
            var imageName = {};
            var menuItems = null;
            var scrollPosition = 0;
            var shouldScroll = false;

            imageScrollService = autoScrollSvc.getInstance();
            objZoomImgScrollService = autoScrollSvc.getInstance();
            transZoomImgScrollService = autoScrollSvc.getInstance();

            var setImageAndProperties = function (image) {
                lrgImgElem.hide();
                scope.showLoading = true;

                scope.currentImage = image;

                scope.imageProperties = [
		            { Name: "Color", Value: image.Color },
		            { Name: "Print Size", Value: image.ImageSize },
		            { Name: "Film Size", Value: image.FilmSize },
		            { Name: "Caption", Value: image.Caption },
                ];

                var imgSrc = baseImgUrl + scope.currentImage.NodeGUID;
                downloadLink.attr('href', imgSrc);
                requestedImg.attr('src', imgSrc);
                imageName.textContent = image.ImageName;

                scope.currentImage.url = imgSrc;

                if (shouldScroll) {

                    scrollPosition = scope.currentIndex * 64;

                    imageScrollService.scrollToPosition(scrollPosition);
                    objZoomImgScrollService.scrollToPosition(scrollPosition);
                    transZoomImgScrollService.scrollToPosition(scrollPosition);
                }

                scope.reset();
            };

            scope.changeImage = function (action) {
                scope.currentIndex += action;

                if (scope.currentIndex < 0) {
                    scope.currentIndex = scope.images.length - 1;
                }

                if (scope.currentIndex >= scope.images.length) {
                    scope.currentIndex = 0;
                }

                scope.imageNumber = scope.currentIndex + 1;

                var currentImage = scope.images[scope.currentIndex];

                setImageAndProperties(currentImage);
            };

            scope.setImage = function (index, image) {
                if (scope.currentIndex === index) {
                    return;
                }

                scope.currentIndex = index;

                scope.imageNumber = scope.currentIndex + 1;

                setImageAndProperties(image);
            };

            scope.imageNumberChanged = function () {
                if (isNaN(scope.imageNumber) || scope.imageNumber % 1 !== 0) {
                    scope.imageNumber = scope.currentIndex + 1;
                }
                else if (scope.imageNumber >= 1 && scope.imageNumber <= scope.images.length) {
                    scope.currentIndex = scope.imageNumber - 1;
                }
                else {
                    scope.imageNumber = scope.currentIndex + 1;
                }

                var currentImage = scope.images[scope.currentIndex];

                setImageAndProperties(currentImage);
            };

            scope.toggleTranscription = function (showTranscription) {
                $rootScope.$broadcast('onToggleTranscription', showTranscription);

                if (!showTranscription) {
                    scope.reset();
                }
            };

            scope.toggleZoom = function (showModal) {
                scope.showZoomModal = showModal;
                BodyCtrl.toggleScrollBars(showModal);

                if (!showModal) {
                    scope.reset();
                }
            };

            scope.reset = function () {
                if(!panzoomElem.panzoom)
                {
                    return;
                }
                panzoomElem.panzoom("reset");
                scope.currentRotationIndex = 0;
                scope.rotateClass = 'zero-degrees';
            };

            scope.rotate = function (action) {
                scope.currentRotationIndex += action;

                if (scope.currentRotationIndex >= rotations.length) {
                    scope.currentRotationIndex = 0;
                }

                if (scope.currentRotationIndex < 0) {
                    scope.currentRotationIndex = rotations.length - 1;
                }

                switch (scope.currentRotationIndex) {
                    case 0:
                        scope.rotateClass = 'zero-degrees';
                        break;
                    case 1:
                        scope.rotateClass = 'ninety-degrees';
                        break;
                    case 2:
                        scope.rotateClass = 'one-eithy-degrees';
                        break;
                    case 3:
                        scope.rotateClass = 'two-seventy-degrees';
                        break;
                    default:
                        scope.rotateClass = 'zero-degrees';
                        break;
                }
            };

            scope.$watch('images', function (newValue, oldValue) {
                if (newValue) {
                  var currentImage = scope.images[scope.currentIndex];

                  shouldScroll = scope.images.length > 5;

                  downloadLink = angular.element(document.querySelector('#downloadImageLink'));
                  requestedImg = angular.element(document.querySelector('#currentRequestedImage'));
                  imageName = document.querySelector('#imageName');

                  if (currentImage) {
                    setImageAndProperties(currentImage);
                  }

                  panzoomElem = scope.hasTranscription ? elem.find('.transcription-panzoom') : elem.find('.zoom-panzoom');

                  panzoomElem.panzoom({
                      $zoomIn: $(".zoom-in"),
                      $zoomOut: $(".zoom-out"),
                      startTransform: scope.hasTranscription ? 'matrix(1, 0, 0, 1, 0, 0)' : 'matrix(0.5, 0, 0, 0.5, 0, -30)',
                      minScale: 0.25,
                      increment: .25
                  });

                  menuItems = angular.element(document.querySelector('.non-zoom-items'));

                  var zoomMenuItems = angular.element(document.querySelector('.zoom-items'));
                  var transMenuItems = angular.element(document.querySelector('.transcript-zoom-items'));

                  imageScrollService.config({ duration: 300, ease: 'easeInOutCubic', container: menuItems });
                  objZoomImgScrollService.config({ duration: 300, ease: 'easeInOutCubic', container: zoomMenuItems });
                  transZoomImgScrollService.config({ duration: 300, ease: 'easeInOutCubic', container: transMenuItems });
                }
            });

            scope.$on('onImageLoaded', function (event, name) {
                if (scope.galleryName !== '' && name === scope.galleryName) {
                    scope.showLoading = false;
                    scope.$apply();
                }
            });
            scope.$on('onGalleryToggleTranscription', function (event, showTranscription) {
                scope.showTranscript = showTranscription;
            });
        }
    };
}]);
nhhs.directive('transcription', ['detectPdfReaderSvc', 'memberSvc', 'siteIdService', function(detectPdfReaderSvc, memberSvc, siteIdService){
	return{
		restrict: 'AE',
		scope: {hasTranscription: '=', transcriptUrl: '='},
		link: function(scope){
			var NHHS_SOCIETY_SITE_ID = 1;

			if(!scope.hasTranscription || (!memberSvc.isValid && siteIdService.siteId === NHHS_SOCIETY_SITE_ID)){
				scope.templateUrl = '';
				return;
			}

			scope.templateUrl = '/App/Content/library/js/angular/views/otherTranscription.html';

			if(detectPdfReaderSvc.isMobile())
			{
				scope.templateUrl = '/App/Content/library/js/angular/views/mobileNoTranscription.html';
			}

			if(!detectPdfReaderSvc.isAcrobatInstalled())
			{
				scope.templateUrl = '/App/Content/library/js/angular/views/noPdfViewer.html';
			}

			if(detectPdfReaderSvc.browserName === 'ie')
			{
				scope.templateUrl = '/App/Content/library/js/angular/views/ieTranscription.html';
			}
		},
		template: "<div ng-include='templateUrl'></div>"
	};
}]);
catalog.directive('searchCategories', ['eventHandlerSvc', function(eventHandlerSvc){
	return {
		restrict: 'AE',
		scope: {},
		templateUrl: '/App/Content/library/js/angular/views/searchCategories.html',
		link: function(scope, elem, attrs){

			scope.categoryCounts = [0, 0, 0, 0, 0, 0];
            scope.categories = [
                { className: 'All', displayText: 'All Records', count: scope.categoryCounts[0] },
                { className: 'Common.Biography', displayText: 'Biographies', count: scope.categoryCounts[1] },
                { className: 'Common.Archive', displayText: 'Archives', count: scope.categoryCounts[2] },
                { className: 'Common.Book', displayText: 'Books', count: scope.categoryCounts[3] },
                { className: 'Common.Object', displayText: 'Objects', count: scope.categoryCounts[4] },
                { className: 'Common.Photo', displayText: 'Photographs', count: scope.categoryCounts[5] }
            ];

            scope.showCategoryCounts = false;
            scope.className = '';

            scope.categorySearch = function(cat){
            	if(scope.className === cat.className){
            		return;
            	}

            	scope.className = cat.className;
        		eventHandlerSvc.onCategoryChanged(cat);
            }

            scope.$on('onUpdateCategories', function(event, args){
            	
        		// Set the scope object to the returned data if any, if not set them all to zero
                scope.categoryCounts = args.categoryCounts ? args.categoryCounts : [0, 0, 0, 0, 0, 0];
                // Show the category numbers
                scope.showCategoryCounts = args.showCategoryCounts;

                angular.forEach(scope.categories, function (cat, index) {
                    cat.count = scope.categoryCounts[index];
                });
            });

            scope.$on('onClassNameChanged', function(event, args){
            	scope.className = args.className;
            	scope.showCategoryCounts = args.showCategoryCounts;
            });

            scope.$on('onSearchReset', function(){
                scope.showCategoryCounts = false;
                scope.className = '';
            });
		}
	}
}]);
catalog.directive('searchBox', ['filterSvc', 'eventHandlerSvc', function(filterSvc, eventHandlerSvc){
	return{
		restrict: 'AE',
		scope: {isNetwork: '='},
		templateUrl: '/App/Content/library/js/angular/views/searchBox.html',
		link: function(scope, elem, attrs){		
			scope.advSearch = false;
			var precisionOptions = filterSvc.precisionOptions();

			function initialize(){
				scope.facets = filterSvc.facets();

	            scope.searchLink = 'advancedSearch';
	            scope.searchToggleText = 'Advanced Search';

	            scope.checkValidation = false;

	            scope.incFilters = [];
	            scope.exFilters = [];

	            scope.andOrExact = precisionOptions.optionsArray; 

				// Object to hold basic search variables
	            scope.basicSearchModel = {
	                Precision: scope.andOrExact[0],
	                Filter: { facet: 'Everything', value: ''},
	                MustHaveImage: scope.isNetwork === 'True'
	            };

	            // Object to hold advanced search variables
	            scope.advSearchModel = {
	                IncPrecision: scope.andOrExact[0],
	                ExPrecision: scope.andOrExact[0],
	                MustHaveImage: scope.isNetwork === 'True',
	                IncludeTranscriptions: false,
	                Year: '',
	                YearA: '',
	                YearB: ''
	            };

	            scope.isFirstSearch = true;
			};	

			function canSearch() {
            /// <summary>Determines whether or not the user submitted a valid search</summary>
            /// <returns type="bool">A bool as to whether the search should be performed or not</returns>

	            return (!scope.advSearch && scope.basicSearchForm.$valid) || (scope.advSearch && scope.advSearchForm.$valid)
	        };

			scope.toggleSearch = function () {
	            $('#advancedSearch').slideToggle('medium');
	            $('#basicSearch').slideToggle('medium');

	            scope.advSearch = !scope.advSearch;
	            scope.searchToggleText = scope.advSearch ? 'Hide Advanced Search' : 'Advanced Search';

	            if (scope.incFilters.length === 0) {
	                scope.incFilters.push(filterSvc.newFilter());
	            }

	            if (scope.exFilters.length === 0) {
	                scope.exFilters.push(filterSvc.newFilter());
	            }
	        };

	        scope.addFilter = function (type) {
	        	if(type === 'include'){
	        		scope.incFilters.push(filterSvc.newFilter());
	        	}
        		else{
        			scope.exFilters.push(filterSvc.newFilter());
        		}
		    };

		    scope.removeFilter = function (index, type) {
		    	if(type === 'include'){
		    		scope.incFilters.splice(index, 1);
		    	}
		        else{
		        	scope.exFilters.splice(index, 1);
		        }
		    };	

		    scope.onSearchTextEntered = function(){
		        scope.checkValidation = true;
		    };

		    scope.reset = function (event) {
		        /// <summary>Triggered when clicking on the reset button.</summary>
		        /// <param name="event" type="object">The event that caused this function to be called</param>
		        /// <returns type="bool">A bool as to whether the event should continue</returns>        
		        scope.checkValidation = false;

		        initialize();

		        // If advanced search is open, initializing will change the toggle link text, so change it back
		        if (scope.advSearch) {
		            scope.searchToggleText = 'Hide Advanced Search';
		        }

		        if (scope.incFilters.length === 0) {
		            scope.incFilters.push(filterSvc.newFilter());
		        }

		        if (scope.exFilters.length === 0) {
		            scope.exFilters.push(filterSvc.newFilter());
		        }

	        	eventHandlerSvc.onSearchReset();

	        	if(event){
                	event.preventDefault();
                }

		    };

		    scope.search = function(event){
		    	var searchParams = {

		    		incFilters: scope.advSearch ? scope.incFilters : [{ facet: scope.basicSearchModel.Filter.facet, value: scope.basicSearchModel.Filter.value }],
                    exFilters: scope.advSearch ? scope.exFilters : [],
                    incCriteria: scope.advSearch ? scope.advSearchModel.IncPrecision.short : scope.basicSearchModel.Precision.short,
                    exCriteria: scope.advSearch ? scope.advSearchModel.ExPrecision.short : '',
                    mustHaveImage: scope.basicSearchModel.MustHaveImage || scope.advSearchModel.MustHaveImage,
                    includeTranscriptions: scope.advSearchModel.IncludeTranscriptions,
                    yearA: scope.advSearchModel.Year !== '' ? scope.advSearchModel.Year : scope.advSearchModel.YearA !== '' ? scope.advSearchModel.YearA : '0',
                    yearB: scope.advSearchModel.YearB !== '' ? scope.advSearchModel.YearB : '0',
                    advSearch: scope.advSearch
                };

                if(canSearch())
                {
                	eventHandlerSvc.onSearch(searchParams);
                }		    	

                if(event){
                	event.preventDefault();
                }
		    	
		    };

		    initialize();

		    scope.$on('onCategoryChanged', function(event, args){		    	
		    	var searchParams = {

		    		incFilters: scope.advSearch ? scope.incFilters : [{ facet: scope.basicSearchModel.Filter.facet, value: scope.basicSearchModel.Filter.value }],
                    exFilters: scope.advSearch ? scope.exFilters : [],
                    incCriteria: scope.advSearch ? scope.advSearchModel.IncPrecision.short : scope.basicSearchModel.Precision.short,
                    exCriteria: scope.advSearch ? scope.advSearchModel.ExPrecision.short : '',
                    mustHaveImage: scope.basicSearchModel.MustHaveImage || scope.advSearchModel.MustHaveImage,
                    includeTranscriptions: scope.advSearchModel.IncludeTranscriptions,
                    yearA: scope.advSearchModel.Year !== '' ? scope.advSearchModel.Year : scope.advSearchModel.YearA !== '' ? scope.advSearchModel.YearA : '0',
                    yearB: scope.advSearchModel.YearB !== '' ? scope.advSearchModel.YearB : '0',
                    advSearch: scope.advSearch
                };

                eventHandlerSvc.onCategorySearch(args.category, searchParams);

		    });

		    scope.$on('onInitSavedSearch', function(event, args){
		    	var sp = args.searchParams;		    	

		    	scope.basicSearchModel.Precision = precisionOptions.getOptionByName(sp.incCriteria);
                scope.basicSearchModel.Filter = (sp.incFilters.length > 0 && !sp.advSearch) ? sp.incFilters[0] : {facet: 'Everything', value: ''};
                scope.basicSearchModel.MustHaveImage = sp.mustHaveImage;

	            //Object to hold advanced search variables
	            scope.advSearchModel = {
	                IncPrecision: precisionOptions.getOptionByName(sp.incCriteria),
	                ExPrecision: scope.andOrExact[0],
	                MustHaveImage: sp.mustHaveImage,
	                IncludeTranscriptions: sp.includeTranscriptions,
	                Year: sp.yearA !== 0 ? sp.yearA : '',
	                YearA: sp.yearA !== 0 ? sp.yearA : '',
	                YearB: sp.yearB !== 0 ? sp.yearB : ''
	            }

	            scope.incFilters = sp.incFilters;
	            scope.exFilters = sp.exFilters;

	            if (sp.advSearch && !scope.advSearch) {
	            	scope.toggleSearch();	                
	            }
	            else{
            		scope.searchToggleText = 'Advanced Search';
	            }
		    });

		    scope.$on('onInitialize', function() {
		    	scope.reset();
		    });
		}
	};
}]);
catalog.directive('searchHeader', ['filterSvc', 'eventHandlerSvc', 'storageSvc', 'urlSvc', 'sharedSearchSvc', function(filterSvc, eventHandlerSvc, storageSvc, urlSvc, sharedSearchSvc){
	return {
		restrict: 'AE',
		scope: {isNetwork: '=', userId: '='},
		templateUrl: '/App/Content/library/js/angular/views/searchHeader.html',
		link: function(scope, elem, attrs){

            scope.sortOptions = filterSvc.sortOptions();
            scope.rppOptions = filterSvc.rppOptions();
            scope.showSortOptions = false;
            scope.view = 'gallery'

            scope.optionsModel = {
                SortBy: scope.sortOptions[0],
                SortDesc: false,
                Rpp: scope.rppOptions[0]
            };

            scope.toggleView = function (view) {
		        if (scope.view !== view) {
		            // Set the scope view, and the search model view
		            scope.view = view;

		            eventHandlerSvc.onToggleView(view);
		        }
		    };

		    scope.mobileSortOptionChanged = function(newSortOption)
		    {
		        if(scope.optionsModel.SortBy === newSortOption)
		        {
		            return;
		        }
		        scope.optionsModel.SortBy = newSortOption;

		        scope.sortOptionChanged();
		    }

		    scope.sortOptionChanged = function () {
		        scope.optionsModel.SortDesc = scope.optionsModel.SortBy === 'Date Desc';

		        eventHandlerSvc.onSortRppChanged(scope.optionsModel);
		    };

		    scope.rppOptionChanged = function () {

		        eventHandlerSvc.onSortRppChanged(scope.optionsModel);
		    };

		    scope.setSaveThisSession = function (event) {
		        var clicked = angular.element(event.currentTarget);

		        var saveThisModel = {
		            guid: clicked.attr('data-guid'),
		            opt: clicked.attr('data-option'),
		            objId: clicked.attr('data-object-id'),
		            objectName: clicked.attr('data-object-name'),
		            heading: clicked.attr('data-heading'),
		            id: clicked.attr('id')
		        }

		        storageSvc.setServerSessionData(urlSvc.resolveUrl(SET_SESSION_ITEM_URL), 'showSaveThis', true);
		        storageSvc.setServerSessionData(urlSvc.resolveUrl(SET_SESSION_ITEM_URL), 'saveThisModel', angular.toJson(saveThisModel));
		    };

            scope.$on('onSearch', function(){
            	scope.showSortOptions = true;
            	scope.isSavedSearch = false;
            });

            scope.$on('onCategorySearch', function(){
            	scope.showSortOptions = true;
            	scope.isSavedSearch = false;
            });

            scope.$on('onSearchReset', function(){
            	scope.showSortOptions = false;
            	scope.view = 'gallery';
            	SearchViewCtrl.galleryViewClick();

            	scope.optionsModel = {
	                SortBy: scope.sortOptions[0],
	                SortDesc: false,
	                Rpp: scope.rppOptions[0]
	            };

	            scope.isSavedSearch = false;
            });

            scope.$on('onViewChanged', function(event, args){
            	scope.view = args.view;

            	if(scope.view === 'gallery'){
            		SearchViewCtrl.galleryViewClick();
            	}
            	else
            	{
            		SearchViewCtrl.listViewClick();
            	}
            });

            scope.$on('onInitSavedSearch', function(event, args){
            	var sp = args.searchParams;

            	scope.optionsModel.SortBy = sp.sortField.sortOption;
                scope.optionsModel.SortDesc = sp.sortField.sortDesc;
	            scope.optionsModel.Rpp = sp.rpp;

	            scope.showSortOptions = true;
            });

            scope.$on('onCheckSavedSearch', function(event, args){
        		var checkSavedSearch = sharedSearchSvc.checkSavedSearch(args.searchId, scope.userId);
        		checkSavedSearch.then(function(data){
        			scope.isSavedSearch = data.isSavedSearch;
        		});
            });

            eventHandlerSvc.onHeaderLoaded(scope.optionsModel);
		}
	}
}]);
catalog.directive('printEmailShare', ['shareThisHelperSvc', 'siteIdService', 'urlSvc', function(shareThisHelperSvc, siteIdService, urlSvc){
	return{
		restrict: 'AE',
		scope: {},
		templateUrl: '/App/Content/library/js/angular/views/printEmailShare.html',
		link: function(scope, elem, attrs){
			var NETWORK_SHARE_THIS_IMAGE_URL = '~/App/Content/library/img/new-hampshire-history-network-icon.jpg',
        		SOCIETY_SHARE_THIS_IMAGE_URL = '~/App/Content/library/img/nhhs-share.jpg',
        		NHHS_SOCIETY_SITE_ID = 1;

			scope.documentName = shareThisHelperSvc.documentName;
			scope.siteName = shareThisHelperSvc.siteName;
			scope.stUrl = '';
			scope.sharedImageUrl = '';
			scope.showShareThis = false;

			var sharedImageUrl = siteIdService.siteId === NHHS_SOCIETY_SITE_ID ? SOCIETY_SHARE_THIS_IMAGE_URL : NETWORK_SHARE_THIS_IMAGE_URL;
            scope.sharedImageUrl = urlSvc.resolveUrl(sharedImageUrl);

            scope.$on('onSearchIdChanged', function(event, args){
            	scope.stUrl = urlSvc.getUrlWithoutHash() + "#/?id=" + args.searchId;
            });

            scope.$on('onSearchReset', function(){
            	scope.showShareThis = false;
            });

            scope.$on('onShowShareThis', function(event, args){
            	scope.showShareThis = args.showShareThis;
            });
		}
	}
}]);
nhhs.service('Item', ['requestFactory', function (requestFactory) {
    var get = function (url, params, qs, headers) {
        return requestFactory
            .get(url, params, qs, headers)
            .then(function (response) {
                return response;
            });
    };


    var post = function(url, data, headers){
    	return requestFactory
    		.post(url, data, headers)
    		.then(function(response){
    			return response;
    		});
    };

    var mock = function () {
        var data = [
            {
	            "img": "/library/img/collections/collection-1.jpg",
	            "heading": "Platter",
	            "dateRange": "1835-1850",
	            "objectId": "1973.015.147",
	            "shortDescription": "Lorem ipsum dolor sit amet, consectetuer adipiscing elit. Aenean commodo ligula eget dolor. Aenean massa. Cum sociis natoque penatibus et magnis dis parturient montes, nascetur ridiculus mus. Donec quam felis, ultricies nec, pellentesque eu, pretium."
	        },
	        {
	            "img": "/library/img/collections/collection-2.jpg",
	            "heading": "Drawing",
	            "dateRange": "1835-1850",
	            "objectId": "1973.015.147",
	            "shortDescription": "Lorem ipsum dolor sit amet, consectetuer adipiscing elit. Aenean commodo ligula eget dolor. Aenean massa. Cum sociis natoque penatibus et magnis dis parturient montes, nascetur ridiculus mus. Donec quam felis, ultricies nec, pellentesque eu, pretium",
	        },
	        {
	            "img": "/library/img/collections/collection-3.jpg",
	            "heading": "Engraving",
	            "dateRange": "1835-1850",
	            "objectId": "1973.015.147",
	            "shortDescription": "Lorem ipsum dolor sit amet, consectetuer adipiscing elit. Aenean commodo ligula eget dolor. Aenean massa. Cum sociis natoque penatibus et magnis dis parturient montes, nascetur ridiculus mus. Donec quam felis, ultricies nec, pellentesque eu, pretium",
	        },
	        {
	            "img": "/library/img/collections/collection-4.jpg",
	            "heading": "Pattern. Shoe Sole",
	            "dateRange": "1835-1850",
	            "objectId": "1973.015.147",
	            "shortDescription": "Lorem ipsum dolor sit amet, consectetuer adipiscing elit. Aenean commodo ligula eget dolor. Aenean massa. Cum sociis natoque penatibus et magnis dis parturient montes, nascetur ridiculus mus. Donec quam felis, ultricies nec, pellentesque eu, pretium",
	        },
	        {
	            "img": "/library/img/collections/collection-5.jpg",
	            "heading": "Platter",
	            "dateRange": "1835-1850",
	            "objectId": "1973.015.147",
	            "shortDescription": "Lorem ipsum dolor sit amet, consectetuer adipiscing elit. Aenean commodo ligula eget dolor. Aenean massa. Cum sociis natoque penatibus et magnis dis parturient montes, nascetur ridiculus mus. Donec quam felis, ultricies nec, pellentesque eu, pretium",
	        },
	        {
	            "img": "/library/img/collections/collection-6.jpg",
	            "heading": "Drawing",
	            "dateRange": "1835-1850",
	            "objectId": "1973.015.147",
	            "shortDescription": "Lorem ipsum dolor sit amet, consectetuer adipiscing elit. Aenean commodo ligula eget dolor. Aenean massa. Cum sociis natoque penatibus et magnis dis parturient montes, nascetur ridiculus mus. Donec quam felis, ultricies nec, pellentesque eu, pretium",
	        },
	        {
	            "img": "/library/img/collections/collection-7.jpg",
	            "heading": "Engraving",
	            "dateRange": "1835-1850",
	            "objectId": "1973.015.147",
	            "shortDescription": "Lorem ipsum dolor sit amet, consectetuer adipiscing elit. Aenean commodo ligula eget dolor. Aenean massa. Cum sociis natoque penatibus et magnis dis parturient montes, nascetur ridiculus mus. Donec quam felis, ultricies nec, pellentesque eu, pretium",
	        }
        ]
        return data;
    };

    return {
        get: get,
    	post: post,
        mock: mock
    }
}]);
nhhs.service('timelineItem', ['requestFactory', function (requestFactory) {
    var get = function (url, params, qs, headers) {
        return requestFactory
            .get(url, params, qs, headers)
            .then(function (response) {
                return response;
            });
    };


    var post = function(url, data, headers){
    	return requestFactory
    		.post(url, data, headers)
    		.then(function(response){
    			return response;
    		});
    };

    var mock = function () {
        var data = [
            {
	            "img": ["/library/img/collections/collection-1.jpg"],
	            "heading": "Platter",
	            "dateRange": "1835-1850",
	            "objectId": "1973.015.141",
	            "shortDescription": "Lorem ipsum dolor sit amet, consectetuer adipiscing elit. Aenean commodo ligula eget dolor. Aenean massa. Cum sociis natoque penatibus et magnis dis parturient montes, nascetur ridiculus mus. Donec quam felis, ultricies nec, pellentesque eu, pretium."
	        },
	        {
	            "img": ["/library/img/collections/collection-2.jpg","/library/img/collections/collection-1.jpg","/library/img/collections/collection-4.jpg"],
	            "heading": "Drawing",
	            "dateRange": "1835-1850",
	            "objectId": "1973.015.142",
	            "shortDescription": "Lorem ipsum dolor sit amet, consectetuer adipiscing elit. Aenean commodo ligula eget dolor. Aenean massa. Cum sociis natoque penatibus et magnis dis parturient montes, nascetur ridiculus mus. Donec quam felis, ultricies nec, pellentesque eu, pretium",
	        },
	        {
	            "img": ["/library/img/collections/collection-3.jpg"],
	            "heading": "Engraving",
	            "dateRange": "1835-1850",
	            "objectId": "1973.015.143",
	            "shortDescription": "Lorem ipsum dolor sit amet, consectetuer adipiscing elit. Aenean commodo ligula eget dolor. Aenean massa. Cum sociis natoque penatibus et magnis dis parturient montes, nascetur ridiculus mus. Donec quam felis, ultricies nec, pellentesque eu, pretium",
	        },
	        {
	            "img": ["/library/img/collections/collection-4.jpg","/library/img/collections/collection-5.jpg"],
	            "heading": "Pattern. Shoe Sole",
	            "dateRange": "1835-1850",
	            "objectId": "1973.015.144",
	            "shortDescription": "Lorem ipsum dolor sit amet, consectetuer adipiscing elit. Aenean commodo ligula eget dolor. Aenean massa. Cum sociis natoque penatibus et magnis dis parturient montes, nascetur ridiculus mus. Donec quam felis, ultricies nec, pellentesque eu, pretium",
	        },
	        {
	            "img": ["/library/img/collections/collection-5.jpg"],
	            "heading": "Platter 2",
	            "dateRange": "1835-1850",
	            "objectId": "1973.015.145",
	            "shortDescription": "Lorem ipsum dolor sit amet, consectetuer adipiscing elit. Aenean commodo ligula eget dolor. Aenean massa. Cum sociis natoque penatibus et magnis dis parturient montes, nascetur ridiculus mus. Donec quam felis, ultricies nec, pellentesque eu, pretium",
	        },
	        {
	            "img": ["/library/img/collections/collection-6.jpg"],
	            "heading": "Drawing 2",
	            "dateRange": "1835-1850",
	            "objectId": "1973.015.146",
	            "shortDescription": "Lorem ipsum dolor sit amet, consectetuer adipiscing elit. Aenean commodo ligula eget dolor. Aenean massa. Cum sociis natoque penatibus et magnis dis parturient montes, nascetur ridiculus mus. Donec quam felis, ultricies nec, pellentesque eu, pretium",
	        },
	        {
	            "img": ["/library/img/collections/collection-7.jpg"],
	            "heading": "Engraving 2",
	            "dateRange": "1835-1850",
	            "objectId": "1973.015.147",
	            "shortDescription": "Lorem ipsum dolor sit amet, consectetuer adipiscing elit. Aenean commodo ligula eget dolor. Aenean massa. Cum sociis natoque penatibus et magnis dis parturient montes, nascetur ridiculus mus. Donec quam felis, ultricies nec, pellentesque eu, pretium",
	        }
        ]
        return data;
    };
    var singleMock = function () {
        var data = {
		    "img": ["/library/img/collections/collection-2.jpg","/library/img/collections/collection-1.jpg","/library/img/collections/collection-4.jpg"],
		    "bigImg": ["/library/img/bigImg.png","/library/img/bigImg.png","/library/img/bigImg.png"],
		    "heading": "Platter",
		    "fullDate": "June 05, 1845 AT 11:30 AM",
		    "objectId": "1973.015.147",
		    "tags": ['BLACKS & SLAVERY','GOVERNMENT & POLITICS','MERRIMACK VALLEY'],
		    "description": "Lorem ipsum dolor sit amet, consectetuer adipiscing elit. Aenean commodo ligula eget dolor. Aenean massa. Cum sociis natoque penatibus et magnis dis parturient montes, nascetur ridiculus mus. Donec quam felis, ultricies nec, pellentesque eu, pretium."
		}
		return data;
    };

    return {
        get: get,
    	post: post,
        mock: mock,
        singleMock: singleMock
    }
}]);
nhhs.service('filterSvc', ['requestFactory', 'siteIdService', function (requestFactory, siteIdService) {
    var NHHS_SOCIETY_SITE_ID = 1;
    var newFilter = function () {
        return {
            facet: 'Everything',
            value: ''
        };
    };

    var facets = function () {
        return siteIdService.siteId === NHHS_SOCIETY_SITE_ID 
            ? [
                'Everything',
                'Title',
                //'Author',
                'Author / Creator',
                'Subjects',
                //'Description',
                //'Item Number',
                //'Accession Number',
                //'Reference Number',
                //'Collection Name',
                //'Object Name',
                //'Material',
                //'Language',
                //'Publisher',
                'Place',
                'People',
                //'Dimensions',
                //'Provenance',
                //'Credit Line'
            ]
            : [
                'Everything',
                'Title',
                //'Author',
                'Author / Creator',
                'Subjects',
                //'Description',
                //'Item Number',
                //'Accession Number',
                //'Reference Number',
                //'Collection Name',
                //'Object Name',
                //'Material',
                //'Language',
                //'Publisher',
                'Place',
                'People',
                //'Dimensions',
                //'Provenance',
                //'Credit Line'
                'Participating Organization'
            ];
            
    };

    var sortOptions = function () {
        return [
            'Relevance',
            'Date Asc',
            'Date Desc',
            'Title'
        ];
    };

    var rppOptions = function () {
        return [
            12,
            24,
            36,
            48,
            60,
            72,
            84,
            96
        ];
    };

    var precisionOptions = function(){
        var and = {
            value: true,
            short: 'All',
            full: 'All words'
        };

        var or = {
            value: false,
            short: 'Any',
            full: 'Any word'
        };

        var exact = {
            value: false,
            short: 'Exact',
            full: 'Exact words or phrase'
        };

        var optionsArray = [
            and, exact, or
        ];

        var options = {
            and:{
            value: true,
            short: 'All',
            full: 'All words'
            },
            exact:{
                value: false,
                short: 'Exact',
                full: 'Exact words or phrase'
            },
            or:{
                value: false,
                short: 'Any',
                full: 'Any word'
            }
        }; 

        var getOptionByName = function(optionName){
            for (var i = optionsArray.length - 1; i >= 0; i--) {
                if(optionsArray[i].short === optionName){
                    return optionsArray[i]
                }
            };
        };

        return {
            optionsArray: optionsArray,
            options: options,
            getOptionByName: getOptionByName
        }
    }

    return {
        newFilter: newFilter,
        facets: facets,
        sortOptions: sortOptions,
        rppOptions: rppOptions,
        precisionOptions: precisionOptions
    }
}]);
nhhs.service('storageSvc', ['$window', 'Item', function ($window, Item) {
    
    var setLocalData = function (key, value) {
        $window.localStorage.setItem(key, value);
    };

    var getLocalData = function (key) {
        return $window.localStorage.getItem(key);
    };

    var removeLocalData = function (key) {
        $window.localStorage.removeItem(key);
    };

    var clearLocalData = function () {
        $window.localStorage.clear();
    };

    var setClientSessionData = function (key, value) {
        $window.sessionStorage.setItem(key, value);
    };

    var setServerSessionData = function (url, key, value) {
        return Item.post(url, angular.toJson({ searchModel: { key: key, value: value } }));
    };

    var getClientSessionData = function (url, key) {
        return $window.sessionStorage.getItem(key);
    };

    var getServerSessionData = function (url, key) {

        return Item.post(url, { key: key })
        .then(function (result) {
            return result.d;
        });
    };

    var removeClientSessionData = function (key) {
        $window.sessionStorage.removeItem(key);
    };

    var removeServerSessionData = function (url, key) {
        Item.post(url, angular.toJson({key: key}));
    };

    var clearSessionData = function () {
        $window.sessionStorage.clear();
    };

    return {
        setLocalData: setLocalData,
        getLocalData: getLocalData,
        removeLocalData: removeLocalData,
        clearLocalData: clearLocalData,
        setClientSessionData: setClientSessionData,
        setServerSessionData: setServerSessionData,
        getClientSessionData: getClientSessionData,
        getServerSessionData: getServerSessionData,
        removeClientSessionData: removeClientSessionData,
        removeServerSessionData: removeServerSessionData,
        clearSessionData: clearSessionData
    };
}]);
nhhs.service('sharedSearchSvc', ['Item', function (Item) {
    searchId = '';
    searchModel = {};
    getSearchModel = function (searchId) {
        return Item
            .get('/api/sharedsearch/GetSearchModel', { searchId: searchId })
            .then(function (response) {
                return response;
            });
    };

    saveSearch = function (event, service) {
        Item.post('/api/sharedsearch/SaveSearchModel', {searchId: searchId, searchModel: searchModel.searchParams}, { 'Content-Type': 'application/json' });
    };

    var checkSavedSearch = function (searchId, userId){
        return Item.post('/api/sharedsearch/CheckIsSavedSearch', {searchId: searchId, userId: userId}, { 'Content-Type': 'application/json' })
                    .then(function (response){
                        return response;
                    });
    }

    if (typeof stLight !== 'undefined') {
        stLight.subscribe("click", saveSearch);
    }
    EmailThisCtrl.subscribe(saveSearch);

    return {
        setSearchId: function (newId) {
            searchId = newId;
        },
        setSearchModel: function (model) {
            searchModel = model;
        },
        getSearchModel: getSearchModel,
        checkSavedSearch: checkSavedSearch
    };
}]);
nhhs.service('imageGallerySvc', function(){
	var setImage = function(event){
		PhotoGalleryCtrl.onItemClick(event);
	};

	var nextImage = function(){
		PhotoGalleryCtrl.onClickNextImage();

		return PhotoGalleryCtrl.currentIndex();
	};

	var prevImage = function(){
		PhotoGalleryCtrl.onClickPreviousImage();

		return PhotoGalleryCtrl.currentIndex();
	};

	var hideGallery = function(){
		PhotoGalleryCtrl.hideGallery();
	}

	var changeNumber = function(newNumber){
		PhotoGalleryCtrl.displayItem(newNumber - 1);
	}

	return {
		setImage: setImage,
		nextImage: nextImage,
		prevImage: prevImage,
		changeNumber: changeNumber,
		hideGallery: hideGallery
	};
});
nhhs.service('urlSvc', ['$location', '$window', function($location, $window){
	var resolveUrl = function(relativeUrl){
		if(!relativeUrl)
		{
			return '';
		}
		relativeUrl = relativeUrl.replace('~', '');

		if (!$window.location.origin) {
		  $window.location.origin = window.location.protocol + "//" + window.location.hostname + (window.location.port ? ':' + window.location.port: '');
		}
		return $window.location.origin + relativeUrl;
	};

	var pathName = function(){
		return $window.location.pathname;
	};

	var absUrl = function(){

		return $location.absUrl();
	};

	var redirect = function(newUrl){
		$window.location.href = newUrl;
	};

	var open = function(newUrl, target){
		$window.open(newUrl, target);
	};

	var getUrlWithoutHash = function(){
		var absUrl = $location.absUrl();
		var hash = $window.location.hash;

		return absUrl.replace(hash, '');
	};

	var getSearchValue = function(propName){

		// this page was accessed with a url parameter, check to see if the assettype variable is in the url
		if($location.search().hasOwnProperty(propName))
		{			 
			return $location.search()[propName];		
		}
		else{
			return null;
		}
	};

	var addSearchValue = function(propName, value){
		$location.search(propName, value);
	};

	var clearSearchValue = function(propName){
		$location.search(propName, null);
	};

	var clearSearch = function(){
		$location.search({});
	};

	var checkSearchExists = function(){
		return !angular.equals({}, $location.search());
	};

    //Returns query strings for search results (?view=list&as=false&pi=0&cn=All&rpp=12&sort=Relevance&sdesc=false&inc=All&exc=&mhi=false&ya=0&yb=0&rf=All%20Records&it=false&icf=Everything;test)
	var getObjectDetailLink = function (baseURL, includeFilter, searchText) {
	    return (baseURL + '#/?view=list&as=false&pi=0&cn=All&rpp=12&sort=Relevance&sdesc=false&inc=All&exc=&mhi=false&ya=0&yb=0&rf=All%20Records&it=false&icf=' + includeFilter + ';' + searchText);
	}

	var setUrlParams = function(searchParams){
		// Update the url for deep linking, which allows the back button of the browser to return to a previous search
		$location.search('view', searchParams.view);
        $location.search('as', searchParams.advSearch);
        $location.search('pi', searchParams.pageIndex);
        $location.search('cn', searchParams.className);
        $location.search('rpp', searchParams.rpp);
        $location.search('sort', searchParams.sortField.sortOption);
        $location.search('sdesc', searchParams.sortField.sortDesc);
        $location.search('inc', searchParams.incCriteria);
        $location.search('exc', searchParams.exCriteria);
        $location.search('mhi', searchParams.mustHaveImage);
        $location.search('ya', searchParams.yearA);
        $location.search('yb', searchParams.yearB);
        $location.search('rf', searchParams.resultsFor);
        $location.search('it', searchParams.includeTranscriptions);
        $location.search('npi', searchParams.nodeParentId);

        var icf = [];
        angular.forEach(searchParams.incFilters, function(filter, index){
            icf.push(filter.facet + ";" + filter.value);
        });

        $location.search('icf', icf);

        var ecf = [];

        angular.forEach(searchParams.exFilters, function(filter, index){
            ecf.push(filter.facet + ";" + filter.value);
        });

        $location.search('ecf', ecf);

        clearSearchValue('id');
	};

	var getReturnToSearchParams = function (searchParams) {
	    /// <summary>
	    /// Creates a string to use for the return to search button to return the user to the collections search with the proper parameters
	    /// </summary>
	    
	    var params = '';
	    if (!searchParams) {
	        return params;
	    }

	    params += ('view=' + searchParams.view);
	    params += ('&as=' + searchParams.advSearch);
	    params += ('&pi=' + searchParams.pageIndex);
	    params += ('&cn=' + searchParams.className);
	    params += ('&rpp=' + searchParams.rpp);
	    params += ('&sort=' + searchParams.sortField.sortOption);
	    params += ('&sdesc=' + searchParams.sortField.sortDesc);
	    params += ('&inc=' + searchParams.incCriteria);
	    params += ('&exc=' + searchParams.exCriteria);
	    params += ('&mhi=' + searchParams.mustHaveImage);
	    params += ('&ya=' + searchParams.yearA);
	    params += ('&yb=' + searchParams.yearB);
	    params += ('&rf=' + searchParams.resultsFor);
	    params += searchParams.includeTranscriptions ? ('&it=' + searchParams.includeTranscriptions) : '';
	    params += searchParams.nodeParentId ? ('&npi=' + searchParams.nodeParentId) : '';

	    angular.forEach(searchParams.incFilters, function (filter) {
	        params += ('&icf=' + (filter.facet + ";" + filter.value));
	    });

	    angular.forEach(searchParams.exFilters, function (filter) {
	        params += ('&ecf=' + (filter.facet + ";" + filter.value));
	    });

	    return params;
	}

	var getSearchModelFromLocation = function(){
		var params = {};

		params.advSearch = $location.search().as === true;
		params.pageIndex = parseInt($location.search().pi);
		params.className = $location.search().cn;
		params.rpp = parseInt($location.search().rpp);
		params.sortField = {sortOption: $location.search().sort, sortDesc: $location.search().sdesc};
		params.incCriteria = $location.search().inc;
		params.exCriteria = $location.search().exc;
		params.mustHaveImage = $location.search().mhi;
		params.yearA = $location.search().ya;
		params.yearB = $location.search().yb;
		params.view = $location.search().view;
		params.resultsFor = $location.search().rf;
		params.includeTranscriptions = $location.search().it;
		params.nodeParentId = $location.search().npi;

		if(typeof($location.search().icf) === 'string'){
			var icf = $location.search().icf.split(';');

			var incFilters = [];
			incFilters.push({facet: icf[0], value: icf.length > 1 ? icf[1] : ''});

			params.incFilters = incFilters;
		}
		else{
			var incFilters = [];
			angular.forEach($location.search().icf, function(icf){
				var filter = icf.split(';');

				incFilters.push({facet: filter[0], value: filter.length > 1 ? filter[1] : ''});
			});

			params.incFilters = incFilters;
		}

		if(getSearchValue('ecf') !== null){
			if(typeof($location.search().ecf) === 'string'){
				var ecf = $location.search().ecf.split(';');

				var exFilters = [];
				exFilters.push({facet: ecf[0], value: ecf.length > 1 ? ecf[1] : ''});

				params.exFilters = exFilters;
			}
			else{
				var exFilters = [];
				angular.forEach($location.search().ecf, function(ecf){
					var filter = ecf.split(';');

					exFilters.push({facet: filter[0], value: filter.length > 1 ? filter[1] : ''});
				});

				params.exFilters = exFilters;
			}
		}
		else{
			params.exFilters = [];
		}		

		return params;
	};

	return {
		resolveUrl: resolveUrl,
		absUrl: absUrl,
		redirect: redirect,
		open: open,
		pathName: pathName,
		getSearchValue: getSearchValue,
		addSearchValue: addSearchValue,
		clearSearchValue: clearSearchValue,
		clearSearch: clearSearch,
		checkSearchExists: checkSearchExists,
		setUrlParams: setUrlParams,
		getSearchModelFromLocation: getSearchModelFromLocation,
		getUrlWithoutHash: getUrlWithoutHash,
		getObjectDetailLink: getObjectDetailLink,
		getReturnToSearchParams: getReturnToSearchParams
	};
}]);
nhhs.factory('autoScrollSvc', ['$window', '$timeout', function($window, $timeout){
	// get easing type
	// @see https://github.com/d-oliveros/ngSmoothScroll/blob/master/lib/angular-smooth-scroll.js
	var getEasingPattern = function(time, ease){
		switch(ease) {
			case 'easeInQuad': 		return time * time; // accelerating from zero velocity
			case 'easeOutQuad': 	return time * (2 - time); // decelerating to zero velocity
			case 'easeInOutQuad': 	return time < 0.5 ? 2 * time * time : -1 + (4 - 2 * time) * time; // acceleration until halfway, then deceleration
			case 'easeInCubic': 	return time * time * time; // accelerating from zero velocity
			case 'easeOutCubic': 	return (--time) * time * time + 1; // decelerating to zero velocity
			case 'easeInOutCubic': 	return time < 0.5 ? 4 * time * time * time : (time - 1) * (2 * time - 2) * (2 * time - 2) + 1; // acceleration until halfway, then deceleration
			case 'easeInQuart': 	return time * time * time * time; // accelerating from zero velocity
			case 'easeOutQuart': 	return 1 - (--time) * time * time * time; // decelerating to zero velocity
			case 'easeInOutQuart': 	return time < 0.5 ? 8 * time * time * time * time : 1 - 8 * (--time) * time * time * time; // acceleration until halfway, then deceleration
			case 'easeInQuint': 	return time * time * time * time * time; // accelerating from zero velocity
			case 'easeOutQuint': 	return 1 + (--time) * time * time * time * time; // decelerating to zero velocity
			case 'easeInOutQuint': 	return time < 0.5 ? 16 * time * time * time * time * time : 1 + 16 * (--time) * time * time * time * time; // acceleration until halfway, then deceleration
			default:				return time;
		}
	};

	var AutoScrollSvc = function(){

		this.step = 16;
		this.duration = 0;
		this.ease = 0;	
		this.runAnimation = null;		
		this.startLocation = 0;
		this.endLocation = 0;
		this.timeLapsed = 0;
		this.distance = 0;
		this.percentage = 0;
		this.position = 0;

		this.container = null;
	};

	AutoScrollSvc.prototype.getCurrentLocation = function(){
		if(this.container)
		{
			return this.container.scrollTop();
		}

		return $window.pageYOffset ? $window.pageYOffset : document.documentElement.scrollTop;
	};

	AutoScrollSvc.prototype.animateScroll = function(self){

		this.timeLapsed += this.step;
		this.percentage = ( this.timeLapsed / this.duration ) > 1 ? 1 : ( this.timeLapsed / this.duration );
		this.position = this.startLocation + ( this.distance * getEasingPattern(this.percentage, this.ease));

		this.container ? this.container.scrollTop(this.position) : $window.scrollTo( 0, this.position );

		this.stopAnimation(self);
	};

	AutoScrollSvc.prototype.stopAnimation = function(self){
		if(this.position == this.endLocation)
		{
			// stop
			$timeout.cancel(this.runAnimation);
		}
		else{
			// set new timeout
			this.runAnimation = $timeout(function(){self.animateScroll(self);}, this.step);
		}
	};

	AutoScrollSvc.prototype.scrollTo = function(elemId){
		var elem = angular.element(document.querySelector(elemId));

		if(elem !== {})
		{
			this.startLocation = this.getCurrentLocation();
			this.endLocation = Math.max(elem.offset().top, 0);
			this.timeLapsed = 0;
			this.distance = this.endLocation - this.startLocation;

			this.animateScroll(this);
		}
	};

	AutoScrollSvc.prototype.scrollToPosition = function(newPosition){

		this.startLocation = this.getCurrentLocation();
		this.endLocation = newPosition
		this.timeLapsed = 0;
		this.distance = this.endLocation - this.startLocation;

		this.animateScroll(this);		
	};

	AutoScrollSvc.prototype.config = function(options){
		this.duration = options.duration;
		this.ease = options.ease;
		this.container = options.container;
	};

	return {
		getInstance: function(){ return new AutoScrollSvc();}
	};
}]);
 nhhs.service('saveThisSvc', ['$timeout', 'storageSvc', 'urlSvc', function ($timeout, storageSvc, urlSvc) {

        var modalButton, showSaveThis, saveThisModel;
        var showSaveThisPromise = storageSvc.getServerSessionData(urlSvc.resolveUrl(GET_SESSION_ITEM_URL), 'showSaveThis');
        showSaveThisPromise.then(function (data) {

            showSaveThis = data === 'True';
            storageSvc.removeServerSessionData(urlSvc.resolveUrl(REMOVE_SESSION_ITEM_URL), 'showSaveThis');
        });

        var savedModelPromise = storageSvc.getServerSessionData(urlSvc.resolveUrl(GET_SESSION_ITEM_URL), 'saveThisModel');
        savedModelPromise.then(function (data) {
            saveThisModel = data ? JSON.parse(data) : {};
        });

        var checkShowSaveThis = function (modalButtonSelector) {
            modalButton = modalButtonSelector ? $(modalButtonSelector) : $('save-modal');
            $timeout(checkShowModal, 0);
        };

        var checkShowModal = function () {
            var guid, opt, objId, objectName, heading, isNetwork;

            if (showSaveThis) {
                if (!saveThisModel) {
                   guid = modalButton.attr('data-guid');
                   opt = modalButton.attr('data-option');
                   objId = modalButton.attr('data-object-id');
                   objectName = modalButton.attr('data-object-name');
                   heading = modalButton.attr('data-heading');
                   id = clicked.attr('id');
                   isNetwork = clicked.attr('data-is-network');
                } else {
                    guid = saveThisModel.guid;
                    opt = saveThisModel.opt;
                    objId = saveThisModel.objId;
                    objectName = saveThisModel.objectName;
                    heading = saveThisModel.heading;
                    id = saveThisModel.id;
                    isNetwork = saveThisModel.isNetwork;
                }
                
                if (objectName && objectName !== '') {
                    SaveThisController.setObjectName(objectName);
                }

                
                if (heading && heading !== '') {
                    SaveThisController.setHeading(heading);
                }
                showModal(guid, objId, opt, id, isNetwork);
            }
        };

        var showModal = function (guid, objId, opt, id, isNetwork) {
            var modal = $(".record-modal");
            modal.addClass("active");
            modal.attr('save-guid', guid);
            modal.attr('url-opt', opt);
            modal.attr('object-id', objId);
            modal.attr('clicked-id', id);
            modal.attr('is-network', isNetwork);
        };

        return {
            checkShowSaveThis: checkShowSaveThis
        };
    }]);
nhhs.service('browserSvc', ['$window', function($window) {
    var setBrowser = function(){
        var userAgent = $window.navigator.userAgent;

        var browsers = {chrome: /chrome/i, safari: /safari/i, firefox: /firefox/i, ie: /trident/i};

        for(var key in browsers) {
            if (browsers[key].test(userAgent)) {
                return key;
            }
       };

       return 'unknown';
    }

    var browser = setBrowser();

    var getBrowser = function(){
        return browser;
    }

    return {
        getBrowser: getBrowser
    };

}]);
nhhs.service('detectPdfReaderSvc', ['$window', 'browserSvc', function($window, browserSvc){
	var browserName = browserSvc.getBrowser();

	var getActiveXObject = function(name) {
	    try { return new ActiveXObject(name); } catch(e) {}
	};

	var getNavigatorPlugin = function(name){
		var nav = $window.navigator;

		if(nav.plugins)
		{
			for (var i = 0; i < nav.plugins.length; i++) {
				if(nav.plugins[i].name === name){
					return nav.plugins[i];
				}
			};
		}		
	};

	var getPdfPlugin = function(){
		if(browserName === 'ie'){
			// load the activeX control
        	// AcroPDF.PDF is used by version 7 and later
        	// PDF.PdfCtrl is used by version 6 and earlier
        	return getActiveXObject('AcroPDF.PDF') || getActiveXObject('PDF.PdfCtrl');
		}

		return getNavigatorPlugin('Adobe Acrobat') || getNavigatorPlugin('Chrome PDF Viewer') || getNavigatorPlugin('WebKit built-in PDF');
	};

	var isAcrobatInstalled = function(){
		return !!getPdfPlugin();
	};

	var isTablet = function(){

		return /Android|webOS|iPhone|iPad|iPod|BlackBerry|IEMobile|Opera Mini/i.test(navigator.userAgent);
	}

	var isMobile = function() {
	  var check = false;
	  (function(a){if(/(android|bb\d+|meego).+mobile|avantgo|bada\/|blackberry|blazer|compal|elaine|fennec|hiptop|iemobile|ip(hone|od)|iris|kindle|lge |maemo|midp|mmp|mobile.+firefox|netfront|opera m(ob|in)i|palm( os)?|phone|p(ixi|re)\/|plucker|pocket|psp|series(4|6)0|symbian|treo|up\.(browser|link)|vodafone|wap|windows ce|xda|xiino/i.test(a)||/1207|6310|6590|3gso|4thp|50[1-6]i|770s|802s|a wa|abac|ac(er|oo|s\-)|ai(ko|rn)|al(av|ca|co)|amoi|an(ex|ny|yw)|aptu|ar(ch|go)|as(te|us)|attw|au(di|\-m|r |s )|avan|be(ck|ll|nq)|bi(lb|rd)|bl(ac|az)|br(e|v)w|bumb|bw\-(n|u)|c55\/|capi|ccwa|cdm\-|cell|chtm|cldc|cmd\-|co(mp|nd)|craw|da(it|ll|ng)|dbte|dc\-s|devi|dica|dmob|do(c|p)o|ds(12|\-d)|el(49|ai)|em(l2|ul)|er(ic|k0)|esl8|ez([4-7]0|os|wa|ze)|fetc|fly(\-|_)|g1 u|g560|gene|gf\-5|g\-mo|go(\.w|od)|gr(ad|un)|haie|hcit|hd\-(m|p|t)|hei\-|hi(pt|ta)|hp( i|ip)|hs\-c|ht(c(\-| |_|a|g|p|s|t)|tp)|hu(aw|tc)|i\-(20|go|ma)|i230|iac( |\-|\/)|ibro|idea|ig01|ikom|im1k|inno|ipaq|iris|ja(t|v)a|jbro|jemu|jigs|kddi|keji|kgt( |\/)|klon|kpt |kwc\-|kyo(c|k)|le(no|xi)|lg( g|\/(k|l|u)|50|54|\-[a-w])|libw|lynx|m1\-w|m3ga|m50\/|ma(te|ui|xo)|mc(01|21|ca)|m\-cr|me(rc|ri)|mi(o8|oa|ts)|mmef|mo(01|02|bi|de|do|t(\-| |o|v)|zz)|mt(50|p1|v )|mwbp|mywa|n10[0-2]|n20[2-3]|n30(0|2)|n50(0|2|5)|n7(0(0|1)|10)|ne((c|m)\-|on|tf|wf|wg|wt)|nok(6|i)|nzph|o2im|op(ti|wv)|oran|owg1|p800|pan(a|d|t)|pdxg|pg(13|\-([1-8]|c))|phil|pire|pl(ay|uc)|pn\-2|po(ck|rt|se)|prox|psio|pt\-g|qa\-a|qc(07|12|21|32|60|\-[2-7]|i\-)|qtek|r380|r600|raks|rim9|ro(ve|zo)|s55\/|sa(ge|ma|mm|ms|ny|va)|sc(01|h\-|oo|p\-)|sdk\/|se(c(\-|0|1)|47|mc|nd|ri)|sgh\-|shar|sie(\-|m)|sk\-0|sl(45|id)|sm(al|ar|b3|it|t5)|so(ft|ny)|sp(01|h\-|v\-|v )|sy(01|mb)|t2(18|50)|t6(00|10|18)|ta(gt|lk)|tcl\-|tdg\-|tel(i|m)|tim\-|t\-mo|to(pl|sh)|ts(70|m\-|m3|m5)|tx\-9|up(\.b|g1|si)|utst|v400|v750|veri|vi(rg|te)|vk(40|5[0-3]|\-v)|vm40|voda|vulc|vx(52|53|60|61|70|80|81|83|85|98)|w3c(\-| )|webc|whit|wi(g |nc|nw)|wmlb|wonu|x700|yas\-|your|zeto|zte\-/i.test(a.substr(0,4)))check = true})(navigator.userAgent||navigator.vendor||window.opera);
	  return check;
	}

	return {
		browserName : browserName,
		isAcrobatInstalled: isAcrobatInstalled,
		isMobile: isMobile,
		isTablet: isTablet
	};
}]);
catalog.service('eventHandlerSvc', ['$rootScope', function($rootScope){
	var onUpdateCategories = function(categoryCounts, showCategoryCounts){
		$rootScope.$broadcast('onUpdateCategories', {categoryCounts: categoryCounts, showCategoryCounts: showCategoryCounts});
	};

	var onCategoryChanged = function(category){
		$rootScope.$broadcast('onCategoryChanged', {category: category});
	};

	var onCategorySearch = function(category, searchParams){
		$rootScope.$broadcast('onCategorySearch', {category: category, searchParams: searchParams});
	};

	var onClassNameChanged = function(className, showCategoryCounts){
		$rootScope.$broadcast('onClassNameChanged', {className: className, showCategoryCounts: showCategoryCounts});
	};

	var onSearchReset = function(){
		$rootScope.$broadcast('onSearchReset');
	};

	var onSearch = function(searchParams){
		$rootScope.$broadcast('onSearch', {searchParams: searchParams});
	};

	var onToggleView = function(view){
		$rootScope.$broadcast('onToggleView', {view: view});
	};

	var onViewChanged = function(view){
		$rootScope.$broadcast('onViewChanged', {view: view});
	};

	var onHeaderLoaded = function(options){
		$rootScope.$broadcast('onHeaderLoaded', {options: options});
	};

	var onSortRppChanged = function(options){
		$rootScope.$broadcast('onSortRppChanged', {options: options});
	};

	var onInitSavedSearch = function(searchParams){
		$rootScope.$broadcast('onInitSavedSearch', {searchParams: searchParams});
	};

	var onToggleAdvancedSearch = function(advSearch){
		$rootScope.$broadcast('onToggleAdvancedSearch', {advSearch: advSearch});
	};

	var onToggleMustHaveImage = function(mustHaveImage){
		$rootScope.$broadcast('onToggleMustHaveImage', {mustHaveImage: mustHaveImage});
	};

	var onSearchIdChanged = function(searchId){
		$rootScope.$broadcast('onSearchIdChanged', {searchId: searchId});
	};

	var onShowShareThis = function(showShareThis){
		$rootScope.$broadcast('onShowShareThis', {showShareThis: showShareThis});
	};

	var onCheckSavedSearch = function(searchId){
		$rootScope.$broadcast('onCheckSavedSearch', {searchId: searchId});
	};

	var onInitialize = function(){
		$rootScope.$broadcast('onInitialize');
	};

	return{
		onUpdateCategories: onUpdateCategories,
		onCategorySearch: onCategorySearch,
		onCategoryChanged: onCategoryChanged,
		onClassNameChanged: onClassNameChanged,
		onSearchReset: onSearchReset,
		onSearch: onSearch,
		onToggleView: onToggleView,
		onViewChanged: onViewChanged,
		onHeaderLoaded: onHeaderLoaded,
		onSortRppChanged: onSortRppChanged,
		onInitSavedSearch: onInitSavedSearch,
		onToggleAdvancedSearch: onToggleAdvancedSearch,
		onToggleMustHaveImage: onToggleMustHaveImage,
		onSearchIdChanged: onSearchIdChanged,
		onShowShareThis: onShowShareThis,
		onCheckSavedSearch: onCheckSavedSearch,
		onInitialize: onInitialize
	};
}]);
nhhs.filter('percent', ['$filter', function ($filter) {
    return function (input, decimals, comma) {
        var percent = $filter('number')(input, decimals) + '%';
        if (comma) {
            return percent;
        } else {
            return percent.replace(',', '');
        }
    };
}]);

nhhs.filter('dollars', ['$filter', function ($filter) {
    return function (input, decimals, comma) {
        var dollars = "$" + $filter('number')(input, decimals);
        if (comma) {
            return dollars;
        } else {
            return dollars.replace(',', '');
        }
    };
}]);

nhhs.filter('html', ['$sce', function ($sce) {
    return function (html) {
        return $sce.trustAsHtml(html);
    };
}]);
nhhs.controller('collectionsSearchController',
    ['$scope', 'Item', '$timeout', 'urlSvc', 'storageSvc', 'sharedSearchSvc', 'siteIdService', 'saveThisSvc', 'autoScrollSvc', 'eventHandlerSvc',
    function ($scope, Item, $timeout, urlSvc, storageSvc, sharedSearchSvc, siteIdService, saveThisSvc, autoScrollSvc, eventHandlerSvc) {

        var collectionScroll = autoScrollSvc.getInstance();
        var searchId = '';

        function submitSearch(resetPageIndex) {
            /// <summary>Submits a valid search to the url service to update the location search value</summary>
            /// <param name="resetPageIndex" type="bool">Whether or not to reset the page index</param>
            /// <returns type="bool">A bool as to whether the search was valid or not</returns>

            var params = $scope.searchModel;

            if (!resetPageIndex && $scope.pageIndex > 0) {
                params.searchParams.pageIndex = $scope.pageIndex - 1;
            }
            else{
                $scope.pageIndex = 1;
                params.searchParams.pageIndex = 0;
            }

            if(!params.searchParams.className){
                params.searchParams.className = $scope.className;
            }

            params.searchParams.view = $scope.view;
            params.searchParams.resultsFor = $scope.resultsFor;

            urlSvc.setUrlParams(params.searchParams);

            return true;
        };

        function submitLocationSearch(searchParams){
            /// <summary> Submits the search to the backend controller based off the parameters in the url, or those built by a saved / shared search </summary>

            // Disable the Search and Reset buttons during a search to help prevent spamming
            $scope.isSearching = true;
            var results = Item.post('/api/collections/search', searchParams);
            results.then(function (data) {
                $scope.results = data.results;
                $scope.totalItems = data.totalItems;

                $scope.view = searchParams.view;
                $scope.resultsFor = searchParams.resultsFor;
                $scope.pageIndex = searchParams.pageIndex + 1;

                eventHandlerSvc.onViewChanged($scope.view);

                $scope.className = searchParams.className;
                eventHandlerSvc.onClassNameChanged(searchParams.className, true);

                $scope.searchModel.searchParams.rpp = searchParams.rpp;
                $scope.searchModel.searchParams.sortField = searchParams.sortField;

                searchParams.className = 'All';

                // Get the counts from the controller
                var counts = Item.post('/api/collections/GetSearchCounts', searchParams);
                counts.then(function (data) {
                    // Reset the search model class name for the pagination to function properly
                    $scope.searchModel.searchParams.className = $scope.className;
                    eventHandlerSvc.onUpdateCategories(data.categoryCounts, true);

                    //Add the search model params to the local storage to use for the object detail page, and search saving
                    storageSvc.setServerSessionData(urlSvc.resolveUrl(SET_SESSION_ITEM_URL), 'searchModel', angular.toJson($scope.searchModel.searchParams));
                    sharedSearchSvc.setSearchModel($scope.searchModel);
                    $timeout(SaveThisController.GetSearchSession, 10);                    
                });

                // Enable the buttons
                $scope.isSearching = false;

                // Show the results for text
                $scope.showResultsFor = true;

                $scope.isFirstSearch = false;

                // Set the values on the shared search service
                sharedSearchSvc.setSearchId(data.searchId);

                // Set the share this url for the share this directive
                eventHandlerSvc.onSearchIdChanged(data.searchId);

                var returnUrl = urlSvc.pathName() + "&searchId=" + data.searchId;
                SaveThisController.updateReturnUrl(returnUrl);

                storageSvc.setServerSessionData(urlSvc.resolveUrl(SET_SESSION_ITEM_URL), 'searchId', data.searchId);
                $timeout(SaveThisController.GetSearchSession, 10);

                eventHandlerSvc.onShowShareThis(true);

                eventHandlerSvc.onInitSavedSearch(searchParams);

                collectionScroll.scrollTo('#headerWrapper');

                var saveThisModelPromise = storageSvc.getServerSessionData(urlSvc.resolveUrl(GET_SESSION_ITEM_URL), 'saveThisModel');
                saveThisModelPromise.then(function(data){
                    var saveThisModel = data;
                    if(saveThisModel && saveThisModel !== {}){
                        saveThisSvc.checkShowSaveThis();
                        storageSvc.removeServerSessionData(urlSvc.resolveUrl(REMOVE_SESSION_ITEM_URL), 'saveThisModel');
                    }
                    else{
                        saveThisSvc.checkShowSaveThis('.save-modal');
                    }            
                });
            });
        };

        function checkSavedSearch(value) {
            var localId = value;
            var model;

            // This was a return to search page from the object detail page, so get the model from local storage and initialize the page based on the stored search model
            if (localId === searchId) {
                model = storageSvc.getServerSessionData(urlSvc.resolveUrl(GET_SESSION_ITEM_URL), 'searchModel');
                model.then(function (data) {
                    $scope.searchModel = { searchParams: angular.fromJson(data) };
                    $scope.searchModel.searchParams.searchInNetwork = siteIdService.siteId !== NHHS_SOCIETY_SITE_ID;

                    $scope.view = $scope.searchModel.searchParams.view;
                    $scope.resultsFor = $scope.searchModel.searchParams.resultsFor;
                    $scope.pageIndex = $scope.searchModel.searchParams.pageIndex + 1;

                    submitSearch(false);
                });
            }
            else {
                // This was a shared / saved search, so get search model from controller, set scope search model, and initialize the page based on if the model is returned
                model = sharedSearchSvc.getSearchModel(searchId);
                model.then(function (data) {
                    if (!data.searchModel) {
                        $scope.initialize();
                        return;
                    }
                    $scope.searchModel = angular.fromJson(data.searchModel);
                    $scope.searchModel.searchParams.searchInNetwork = siteIdService.siteId !== NHHS_SOCIETY_SITE_ID;
                    
                    $scope.view = $scope.searchModel.searchParams.view;
                    $scope.resultsFor = $scope.searchModel.searchParams.resultsFor;
                    $scope.pageIndex = $scope.searchModel.searchParams.pageIndex + 1;

                    eventHandlerSvc.onCheckSavedSearch(searchId);
                    submitSearch(false);
                });
            }
        }

        var init = function(){

            collectionScroll.config({duration: 1000, ease: 'easeInOutCubic'});

            $scope.urlSvc = urlSvc;
            $scope.results = [];

            $scope.isSearching = true;

            $scope.searchModel = {
                searchParams: { }
            };

            if(urlSvc.checkSearchExists()){
                if (urlSvc.getSearchValue('id') !== null) {
                    searchId = urlSvc.getSearchValue('id');
                    var sessionItem = storageSvc.getServerSessionData(urlSvc.resolveUrl(GET_SESSION_ITEM_URL), 'searchId');
                    sessionItem.then(checkSavedSearch);
                }
                else {
                    $scope.searchModel.searchParams = urlSvc.getSearchModelFromLocation();
                    $scope.searchModel.searchParams.searchInNetwork = siteIdService.siteId !== NHHS_SOCIETY_SITE_ID;
                    submitLocationSearch($scope.searchModel.searchParams);
                }                
            }
            else {
                $scope.searchModel.searchParams.searchInNetwork = siteIdService.siteId !== NHHS_SOCIETY_SITE_ID;
                $scope.searchModel.searchParams.rpp = 12;
                $scope.searchModel.searchParams.sortField = { sortOption: 'Relevance', sortDesc: false };
                $scope.initialize();
            }
        };

        $scope.initialize = function () {
            storageSvc.removeServerSessionData(urlSvc.resolveUrl(REMOVE_SESSION_ITEM_URL), 'searchId');
            storageSvc.removeServerSessionData(urlSvc.resolveUrl(REMOVE_SESSION_ITEM_URL), 'searchModel');

            var searchInNetwork = siteIdService.siteId !== NHHS_SOCIETY_SITE_ID;

            // Get the random set of results
            var results = Item.post('/api/collections/load', searchInNetwork);
            results.then(function(data) {
                $scope.results = data.results;
                $scope.totalItems = data.totalItems;
                eventHandlerSvc.onSearchIdChanged(data.searchId);
                //$scope.returnUrl = "~/" + urlSvc.pathName() + "#/?id=" + data.searchId;

                var returnUrl = urlSvc.pathName() + "&searchId=" + data.searchId;
                SaveThisController.updateReturnUrl(returnUrl);

                $scope.isSearching = false;
                $scope.view = 'gallery';
            });

            $scope.resultsFor = 'All Records';

            // The current page object, which is updated by the pagination directive
            $scope.pageIndex = 1;

            // The total number of items a search returns
            $scope.totalItems = 0;

            // Whether this was the first time the page loaded and was set up with random objects
            $scope.isFirstSearch = true;

            $scope.showResultsFor = false;
            //$scope.showShareThis = false;

            $scope.className = '';

            eventHandlerSvc.onClassNameChanged('', false);
            eventHandlerSvc.onInitialize();
        };

    $scope.goToPage = function () {
        /// <summary>Triggered when a button in the pager has been clicked on. Submits a search, using the stored search model.</summary>
        submitSearch(false, false, true);
    };

    $scope.search = function () {
        /// <summary>Triggered when clicking on the search button.</summary>
        /// <param name="event" type="object">The event that caused this function to be called</param>
        /// <returns type="bool">A bool as to whether the event should continue</returns>

        // Reset the page index to the first page
        $scope.pageIndex = 1;

        $scope.resultsFor = 'All Records';

        $scope.className = 'All';
        eventHandlerSvc.onClassNameChanged('All', true);
        $scope.searchModel.searchParams.className = $scope.className;

        if ($scope.isFirstSearch && siteIdService.siteId === NHHS_SOCIETY_SITE_ID  && !$scope.searchModel.searchParams.mustHaveImage) {
            eventHandlerSvc.onViewChanged('list');
            $scope.view = 'list';
        }

        submitSearch(true, true, true);
    };

    $scope.categorySearch = function (category) {
        /// <summary>Triggered when clicking on the side bar category links.</summary>
        /// <param name="event" type="object">The event that caused this function to be called</param>
        /// <param name="category" type="object">The object in the repeater that was clicked on.</param>
        /// <returns type="bool">A bool as to whether the event should continue</returns>

        // Set the scope classname to the passed in one
        $scope.className = category.className;

        $scope.resultsFor = category.displayText;

        SearchViewCtrl.filterViewClick();

        // Check if the user has performed a search yet
        if ($scope.isFirstSearch) {
            if ($scope.isFirstSearch && siteIdService.siteId === NHHS_SOCIETY_SITE_ID && !$scope.searchModel.searchParams.mustHaveImage) {
                eventHandlerSvc.onViewChanged('list');
                $scope.view = 'list';
            }

            $scope.isFirstSearch = false;

            return submitSearch(true, true, true);
        }
        else {
            $scope.searchModel.searchParams.className = $scope.className;
            return submitSearch(true, false, true);
        }
    }

    $scope.reset = function () {
        /// <summary>Triggered when clicking on the reset button.</summary>       

        storageSvc.removeServerSessionData(urlSvc.resolveUrl(REMOVE_SESSION_ITEM_URL), 'searchId');
        storageSvc.removeServerSessionData(urlSvc.resolveUrl(REMOVE_SESSION_ITEM_URL), 'searchModel');

        urlSvc.clearSearch();
    };

    $scope.setSaveThisSession = function (event) {
        var clicked = angular.element(event.currentTarget);

        var saveThisModel = {
            guid: clicked.attr('data-guid'),
            opt: clicked.attr('data-option'),
            objId: clicked.attr('data-object-id'),
            objectName: clicked.attr('data-object-name'),
            heading: clicked.attr('data-heading'),
            id: clicked.attr('id')
        }

        storageSvc.setServerSessionData(urlSvc.resolveUrl(SET_SESSION_ITEM_URL), 'showSaveThis', true);
        storageSvc.setServerSessionData(urlSvc.resolveUrl(SET_SESSION_ITEM_URL), 'saveThisModel', angular.toJson(saveThisModel));
    };

    $scope.$on('onCategorySearch', function(event, args){
        var searchParams = args.searchParams;

        if ($scope.isFirstSearch) {
            $scope.searchModel.searchParams.incFilters = searchParams.incFilters;
            $scope.searchModel.searchParams.exFilters = searchParams.exFilters;
            $scope.searchModel.searchParams.incCriteria = searchParams.incCriteria;
            $scope.searchModel.searchParams.exCriteria = searchParams.exCriteria;
            $scope.searchModel.searchParams.mustHaveImage = searchParams.mustHaveImage;
            $scope.searchModel.searchParams.yearA = searchParams.yearA;
            $scope.searchModel.searchParams.yearB = searchParams.yearB;
            $scope.searchModel.searchParams.className = args.category.className;
            $scope.searchModel.searchParams.advSearch = searchParams.advSearch;
        }        

        $scope.categorySearch(args.category);
    }); 

    $scope.$on('onSearchReset', function(){
        $scope.reset();
    });

    $scope.$on('onToggleView', function(event, args){
        var view = args.view;
        switch (view) {
            case 'gallery':
                // Store the current scope results
                var results = $scope.results;
                // Clear the scope results array
                $scope.results = [];

                // Set a timeout to reset the scope results. This is needed to allow the masonry plugin to refresh the view.
                // Otherwise the results just stack on top of each other...
                $timeout(function () {
                    $scope.results = results;
                }, 10);
                break;
            case 'list':
            default:
                break;
        }

        $scope.view = $scope.searchModel.searchParams.view = view;

        if(urlSvc.getSearchValue('view') !== null){
            urlSvc.addSearchValue('view', $scope.view);
        }
    });

    $scope.$on('onSearch', function(event, args){
        var searchParams = args.searchParams;

        $scope.searchModel.searchParams.incFilters = searchParams.incFilters;
        $scope.searchModel.searchParams.exFilters = searchParams.exFilters;
        $scope.searchModel.searchParams.incCriteria = searchParams.incCriteria;
        $scope.searchModel.searchParams.exCriteria = searchParams.exCriteria;
        $scope.searchModel.searchParams.mustHaveImage = searchParams.mustHaveImage;
        $scope.searchModel.searchParams.yearA = searchParams.yearA;
        $scope.searchModel.searchParams.yearB = searchParams.yearB;
        $scope.searchModel.searchParams.advSearch = searchParams.advSearch;
        $scope.searchModel.searchParams.includeTranscriptions = searchParams.includeTranscriptions;

        $scope.search();
    });

    $scope.$on('onSortRppChanged', function(event, args){
        $scope.searchModel.searchParams.rpp = args.options.Rpp;
        $scope.searchModel.searchParams.sortField = { sortOption: args.options.SortBy, sortDesc: args.options.SortDesc };

        submitSearch(true, false, true);
    });

    init();
}]);
nhhs.controller('objectDetailController', 
    ['$scope', '$rootScope', 'nodeGuidService', 'Item', '$timeout', 'urlSvc', 'storageSvc', 'siteIdService', 'saveThisSvc', 'memberSvc',
    function ($scope, $rootScope, nodeGuidService, Item, $timeout, urlSvc, storageSvc, siteIdService, saveThisSvc, memberSvc) {

    var ELECTRONIC_RESOURCE_JOIN_TEXT = 'Electronic Resources are only available to New Hampshire Historical Society members. To access electronic resources, please join the New Hampshire Historical Society.',
    TRANSCRIPTION_JOIN_TEXT = 'Transcriptions are only available to New Hampshire Historical Society members. To access transcriptions, please join the New Hampshire Historical Society.',
    NETWORK_LOADING_IMAGE_URL = '~/App/Content/library/img/icons/network_loading.gif',
    SOCIETY_LOADING_IMAGE_URL = '~/App/Content/library/img/icons/society_loading.gif';

    var currentImageNumber = 0;

    $scope.showTranscript = false;
    $scope.showMemberModal = false;

    $scope.specialFields = ["Subjects", "People", "Organizations", "Finding Aid Link", "Electronic Resources"];

    $scope.showLoading = true;

    var loadingGif = siteIdService.siteId === NHHS_SOCIETY_SITE_ID ? SOCIETY_LOADING_IMAGE_URL : NETWORK_LOADING_IMAGE_URL;
    $scope.loadingGif = urlSvc.resolveUrl(loadingGif);    

    function getSearchModel(model) {
        $scope.searchModel = (model !== '' && model != null) ? angular.fromJson(model) : '';
        var data = { id: $scope.nodeGuid, searchParams: $scope.searchModel };
        var objectPromise = Item.post('/api/objectdetail/getnodedata', data);
        objectPromise.then(setScopeObject);
    };

    function setScopeObject(result) {
        $scope.showLoading = false;
        $scope.object = result.resultObject;

        //angular.forEach($scope.object.resultNode.ObjectProperties, function(value, key){
        //    if(value.Name === 'Subjects')
        //    {
        //        var subjects = value.Value.replace(/\-\-/g, '<br />').replace(/<br\/>/g, '<br />').split("<br />");

        //        $scope.subjects = subjects && subjects.length > 0 ? subjects : [];
        //    }
        //    else if(value.Name === 'People')
        //    {
        //        var people = value.Value.replace(/\-\-/g, '<br />').replace(/<br\/>/g, '<br />').split("<br />");

        //        $scope.people = people && people.length > 0 ? people : [];
        //    }
        //    else if(value.Name === 'Organizations')
        //    {
        //        var orgs = value.Value.replace(/\-\-/g, '<br />').replace(/<br\/>/g, '<br />').split("<br />");

        //        $scope.orgs = orgs && orgs.length > 0 ? orgs : [];
        //    }
        //    else if(value.Name === 'Creator')
        //    {
        //        value.Value = value.Value.replace(/;/g, '<br />');
        //    }
        //});
        
        var hdnObjectName = document.querySelector("#hdnObjectName");
        hdnObjectName.value = $scope.object.resultNode.Name;

        var searchIdPromise = storageSvc.getServerSessionData(urlSvc.resolveUrl(GET_SESSION_ITEM_URL), 'searchId');
        searchIdPromise.then(setScopeSearchId);

        saveThisSvc.checkShowSaveThis('.save-modal');
    };

    function setScopeSearchId(id) {
        $scope.searchId = id;
    };

    // Function to create the search model
    function createSearchModel(includeFilters) {
        var isNetwork = siteIdService.siteId !== NHHS_SOCIETY_SITE_ID
        return {
            searchParams: {
                searchTerms: "",
                incFilters: includeFilters,
                exFilters: [],
                pageIndex: 0,
                rpp: 12,
                sortField: { sortOption: "Relevance", sortDesc: false },
                incCriteria: "All",
                exCriteria: '',
                mustHaveImage: isNetwork,
                includeTranscriptions: false,
                yearA: '0',
                yearB: '0',
                className: 'All',
                view: isNetwork ? 'gallery' : 'list',
                advSearch: false,
                searchInNetwork: isNetwork,
                resultsFor: 'All Records'
            }
        };
    };

    function setSessionData(event, baseUrl) {
        var idPromise = storageSvc.setServerSessionData(urlSvc.resolveUrl(SET_SESSION_ITEM_URL), 'searchId', $scope.searchId);

        idPromise.then(function (result) {
            var mPromise = storageSvc.setServerSessionData(urlSvc.resolveUrl(SET_SESSION_ITEM_URL), 'searchModel', angular.toJson($scope.searchModel.searchParams));

            mPromise.then(function(){
                $timeout(function(){
                    $scope.returnToSearch(event, baseUrl);
                }, 0);
            });
        });
    };

    $scope.initialize = function () {
        $scope.urlSvc = urlSvc;

        $scope.searchModel = {};
        $scope.nodeGuid = nodeGuidService.nodeId;
        $scope.subjects = [];

        //$scope.returnUrl = "/Object?id=" + $scope.nodeGuid;
        //$scope.returnUrl = "?id=" + $scope.nodeGuid;

        //var returnUrl = "/Object?id=" + $scope.nodeGuid;
        //SaveThisController.updateReturnUrl(returnUrl);

        var modelPromise = storageSvc.getServerSessionData(urlSvc.resolveUrl(GET_SESSION_ITEM_URL), 'searchModel');
        modelPromise.then(getSearchModel);

        $scope.isValidMember = memberSvc.isValid;
    };

    $scope.initialize();

    $scope.getNextOrPrevRecord = function (event, baseUrl, guid) {
        if (event) {
            event.preventDefault();
        }

        var url = baseUrl + "?id=" + guid;
        urlSvc.redirect(url);
    };

    $scope.returnToSearch = function (event, baseUrl) {
        if (event) {
            event.preventDefault();
        }

        var params = urlSvc.getReturnToSearchParams($scope.searchModel);

        var url = baseUrl + "#/?" + params;
        urlSvc.redirect(url);
    };

    $scope.submitSubjectsSearch = function (event, subject, baseUrl) {
        var url = urlSvc.getObjectDetailLink(baseUrl, 'Subjects', subject);
        urlSvc.redirect(url);
    };

    $scope.submitPeopleSearch = function (event, person, baseUrl) {
        var url = urlSvc.getObjectDetailLink(baseUrl, 'People', person);
        urlSvc.redirect(url);
    };

    $scope.toggleTranscription = function(showTranscription){
        if(showTranscription){
            if($scope.isValidMember || siteIdService.siteId !== NHHS_SOCIETY_SITE_ID)
            {
                $scope.showTranscript = showTranscription;
                $rootScope.$broadcast('onGalleryToggleTranscription', showTranscription);
            }
            else
            {
                $scope.joinText = TRANSCRIPTION_JOIN_TEXT;
                $scope.showMemberModal = !$scope.showMemberModal;
            }
        }
        else{
            $scope.showTranscript = showTranscription;
            $rootScope.$broadcast('onGalleryToggleTranscription', showTranscription);
        }
        
        BodyCtrl.toggleScrollBars(showTranscription);
    }

    $scope.getElectronicResource = function(url){
        if($scope.isValidMember || siteIdService.siteId !== NHHS_SOCIETY_SITE_ID)
        {
            urlSvc.open(url, '_blank');
        }
        else
        {
            $scope.joinText = ELECTRONIC_RESOURCE_JOIN_TEXT;
            $scope.showMemberModal = !$scope.showMemberModal;
        }
    };

    $scope.$on('onToggleTranscription', function(event, showTranscription){        
        $scope.toggleTranscription(showTranscription);
    });

    $scope.$on('onToggleZoom', function(event, showZoom){        
        $scope.toggleZoomModal(showZoom);
    });

    $scope.toggleMemberModal = function(showMemberModal){
        $scope.showMemberModal = showMemberModal;
        BodyCtrl.toggleScrollBars(showMemberModal);
    }

    $scope.toggleZoomModal = function(showZoomModal){
        $scope.showZoomModal = showZoomModal;
        BodyCtrl.toggleScrollBars(showZoomModal);
    }

    $scope.checkIsSpecialField = function(propertyName){

        return $scope.specialFields.indexOf(propertyName) === -1;
    };

    $scope.setSaveThisSession = function (event) {
        var clicked = angular.element(event.currentTarget);

        var saveThisModel = {
            guid: clicked.attr('data-guid'),
            opt: clicked.attr('data-option'),
            objId: clicked.attr('data-object-id'),
            objectName: clicked.attr('data-object-name'),
            heading: clicked.attr('data-heading'),
            isNetwork: clicked.attr('data-is-network')
        }

        storageSvc.setServerSessionData(urlSvc.resolveUrl(SET_SESSION_ITEM_URL), 'showSaveThis', true);
        storageSvc.setServerSessionData(urlSvc.resolveUrl(SET_SESSION_ITEM_URL), 'saveThisModel', angular.toJson(saveThisModel));
    };
}]);
nhhs.controller('timelineController', ['$scope', 'timelineItem', 'urlSvc', 'saveThisSvc', 'storageSvc', 
    function ($scope, timelineItem, urlSvc, saveThisSvc, storageSvc) {

    MIN_STARING_DATE = 1600,
    MAX_STARTING_DATE = new Date().getFullYear(),
    MIN_SLIDER_YEAR = 1600,
    MAX_SLIDER_YEAR = new Date().getFullYear();

    var topicAll = $('#topicsAll');
    var regionAll = $('#regionAll');
    var timelineSlider = $("#timelineSlider");
    $scope.statewideAndBeyond = false;

    function initImagePositions(){
        $scope.imagePositions = [];

        angular.forEach($scope.results, function(value, key) {
                $scope.imagePositions.push([value.images.length-1,0]);
            });
    }

    function checkValidDate(event){
        if(event && event.currentTarget)
        {
            var d1 = $scope.timelineModel.dateOne,
            d2 = $scope.timelineModel.dateTwo;

            if(event.currentTarget.id == 'datepickerStart')
            {
                if(isNaN(d1) || d1 < MIN_SLIDER_YEAR)
                {
                    $scope.timelineModel.dateOne = MIN_SLIDER_YEAR;
                    $scope.updateSlider();
                }
                
                if(d1 > d2)
                {
                    $scope.timelineModel.dateOne = d2;
                    $scope.updateSlider();
                }
            }            
            else if(event.currentTarget.id == 'datepickerEnd')
            {
                if(isNaN(d2) || d2 > MAX_SLIDER_YEAR)
                {
                    $scope.timelineModel.dateTwo = MAX_SLIDER_YEAR;
                    $scope.updateSlider();
                }
                
                if(d2 < d1)
                {
                    $scope.timelineModel.dateTwo = d1;
                    $scope.updateSlider();
                }
            } 

            event.preventDefault();           
        }        
    }

    var checkShowSaveThis = function(){
        saveThisSvc.checkShowSaveThis();
    };

    $scope.init = function () {
        $scope.urlSvc = urlSvc;
        //$scope.returnUrl = '~/Timeline';

        $scope.isSearching = true;

        BodyCtrl.addClass('timeline-overlay');
        
        //Instantiated variables that aren't passed to WebAPI
        $scope.backText = 'Back';
        $scope.selectedItem = {};
        $scope.showAdvSearch = false;

        //service..?
        var topics = timelineItem.get('/api/timeline/GetTimelineTopics');

        topics.then(function (data) {
            $scope.topics = data.topics;
        });

        var regions = timelineItem.get('/api/timeline/GetTimelineRegions');
        regions.then(function (data) {
            $scope.regions = data.regions;
        });
        
        $scope.showModal = false;
        //This model handles all dynamic data on the page, and is passed as a parameter to WebAPI for filtered search results
        $scope.timelineModel = {
            dateOne: MIN_STARING_DATE,
            dateTwo: MAX_STARTING_DATE,
            keywords: '',
            selectedTopics: [],
            selectedRegions: []
        };

        // ------------------------
        // *** parse the id in the url to use as an identifier to auto-open a timeline item ~Andrew J ***
        // ------------------------
        var objIDStringLength = 12;     // change this value based on length of objectId
        var objIDurlSearchKey = "id=";  // change this based on the desired search key in the url
        
        var urlID = window.location.href;
        if(urlID.search(objIDurlSearchKey) != -1)
        {
            urlID = urlID.substring(urlID.search(objIDurlSearchKey)+3).split("&")[0];
        }
        else
        {
            urlID = null;
        }
        // -----------------------

        var results = timelineItem.get('/api/timeline/load', $scope.timelineModel);

        results.then(function(data) {
            $scope.isSearching = false;
            
            $scope.results = data.results;
            /*Since we're using a promise, we have to wait till the promise returns before initializing the image positions and loading a single object from passed in id ~Paul O*/

            initImagePositions();

            //------------------
            // Auto-load the right page based on ID ~Andrew J
            //------------------
            if (urlID != null) {
                $scope.getItemDetails(urlID, true);
                BodyCtrl.toggleScrollBars($scope.showModal);
            }
            else
            {
                $scope.setSingleItem($scope.results[0].objectId);
            }
            //------------------
        });

        //MOCK DATA
        //$scope.results = timelineItem.mock();
        //initImagePositions();
        //Set initial slider values for both handles
        timelineSlider.slider({
              range: true,
              min: MIN_SLIDER_YEAR,
              max: MAX_SLIDER_YEAR,
              values: [ $scope.timelineModel.dateOne, $scope.timelineModel.dateTwo ],
              stop: function(event, ui) {
                    $scope.timelineModel.dateOne = ui.values[0];
                    $scope.timelineModel.dateTwo = ui.values[1];
                    $scope.$apply();
                    
                    $scope.applySearch(event);
              },
            slide: function (event, ui) {
                $scope.timelineModel.dateOne = ui.values[0];
                $scope.timelineModel.dateTwo = ui.values[1];
                $scope.$apply();
            }
        }).each(function() {
            // Add labels to slider whose values 
            // are specified by min, max
            // Get the options for this slider (specified above)
            var opt = $(this).data().uiSlider.options;
            // Get the number of possible values
            var vals = (opt.max - opt.min);
            // Position the labels
            for (var i = 0; i <= vals; i++) {
                if ((i+opt.min) % 50 == 0)
                {
                    // Create a new element and position it with percentages
                    var labelel = $('<span class="timelineLegendNumber">' + (i + opt.min) + '</span>').css('left', i/vals*100 + '%');
                    var markerel = $('<span class="timelineLegendMarker">|</span>').css('left', i/vals*100 + '%');
                    // Add the elements inside #slider
                    $(this).append(markerel).append(labelel);
                }
            }
        });
    }

    $scope.updateSlider = function(){
        /// <summary>Update the slider positions based on text input into date ranges</summary>
        var d1 = $scope.timelineModel.dateOne,
        d2 = $scope.timelineModel.dateTwo;

        timelineSlider.slider('values',0,d1).slider('values',1,d2);
    }

    $scope.getItemDetails = function(itemID, fromWebApi) {
        $scope.selectedItem = itemID;
        /// <summary>Access WebAPI to retreive properties for a single item, then populates details modal with data and shows it</summary>
        /// <param name="itemID" type="GUID">The item id to retreive</param>
        if ($scope.selectedItem != null)
        {
            $scope.showModal = !fromWebApi
                ? $scope.setSingleItem($scope.selectedItem)
                : $scope.getDetailsFromWebApi(itemID);

            if($scope.singleItem){
                $scope.singleItem.shareUrl = $scope.getObjectUrl($scope.singleItem.objectId);

                //$scope.returnUrl = '~/Timeline?id=' + $scope.singleItem.objectId;
            }
        }

        BodyCtrl.toggleScrollBars($scope.showModal);
    }

    $scope.setSingleItem = function (itemId) {
        /// <summary>Retreives properties for a single item, then populates details modal with data and shows it</summary>
        /// <param name="itemID" type="GUID">The item id to retreive</param>

        //------------------------
        // load the specified page ~Andrew J
        //------------------------
        var count = $scope.results.length;
        for (var i = 0; i < count; i++) {
            if($scope.results[i].objectId == itemId) {
                $scope.singleItem = $scope.results[i];
                $scope.singleImageActive = $scope.singleItem.images[0];
                return true;
            }
        }
        //------------------------

        return false;
    }

    $scope.getDetailsFromWebApi = function(itemId) {
        var itemPromise = timelineItem.get('/api/timeline/LoadSingle', { itemId: itemId });
        return itemPromise.then(function (result) {
            if (result != null && result.results != null) {
                $scope.singleItem = result.results;
                $scope.singleImageActive = $scope.singleItem.images[0];

                $scope.singleItem.shareUrl = $scope.getObjectUrl($scope.singleItem.objectId);

                //$scope.returnUrl = '~/Timeline?id=' + $scope.singleItem.objectId;

                checkShowSaveThis();
            }

            return $scope.singleItem != null;
        })
    }

    $scope.toggleTopics = function(topic) {
        /// <summary>Toggles topics by topic name</summary>
        /// <param name="propName" type="string">String value of the topic</param>
        var idx = $scope.timelineModel.selectedTopics.indexOf(topic.id);

        // is currently selected
        if (idx > -1) {
          $scope.timelineModel.selectedTopics.splice(idx, 1);
        }

        // is newly selected
        else {
            $scope.timelineModel.selectedTopics.push(topic.id);
        }

        topicAll[0].checked = $scope.timelineModel.selectedTopics.length === $scope.topics.length;
    };

    $scope.toggleRegions = function(regionId, regionName) {
        /// <summary>Toggles regions by region name</summary>
        /// <param name="propName" type="string">String value of the region</param>

        var index = $scope.timelineModel.selectedRegions.indexOf(regionId);

        if(regionName === 'Statewide & Beyond'){
            $scope.statewideAndBeyond = index === -1;
        }        

        // is currently selected
        if (index > -1) {
            // only remove the region if 'Statewide & Beyond' is not selected
            $scope.timelineModel.selectedRegions.splice(index, 1);        
        }

        // is newly selected
        else {
            $scope.timelineModel.selectedRegions.push(regionId);
        }

        regionAll[0].checked = $scope.timelineModel.selectedRegions.length === $scope.regions.length;
    };

    $scope.toggleAll = function(cb, type){
        /// <summary>Toggles all of the filters for either topics or regions</summary>
        /// <param name="cb" type="selector">Selector for checkbox that initializes this onclick</param>
        /// <param name="type" type="selector">Selector for the type of checkboxes, either .topicCheck or .regionCheck</param>
        var set = $(type);
        if($(cb)[0].checked) { // check select status
            set.each(function() { //loop through each checkbox
                this.checked = true;  //select all checkboxes with class "checkbox1"
            });
            if (type == '.topicCheck'){
                $scope.timelineModel.selectedTopics = [];
                //$scope.timelineModel.selectedTopics = $scope.topics.slice(0);
                for(var i = 0;i < $scope.topics.length;i++)
                {
                    $scope.timelineModel.selectedTopics.push($scope.topics[i].id);
                }
            }else{
                $scope.timelineModel.selectedRegions = [];
                //$scope.timelineModel.selectedRegions = $scope.regions.slice(0);
                for(var i = 0;i < $scope.regions.length;i++)
                {
                    $scope.timelineModel.selectedRegions.push($scope.regions[i].id);
                }

                $scope.statewideAndBeyond = true;
                $('#regionAll')[0].checked = true;
            }
        }else{
            set.each(function() { //loop through each checkbox
                this.checked = false; //deselect all checkboxes with class "checkbox1"                       
            });
            if (type == '.topicCheck'){
                $scope.timelineModel.selectedTopics = [];
            }else{
                $scope.timelineModel.selectedRegions = [];

                $scope.statewideAndBeyond = false;
                $('#regionAll')[0].checked = false;
            }       
        }
    }

    $scope.changeSlideImg = function (index, action) {
        $scope.imagePositions[index][1] += action;
        if ($scope.imagePositions[index][1] < 0)
        {
            $scope.imagePositions[index][1] = $scope.imagePositions[index][0];
        }else if($scope.imagePositions[index][1] > $scope.imagePositions[index][0])
        {
            $scope.imagePositions[index][1] = 0;
        }
    }

    $scope.setSingleImageActive = function (index) {
        if (index < 0) {
            index = $scope.singleItem.images.length - 1;
        }

        if (index >= $scope.singleItem.images.length) {
            index = 0;
        }

        $scope.singleImageActive = $scope.singleItem.images[index];
        $('#imageModalContainer').trigger('classChange');
    }

    $scope.applySearch = function(event){
        /// <summary>Pass the updated timelineModel to WebAPI to refine results from initial load</summary>
        /// <param name="event" type="object">No params passed, but makes heavy use of $scope.timelineModel to send updated filters</param>

        $scope.results = [];
        $scope.isSearching = true;
        checkValidDate(event);

        var params = $scope.timelineModel;
        var results = timelineItem.get('/api/timeline/load', params);

        if ($scope.showAdvSearch) {
            $scope.showAdvSearch = false;
        }

        results.then(function(data) {
            $scope.isSearching = false;
            $scope.results = data.results;

            initImagePositions();
        });

        if(event){
            event.preventDefault();
        }
    };

    $scope.clearFilters = function (event) {
        $('#regionAll')[0].checked = false;
        $scope.toggleAll('#regionAll', '.regionCheck');

        $('#topicsAll')[0].checked = false;
        $scope.toggleAll('#topicsAll', '.topicCheck');

        $scope.statewideAndBeyond = false;

        if (event) {
            event.preventDefault();
        }
    };

    $scope.clearAll = function(){
        $scope.clearFilters();

        $scope.timelineModel = {
            dateOne: MIN_STARING_DATE,
            dateTwo: MAX_STARTING_DATE,
            keywords: '',
            selectedTopics: [],
            selectedRegions: []
        };

        $scope.updateSlider();

        $scope.applySearch();
    }

    $scope.getRegionId = function (propName) {
        if (!$scope.regions) {
            return -1;
        }
        for (var i = 0; i < $scope.regions.length; i++) {
            if ($scope.regions[i].name === propName) {
                return $scope.regions[i].id;
            }
        }
        return -1;
    };

    $scope.toggleImageModal = function () {
        $scope.showImageModal = !$scope.showImageModal;
        $('#imageModalContainer').trigger('classChange');
    };

    $scope.toggleModal = function () {
        $scope.showModal = !$scope.showModal;

        BodyCtrl.toggleScrollBars($scope.showModal);
    };

    $scope.getObjectUrl = function (objectId){
        var absUrl =  (urlSvc.absUrl().indexOf("?") > -1) 
                        ? urlSvc.absUrl().split("?")[0] 
                        : urlSvc.absUrl();

        var fullUrl = absUrl + "?id=" + objectId;

        return fullUrl;
    };

    $scope.setSaveThisSession = function (event) {
        var clicked = angular.element(event.currentTarget);

        var saveThisModel = {
            guid: clicked.attr('data-guid'),
            opt: clicked.attr('data-option'),
            objId: clicked.attr('data-object-id'),
            objectName: clicked.attr('data-object-name'),
            heading: clicked.attr('data-heading'),
            id: clicked.attr('id')
        }

        storageSvc.setServerSessionData(urlSvc.resolveUrl(SET_SESSION_ITEM_URL), 'showSaveThis', true);
        storageSvc.setServerSessionData(urlSvc.resolveUrl(SET_SESSION_ITEM_URL), 'saveThisModel', angular.toJson(saveThisModel));
    };

    $(document).on('onObjectSaved', function(event, data){
        var objectId = data.objectId;
        if(objectId !== '')
        {
            for (var i = $scope.results.length - 1; i >= 0; i--) {
                if($scope.results[i].objectId === objectId)
                {
                    $scope.results[i].isSaved = true;
                    $scope.singleItem.isSaved = true;

                    $scope.$apply();
                    break;
                }
            };
        }
    });

    //Call initializer method 
    $scope.init();
}]);
// Generated by CoffeeScript 1.8.0
(function() {
  var __indexOf = [].indexOf || function(item) { for (var i = 0, l = this.length; i < l; i++) { if (i in this && this[i] === item) return i; } return -1; };

  angular.module('localytics.directives', []);

  angular.module('localytics.directives').directive('chosen', [
    '$timeout', function($timeout) {
      var CHOSEN_OPTION_WHITELIST, NG_OPTIONS_REGEXP, isEmpty, snakeCase;
      NG_OPTIONS_REGEXP = /^\s*(.*?)(?:\s+as\s+(.*?))?(?:\s+group\s+by\s+(.*))?\s+for\s+(?:([\$\w][\$\w]*)|(?:\(\s*([\$\w][\$\w]*)\s*,\s*([\$\w][\$\w]*)\s*\)))\s+in\s+(.*?)(?:\s+track\s+by\s+(.*?))?$/;
      CHOSEN_OPTION_WHITELIST = ['noResultsText', 'allowSingleDeselect', 'disableSearchThreshold', 'disableSearch', 'enableSplitWordSearch', 'inheritSelectClasses', 'maxSelectedOptions', 'placeholderTextMultiple', 'placeholderTextSingle', 'searchContains', 'singleBackstrokeDelete', 'displayDisabledOptions', 'displaySelectedOptions', 'width'];
      snakeCase = function(input) {
        return input.replace(/[A-Z]/g, function($1) {
          return "_" + ($1.toLowerCase());
        });
      };
      isEmpty = function(value) {
        var key;
        if (angular.isArray(value)) {
          return value.length === 0;
        } else if (angular.isObject(value)) {
          for (key in value) {
            if (value.hasOwnProperty(key)) {
              return false;
            }
          }
        }
        return true;
      };
      return {
        restrict: 'A',
        require: '?ngModel',
        terminal: true,
        link: function(scope, element, attr, ngModel) {
          var chosen, defaultText, disableWithMessage, empty, initOrUpdate, match, options, origRender, removeEmptyMessage, startLoading, stopLoading, valuesExpr, viewWatch;
          element.addClass('localytics-chosen');
          options = scope.$eval(attr.chosen) || {};
          angular.forEach(attr, function(value, key) {
            if (__indexOf.call(CHOSEN_OPTION_WHITELIST, key) >= 0) {
              return options[snakeCase(key)] = scope.$eval(value);
            }
          });
          startLoading = function() {
            return element.addClass('loading').attr('disabled', true).trigger('chosen:updated');
          };
          stopLoading = function() {
            return element.removeClass('loading').attr('disabled', false).trigger('chosen:updated');
          };
          chosen = null;
          defaultText = null;
          empty = false;
          initOrUpdate = function() {
            if (chosen) {
              return element.trigger('chosen:updated');
            } else {
              chosen = element.chosen(options).data('chosen');
              return defaultText = chosen.default_text;
            }
          };
          removeEmptyMessage = function() {
            empty = false;
            return element.attr('data-placeholder', defaultText);
          };
          disableWithMessage = function() {
            empty = true;
            return element.attr('data-placeholder', chosen.results_none_found).attr('disabled', true).trigger('chosen:updated');
          };
          if (ngModel) {
            origRender = ngModel.$render;
            ngModel.$render = function() {
              origRender();
              return initOrUpdate();
            };
            if (attr.multiple) {
              viewWatch = function() {
                return ngModel.$viewValue;
              };
              scope.$watch(viewWatch, ngModel.$render, true);
            }
          } else {
            initOrUpdate();
          }
          attr.$observe('disabled', function() {
            return element.trigger('chosen:updated');
          });
          if (attr.ngOptions && ngModel) {
            match = attr.ngOptions.match(NG_OPTIONS_REGEXP);
            valuesExpr = match[7];
            scope.$watchCollection(valuesExpr, function(newVal, oldVal) {
              var timer;
              return timer = $timeout(function() {
                if (angular.isUndefined(newVal)) {
                  return startLoading();
                } else {
                  if (empty) {
                    removeEmptyMessage();
                  }
                  stopLoading();
                  if (isEmpty(newVal)) {
                    return disableWithMessage();
                  }
                }
              });
            });
            return scope.$on('$destroy', function(event) {
              if (typeof timer !== "undefined" && timer !== null) {
                return $timeout.cancel(timer);
              }
            });
          }
        }
      };
    }
  ]);

}).call(this);

nhhs.service('exhibitionItem', ['requestFactory', function (requestFactory) {
    var get = function (url, params, qs, headers) {
        return requestFactory
            .get(url, params, qs, headers)
            .then(function (response) {
                return response;
            });
    };


    var post = function(url, data, headers){
    	return requestFactory
    		.post(url, data, headers)
    		.then(function(response){
    			return response;
    		});
    };

    var mock = function () {
        var data = [
            {
	            "img": "/library/img/collections/collection-1.jpg",
	            "heading": "Platter",
	            "dateRange": "1835-1850",
	            "objectId": "1973.015.147",
	            "shortDescription": "1 - Lorem ipsum dolor sit amet, consectetuer adipiscing elit. Aenean commodo ligula eget dolor. Aenean massa. Cum sociis natoque penatibus et magnis dis parturient montes, nascetur ridiculus mus. Donec quam felis, ultricies nec, pellentesque eu, pretium.",
	            "address": "123 main st",
	            "people": "blah",
	            "url": "http://www.wmur.com"
	        },
	        {
	            "img": "/library/img/collections/collection-2.jpg",
	            "heading": "Drawing",
	            "dateRange": "1735-1750",
	            "objectId": "1973.015.147",
	            "shortDescription": "2 - Lorem ipsum dolor sit amet, consectetuer adipiscing elit. Aenean commodo ligula eget dolor. Aenean massa. Cum sociis natoque penatibus et magnis dis parturient montes, nascetur ridiculus mus. Donec quam felis, ultricies nec, pellentesque eu, pretium",
	            "address": "123 main st",
	            "people": "blah",
	            "url": "http://www.unionleader.com"
	        },
	        {
	            "img": "/library/img/collections/collection-3.jpg",
	            "heading": "Engraving",
	            "dateRange": "1635-1650",
	            "objectId": "1973.015.147",
	            "shortDescription": "3 - Lorem ipsum dolor sit amet, consectetuer adipiscing elit. Aenean commodo ligula eget dolor. Aenean massa. Cum sociis natoque penatibus et magnis dis parturient montes, nascetur ridiculus mus. Donec quam felis, ultricies nec, pellentesque eu, pretium",
	            "address": "123 main st",
	            "people": "blah",
	            "url": "http://www.nytimes.com"
	        },
	        {
	            "img": "/library/img/collections/collection-4.jpg",
	            "heading": "Pattern. Shoe Sole",
	            "dateRange": "1535-1550",
	            "objectId": "1973.015.147",
	            "shortDescription": "4 - Lorem ipsum dolor sit amet, consectetuer adipiscing elit. Aenean commodo ligula eget dolor. Aenean massa. Cum sociis natoque penatibus et magnis dis parturient montes, nascetur ridiculus mus. Donec quam felis, ultricies nec, pellentesque eu, pretium",
	            "address": "123 main st",
	            "people": "blah",
	            "url": "http://www.mashable.com"
	        },
	        {
	            "img": "/library/img/collections/collection-5.jpg",
	            "heading": "Platter",
	            "dateRange": "1435-1450",
	            "objectId": "1973.015.147",
	            "shortDescription": "5 - Lorem ipsum dolor sit amet, consectetuer adipiscing elit. Aenean commodo ligula eget dolor. Aenean massa. Cum sociis natoque penatibus et magnis dis parturient montes, nascetur ridiculus mus. Donec quam felis, ultricies nec, pellentesque eu, pretium",
	            "address": "123 main st",
	            "people": "blah",
	            "url": "http://www.yahoo.com"
	        },
	        {
	            "img": "/library/img/collections/collection-6.jpg",
	            "heading": "Drawing",
	            "dateRange": "1335-1350",
	            "objectId": "1973.015.147",
	            "shortDescription": "6 - Lorem ipsum dolor sit amet, consectetuer adipiscing elit. Aenean commodo ligula eget dolor. Aenean massa. Cum sociis natoque penatibus et magnis dis parturient montes, nascetur ridiculus mus. Donec quam felis, ultricies nec, pellentesque eu, pretium",
	            "address": "123 main st",
	            "people": "blah",
	            "url": "http://www.bing.com"
	        },
	        {
	            "img": "/library/img/collections/collection-7.jpg",
	            "heading": "Engraving",
	            "dateRange": "1235-1250",
	            "objectId": "1973.015.147",
	            "shortDescription": "7 - Lorem ipsum dolor sit amet, consectetuer adipiscing elit. Aenean commodo ligula eget dolor. Aenean massa. Cum sociis natoque penatibus et magnis dis parturient montes, nascetur ridiculus mus. Donec quam felis, ultricies nec, pellentesque eu, pretium",
	            "address": "123 main st",
	            "people": "blah",
	            "url": "http://www.google.com"
	        }
        ]
        return data;
    };
    var singleMock = function () {
        var data = {
		    "img": ["/library/img/collections/collection-2.jpg","/library/img/collections/collection-1.jpg","/library/img/collections/collection-4.jpg"],
		    "bigImg": ["/library/img/bigImg.png","/library/img/bigImg.png","/library/img/bigImg.png"],
		    "heading": "Platter",
		    "fullDate": "June 05, 1845 AT 11:30 AM",
		    "objectId": "1973.015.147",
		    "tags": ['BLACKS & SLAVERY','GOVERNMENT & POLITICS','MERRIMACK VALLEY'],
		    "description": "Lorem ipsum dolor sit amet, consectetuer adipiscing elit. Aenean commodo ligula eget dolor. Aenean massa. Cum sociis natoque penatibus et magnis dis parturient montes, nascetur ridiculus mus. Donec quam felis, ultricies nec, pellentesque eu, pretium."
		}
		return data;
    };

    return {
        get: get,
    	post: post,
        mock: mock,
        singleMock: singleMock
    }
}]);
nhhs.controller('exhibitionController', ['$scope', '$timeout', 'nodeGuidService', 'exhibitionItem', 'urlSvc', 'saveThisSvc', 'storageSvc',  
    function ($scope, $timeout, nodeGuidService, exhibitionItem, urlSvc, saveThisSvc, storageSvc) {

    $scope.init = function () {
        //Instantiated variables that aren't passed to WebAPI
        $scope.selectedItem = {};
        $scope.selectedItemIndex = 0;
        $scope.selectedFilterId = '';

        $scope.showImgModal = false;

        var nodeGuid = { nodeGuid: nodeGuidService.nodeGuid };        

        var results = exhibitionItem.get('/api/exhibition/load', nodeGuid);
         results.then(function(data) {
             $scope.results = data.results;

             if($scope.results.length > 0)
             {
                var exhibitModel = {};

                // Check for the id in the session to see if the user was redirected after login
                var exhibitModelPromise = storageSvc.getServerSessionData(urlSvc.resolveUrl(GET_SESSION_ITEM_URL), 'saveThisModel');
                exhibitModelPromise.then(function(data){
                    exhibitModel = data ? angular.fromJson(data) : null; 

                    if(exhibitModel)
                    {
                       var item = '';

                       for (var i = 0; i < $scope.results.length; i++) {
                            if($scope.results[i].NodeGuid === exhibitModel.guid)
                            {
                                item = $scope.results[i];
                                break;
                            }
                        };

                        if(item)
                        {
                            $scope.showModal(item);
                            saveThisSvc.checkShowSaveThis();
                        }
                       else{
                            $scope.selectedItem = $scope.results[0];
                            saveThisSvc.checkShowSaveThis('.save-modal');
                        } 
                    }
                });
             }
                storageSvc.removeServerSessionData(urlSvc.resolveUrl(REMOVE_SESSION_ITEM_URL), 'saveThisModel');
             //$scope.returnUrl = "~" + urlSvc.pathName();
         });   
    }

    $scope.applyFilter = function (nodeId) {
        var results = exhibitionItem.post('/api/exhibition/filter', nodeId);

        $scope.selectedFilterId = nodeId;

        results.then(function (data) {
            $scope.results = data.results;
        });
    }

    $scope.showModal = function(item){
        if (item) {
            $scope.selectedItemIndex = $scope.results.indexOf(item);
            $scope.selectedItem = $scope.results[$scope.selectedItemIndex];
        }
        $scope.showImgModal = !$scope.showImgModal;

        BodyCtrl.toggleScrollBars($scope.showImgModal);
    };

    $scope.swapItem = function(action){
        $scope.selectedItemIndex += action;

        if($scope.selectedItemIndex < 0)
        {
            $scope.selectedItemIndex = $scope.results.length - 1;
        }

        if($scope.selectedItemIndex >= $scope.results.length)
        {
            $scope.selectedItemIndex = 0;
        }

        $scope.selectedItem = $scope.results[$scope.selectedItemIndex];
    }

    $scope.setSaveThisSession = function (event) {
        var clicked = angular.element(event.currentTarget);

        var saveThisModel = {
            guid: clicked.attr('data-guid'),
            opt: clicked.attr('data-option'),
            objId: clicked.attr('data-object-id'),
            objectName: clicked.attr('data-object-name'),
            heading: clicked.attr('data-heading'),
            id: clicked.attr('id')
        }

        storageSvc.setServerSessionData(urlSvc.resolveUrl(SET_SESSION_ITEM_URL), 'showSaveThis', true);
        storageSvc.setServerSessionData(urlSvc.resolveUrl(SET_SESSION_ITEM_URL), 'saveThisModel', angular.toJson(saveThisModel));
    };

    $(document).on('onObjectSaved', function(event, data){
        var nodeGuid = data.nodeGuid;
        if(nodeGuid !== '')
        {
            for (var i = $scope.results.length - 1; i >= 0; i--) {
                if($scope.results[i].NodeGuid === nodeGuid)
                {
                    $scope.results[i].isSaved = true;
                    $scope.selectedItem.isSaved = true;

                    $scope.$apply();
                    break;
                }
            };
        }
    });

    //Call initializer method 
    $scope.init();
}]);
