/* ocms-slideShow.js */

/*
    2012-Jan-06  dwl  special case fadeIn/Out for IE8 which doesn't do opacity changes on
                      absolutely positioned child elements
	2011-Nov-10  dwl  added resetDurationTimer, called by goTo(), but not exposed publicly
	2011-Mar-11  dwl  changed default slideDuration to 7s, minor formatting changes
	2010-Dec-23  dwl  added preGoCallback
	2010-Dec-06  dwl  changed initization of settings based on args type
*/

var OCMS;
if (typeof OCMS === "undefined") {
	/* OCMS becomes a global var */
	OCMS = {};
}

(function () {
	if (OCMS.slideShow === undefined) {
		OCMS.slideShow = function (args) {

			/* -- OCMS.slideShow local functions -- */
			function resetDurationTimer () {
				if (bRunning) {
					clearInterval(timeOutId);
				}
				timeOutId = setInterval(go, settings.slideDuration);
			}	// resetDurationTimer


            function fadeIn (nIt) {
                if (OCMS.isIE8) {
                    itemsIE8[nIt].fadeIn(settings.transitionSpeed);
                } else {
                    $items.eq(nIt).fadeIn(settings.transitionSpeed);
                }
            }   // fadeIn


            function fadeOut (nIt) {
                var $thisItem,
                    $childrenToo;

                if (OCMS.isIE8) {
                    itemsIE8[nIt].fadeOut(settings.transitionSpeed / 2);
                } else {
                    $items.eq(nIt).fadeOut(settings.transitionSpeed / 2);
                }
            }


			function goTo (nIndex) {
				//console.log("goTo: %d from %d", nIndex, nCurIndex);
				if (true) { //nIndex !== nCurIndex) {
					if ($.isFunction(settings.preGoCallback)) {
						settings.preGoCallback({
							oldIndex: nCurIndex,
							newIndex: nIndex,
							$newItem: $items.eq(nIndex),
							maxIndex: nMaxIndex
						});
					}

                    // previously this old item had .hide(), which helped with initial conditions
                    // without the !== guard, and gave impression of more responsiveness to user click
                    if (nIndex !== nCurIndex) {
    					fadeOut(nCurIndex);
    				}
					nCurIndex = nIndex;
                    fadeIn(nCurIndex);

					if (bRunning) {
						resetDurationTimer();
					}
				}
			}   // goTo


			function go (delta) {
				var nOldIndex = nCurIndex;

				if (nMaxIndex > 0) {
					if (delta !== 1 && delta !== -1) {
						delta = 1;
					}

					//console.log("go: %d %d", nCurIndex, delta);

					// show next (or previous!) image
					nCurIndex += delta;
					if (nCurIndex > nMaxIndex) {
						nCurIndex = 0;
					} else {
						if (nCurIndex < 0) {
							nCurIndex = nMaxIndex;
						}
					}

					if ($.isFunction(settings.preGoCallback)) {
						settings.preGoCallback({
							oldIndex: nOldIndex,
							newIndex: nCurIndex,
							$newItem: $items.eq(nCurIndex),
							maxIndex: nMaxIndex
						});
					}

                    fadeOut(nOldIndex);
                    fadeIn(nCurIndex);

					// remember, we're not always running; this could have been a 'manual' advance
					if (bRunning) {
						if (timeOutId) {
							// console.assert(timeOutId);
							// stop the timer (we're not necessarily here because it's been triggered)
							clearInterval(timeOutId);
							timeOutId = null;
						}

						// 60000 ms per minute
						if (settings.stopMinutes && Math.round((new Date() - nRunningStart) / 60000) < settings.stopMinutes) {
							timeOutId = setInterval(go, settings.slideDuration);
						} else {
							pause();
						}
					}
				}
			}	// go


			function pause () {
				if (bRunning) {
					bRunning = false;
					clearInterval(timeOutId);
					timeOutId = null;
				}
			}   // pause


			function resume () {
				if (!bRunning) {
					timeOutId = setInterval(go, settings.slideDuration);
					nRunningStart = new Date();
					bRunning = true;
				}
			}   // resume


			function toggle () {
				if (bRunning) {
					pause();
				} else {
					resume();
				}

				return bRunning;
			}   // toggle


			/* -- begin OCMS.slideShow -- */
			var settings = {
					slideDuration: 7000,	// does not adjust based on transitionSpeed
					transitionSpeed: 750,
					autoStart: true,
					stopMinutes: 30,
					startAtSlideNumber: 0,
					preGoCallback: null
				};

			if (typeof args === "string") {
				settings.selector = args;
			} else {
				// assume parameter object
				$.extend(true, settings, args);
			}

			var	$items = $(settings.selector),
				nMaxIndex = $items.length - 1,	// 0-based
				timeOutId = null,
				bRunning = false,
				nCurIndex = settings.startAtSlideNumber,
				nRunningStart = 0,
				itemsIE8 = [];

			if (OCMS.inPageEditor) {
				settings.autoStart = false;
			}

			if (nMaxIndex > 0) {
				// assumes that all items but the starting one should initially be hidden
				$items.not(':eq(' + nCurIndex + ')').hide();

				if (settings.autoStart) {
					timeOutId = setInterval(go, settings.slideDuration);
					nRunningStart = new Date();
					bRunning = true;
				}

                // build a parallel collection of elements that also includes all absolutely
                // positioned elements within each slide/item for IE8; except ones with class ssIGNORE
				if (OCMS.isIE8) {
				    $items.each(function (nIt, item) {
                        var $absChildren = $('*:not(.ssIGNORE)', item).filter(function () {
				            return $(this).css('position') === 'absolute';
				        });
				        OCMS.consoleMsg('\tabs children: ' + $absChildren.length);

				        itemsIE8[nIt] = $(item).add($absChildren);
				    });
				}
			}

			return {
				pause: pause,
				resume: resume,
				next: function () { return go(1); },
				previous: function () { return go(-1); },
				getSlideNumber: function () { return nCurIndex; },
				getIsRunning: function () { return bRunning; },
				goToSlideNumber: goTo,
				toggle: toggle
			};
		}	// slideShow
	}	// OCMS.slideShow === undefined
})();
