/**********************************************************************
* 
*
*
**********************************************************************/

//var DEBUG = DEBUG != null ? DEBUG : true

var STEPS_TO_CHANGE_DIRECTION = 2
var _STEPS_LEFT_TO_CHANGE_DIRECTION = STEPS_TO_CHANGE_DIRECTION
var DIRECTION = 'next'



/*********************************************************************/

function updateDirection(direction){
	if(DIRECTION != direction){
		_STEPS_LEFT_TO_CHANGE_DIRECTION--
		if(_STEPS_LEFT_TO_CHANGE_DIRECTION == 0){
			DIRECTION = direction
			_STEPS_LEFT_TO_CHANGE_DIRECTION = 2
		}
	} else {
			_STEPS_LEFT_TO_CHANGE_DIRECTION = 2
	}
}


function directionImage(reverse){
	if(DIRECTION == (reverse ? 'prev' : 'next')){
		nextImage()
	} else {
		prevImage()
	}
}



/*********************************************************************/

var KEYBOARD_CONFIG = {
	// Global bindings...
	'*': {
		title: 'Global bindings',
		doc: 'NOTE: binding priority is the same as the order of sections '+
			'on this page.',

		F4: {
			alt: doc('Close viewer', 
				function(){ 
					closeWindow() 
					return false
				}),
		},
		F5: doc('Reload viewer', 
			function(){ 
				reload() 
				return false
			}),
		F12: doc('Show devTools', 
			function(){ 
				showDevTools() 
				return false
			}),
		// NOTE: these are for systems where F** keys are not available 
		// 		or do other stuff...
		R: {
			'ctrl+alt': doc('Reload viewer', 
				function(){ 
					reloadViewer() 
					return false
				}),
			'ctrl+shift': 'F5',
		},
		P: {
			'ctrl+shift': 'F12',
		},

		// NOTE: this is handled by the wrapper at this point, so we do 
		// 		not have to do anything here...
		F11: doc('Toggle full screen view', function(){ toggleFullscreenMode() }),
		F: {
			ctrl: 'F11',
		},

	},

	// info overlay...
	//
	// NOTE: this is here to prevent selecting images while trying to 
	// 		select info text...
	'.overlay-info:hover': {
		title: 'Info overlay',
		doc: 'Displayed on bottom of the screen if enabled (toggle with '+
			'<b>I</b>) and/or inline, at bottom of an image when cursor '+
			'is over it (only in ribbon view, toggle with <b>alt-I</b>)'+

			'<p>NOTE: when the cursor is over the info overlay one can use '+
			'Ctrl-A and Ctrl-D for info text selection, without affecting '+
			'image selection/marks.',

		ignore: [ 'A' ],

		A: {
			// NOTE: this is here only for documentation...
			ctrl: doc('Select all'),
		},
		D: {
			ctrl: doc('Clear selection', 
				function(){
					document.getSelection().empty()
					return false
				})
		}
	},


	// dialogs...
	//
	'.viewer.overlay .overlay-block.dialog': {
		title: 'Dialog',
		doc: 'NOTE: to <i>close</i> a dialog, in addition to the keyaboard '+
			'shortcuts, one can also click anywhere outside the dialog.',

		ignore: '*',

		'insert-return': doc('Insert return'),

		Enter: {
				default: doc('Accept dialog',
					function(){
						var f = $(':focus')
						
						// trigger the default button action...
						if(f.length > 0 
								&& (/button/i.test(f[0].tagName) 
									|| f.attr('type') == 'button')){
							return true

						// accept the dialog...
						} else {
							getOverlay($('.viewer')).trigger('accept')
							hideOverlay($('.viewer')) 
						}
					}),
				shift: 'insert-return',
				//ctrl: 'insert-return',
			},
		Esc: doc('Close dialog', 
			function(){ 
				//getOverlay($('.viewer')).trigger('close')
				hideOverlay($('.viewer')) 
				return false
			}),
	},


	// help view...
	//
	// NOTE: need to keep all info modes before the rest so as to give 
	// 		their bindings priority...
	'.drawer-mode': {
		title: 'Drawer views',
		doc: 'NOTE: In this view all other key bindings are disabled, '+
			'except app defaults and the ones explicitly defined here.',

		ignore: '*',

		Esc: doc('Close drawer',
			function(){ 
				toggleKeyboardHelp('off') 
				return false
			}),
		Q: 'Esc',
	},


	// slideshow view...
	//
	'.slideshow-mode': {
		title: 'Slideshow view',
		doc: 'To enter this view press <b>S</b>.',

		// XXX think about what else to disable here...
		ignore: [
			'Up', 'Down', 'Enter', 'R', 'L',
			],

		L: doc('Toggle slideshow looping',
			function(){
				SLIDESHOW_LOOP = SLIDESHOW_LOOP ? false : true
				showStatus('Slideshow: looping', SLIDESHOW_LOOP ? 'enabled...' : 'disabled...')
				return false
			}),
		R: doc('Reverse slideshow direction',
			function(){
				SLIDESHOW_DIRECTION = SLIDESHOW_DIRECTION == 'next' ? 'prev' : 'next'
				showStatus('Slideshow: direction:', SLIDESHOW_DIRECTION + '...')
				return false
			}),
		Esc: doc('Exit/stop slideshow', 
			function(){ 
				toggleSlideShowMode('off') 
				return false
			}),
		S: 'Esc',
		Q: 'Esc',
	},


	// single image view...
	//
	'.single-image-mode': {
		title: 'Single image view',
		doc: 'To toggle between this and ribbon view press <b>Enter</b>.',

		Esc: doc('Exit single image view', 
				function(){ 
					toggleSingleImageMode('off') 
					return false
				}),
		Q: 'Esc',
	},


	// crop views...
	//
	'.single-ribbon-mode:not(.single-image-mode), .marked-only-view:not(.single-image-mode)': {
		title: 'Cropped ribbon views',
		doc: 'To crop marked images press <b>shift-F2</b> and for '+
			'single ribbon crop view press <b>F3</b>.'+
			'<p>NOTE: toggling crop views is only possible from ribbon view.',

		Esc: {
				default: doc('Uncrop to last state', 
					function(){ 
						uncropLastState()
						return false
					}),
				shift: doc('Exit crop view', 
					function(){ 
						toggleMarkedOnlyView('off') 
						toggleSingleRibbonMode('off') 
						return false
					}),
			},
		Q: 'Esc',
	},


	// visible marks...
	//
	/* XXX does this work???
	 * 		...appears to be overtaken by every Esc definition before,
	 * 		and every single one of them returns false...
	'.marks-visible': {
		title: 'Visible marks',

		Esc: doc('Hide marks', 
				function(){ 
					toggleMarkesView('off')
					return false
				}),
	},
	*/


	// ribbon view only...
	//
	// XXX this breaks getKeyHandlers(...) when modes argument is given...
	'.viewer:not(.overlay):not(.single-image-mode)': {
		title: 'Ribbon view',

		Left: {
				alt: doc('Shift image left', 
					function(){ 
						event.preventDefault()
						shiftImageLeft() 
						centerView(null, 'css')
						// XXX for some odd reason centerRibbons does 
						// 		something really odd here...
						//centerRibbons()
						// XXX HACK...
						// XXX this still gets misaligned sometimes but this
						// 		is likely due to one of the align bugs 
						if(window._center_ribbon_delay != null){
							clearTimeout(_center_ribbon_delay)
						}
						_center_ribbon_delay = setTimeout(
							function(){ 
								centerRibbons() 
							}, 300)

						return false
					}),
			},
		Right: {
				alt: doc('Shift image right', 
					function(){ 
						event.preventDefault()
						shiftImageRight() 
						centerView(null, 'css')
						// XXX for some odd reason centerRibbons does 
						// 		something really odd here...
						//centerRibbons()
						// XXX HACK...
						// XXX this still gets misaligned sometimes but this
						// 		is likely due to one of the align bugs 
						// 		(see: TODO.otl)
						if(window._center_ribbon_delay != null){
							clearTimeout(_center_ribbon_delay)
						}
						_center_ribbon_delay = setTimeout(
							function(){ 
								centerRibbons() 
							}, 300)

						return false
					}),
			},

		// zooming...
		'#1': doc('Fit one image', function(){ fitNImages(1) }),
		'#2': doc('Fit two images', function(){ fitNImages(2) }),
		'#3': doc('Fit three images', function(){ fitNImages(3) }),
		'#4': doc('Fit four images', function(){ fitNImages(4) }),
		'#5': doc('Fit five images', function(){ fitNImages(5) }),
		'#6': doc('Fit six images', function(){ fitNImages(6) }),
		'#7': doc('Fit seven images', function(){ fitNImages(7) }),
		'#8': doc('Fit eight images', function(){ fitNImages(8) }),
		'#9': doc('Fit nine images', function(){ fitNImages(9) }),

		// cropping...
		// XXX add a non FXX key for macs...
		F2: {
				shift: doc('Crop marked only images', 
					function(){
						toggleMarkedOnlyView('on')
						// prevent the default from the main mode from 
						// getting called...
						return false
					}),
			},

		// XXX add a non FXX key for macs...
		F3: doc('Crop single ribbon', 
			function(){
				event.preventDefault()
				toggleSingleRibbonMode('on')
			}),
	},


	// general setup...
	//
	'.viewer:not(.overlay)': {
		title: 'Viewer',
		doc: 'These key bindings work in most other viewer views.'+

			'<p>NOTE: shifting all marked images from different ribbons will '+
			'perform the operations on ALL marked images but relative '+
			'the the current ribbon. i.e. some images might get promoted, '+
			'others demoted while some will not change position. ',

		// Basics...
		// XXX STUB: use a real path browser...
		O: doc('Open a directory path',
			function(){
				loadDirectoryDialog()
			}),


		// Navigation...
		// XXX need to cancel the animation of the prev action...
		Left: {
				default: doc('Previous image',
					function(){ 
						event.preventDefault()
						// update direction...
						updateDirection('prev')
						prevImage() 
						centerRibbons()
					}),
				ctrl: 'prev-screen',
			},
		Right: {
				default: doc('Next image',
					function(){ 
						event.preventDefault()
						// update direction...
						updateDirection('next')
						nextImage() 
						centerRibbons()
					}),
				ctrl: 'next-screen',
			},
		'prev-screen': doc('Previous screen',
				function(){ 
					event.preventDefault()
					prevScreenImages()
					centerRibbons()
				}),
		'next-screen': doc('Next screen',
				function(){ 
					event.preventDefault()
					nextScreenImages()
					centerRibbons()
				}),
		Space: {
				default: 'Right',
				shift: 'Left',
				// screen-oriented movement...
				ctrl: 'Right',
				'ctrl+shift': 'prev-screen',
			},
		Backspace: {
				default: 'Left',
				shift: 'Right',
				// screen-oriented movement...
				ctrl: 'Left',
				'ctrl+shift': 'next-screen',
			},
		Home: doc('First image', 
			function(){
				event.preventDefault()
				firstImage()
				centerRibbons()
			}),
		End: doc('Last image',
			function(){
				event.preventDefault()
				lastImage()
				centerRibbons()
			}),


		// combined navigation and editor actions...
		Up: {
				default: doc('Go to ribbon above', 
					function(){ 
						event.preventDefault()
						prevRibbon() 
						centerRibbons()
					}),
				shift: doc('Shift image up',
					function(){ 
						event.preventDefault()
						shiftImageUp(null, DIRECTION) 
						centerRibbons()
					}),
				'ctrl+shift': doc('Shift image up to empty ribbon',
					function(){
						event.preventDefault()
						shiftImageUpNewRibbon(null, DIRECTION) 
						centerRibbons()
					}),
				alt: doc('Shift marked images up',
					function(){
						toggleMarkesView('on')
						shiftMarkedImagesUp()
					}),
				'alt+shift': doc('Shift marked images up to empty ribbon',
					function(){
						// XXX
					}),
			},
		Down: {
				default: doc('Go to ribbon below', 
					function(){
						event.preventDefault()
						nextRibbon() 
						centerRibbons()
					}),
				shift: doc('Shift image down',
					function(){ 
						event.preventDefault()
						shiftImageDown(null, DIRECTION) 
						centerRibbons()
					}),
				'ctrl+shift': doc('Shift image down to empty ribbon',
					function(){
						event.preventDefault()
						shiftImageDownNewRibbon(null, DIRECTION) 
						centerRibbons()
					}),
				alt: doc('Shift marked images down',
					function(){
						toggleMarkesView('on')
						shiftMarkedImagesDown()
					}),
				'alt+shift': doc('Shift marked images down to empty ribbon',
					function(){
						// XXX
					}),
			},

		L: doc('Rotate image left', function(){ rotateLeft() }),
		R: {
				default: doc('Rotate image right', 
					function(){ rotateRight() }),
				ctrl: doc('Reverse image order', 
					function(){ 
						event.preventDefault()
						reverseImageOrder() 
					}),
			},
		H: doc('Flip image horizontally', 
			function(){ 
				var o = getImage().attr('orientation')
				// need to rotate relative to user, not relative to image...
				if(o == 90 || o == 270){
				   flipVertical() 
				} else {
					flipHorizontal() 
				}
			}),
		V: doc('Flip image vertically', 
			function(){ 
				var o = getImage().attr('orientation')
				// need to rotate relative to user, not relative to image...
				if(o == 90 || o == 270){
					flipHorizontal() 
				} else {
					flipVertical() 
				}
			}),


		// zooming...
		'#1': doc('Fit image to screen', function(){ fitNImages(1) }),
		// XXX this will do different stuff for different proportioned screens...
		'#2': doc('Show big image', function(){ fitNImages(1.5, true) }),
		'#3': doc('Show small image', function(){ fitNImages(3, true) }),

		'-': doc('Zoom in', function(){ zoomOut() }),
		'=': doc('Zoom out', function(){ zoomIn() }),


		Enter: doc('Toggle single image view', 
				function(){ toggleSingleImageMode() }),

		B: doc('Toggle theme', function(){ toggleTheme() }),

		S: {
				default: doc('Start slideshow', 
					function(){ toggleSlideShowMode('on') }),
				shift: doc('Sort images',
					function(){
						sortImagesDialog()
					}),
				ctrl: doc('Save current state', 
					function(){
						event.preventDefault()
						//saveLocalStorage()

						showStatusQ('Saving: localStorage: Data.')
						saveLocalStorageData()
						showStatusQ('Saving: localStorage: Marks.')
						saveLocalStorageMarks()

						showStatusQ('Saving: localStorage: Settings.')
						saveLocalStorageSettings()

						if(IMAGES_CREATED){
							showStatusQ('Saving: File: Images.')
							dumpJSON(normalizePath(CACHE_DIR +'/'+ IMAGES_FILE_DEFAULT), IMAGES)
							//saveFileImages()
							IMAGES_CREATED = false
						}
						showStatusQ('Saving: File: State.')
						saveFileState()

						showStatusQ('Saving: Done.')
					}),
				'ctrl+shift': doc('Export',
					function(){
						exportPreviewsDialog()
					}), 
			},
		Z: {
				ctrl: doc('Restore to last saved state', 
					function(){
						loadLocalStorage()
						loadLocalStorageMarks()
					})
			},


		// marking...
		// XXX not final, think of a better way to do this...
		// XXX need mark navigation...
		// XXX need marked image shift up/down actions...
		// XXX unmarking an image in marked-only mode results in nothing
		// 		visible focused if we unmark the first or last image in 
		// 		the ribbon...
		M: {
				// NOTE: marking moves in the same direction as the last
				//		move...
				//		i.e. marking can change direction depending on where
				//		we moved last...
				// NOTE: marking does not change move direction...
				// XXX  should this toggle or set mark to on?
				default: doc('Mark current image and advance',
					function(){ 
						toggleImageMark('on')
						directionImage()
						// XXX do we need this???
						//if(getImage().filter(':visible').length == 0){
						//	centerView(focusImage(getImageBefore()))
						//}
						centerRibbons()
					}),
				// same as default but in reverse direction...
				shift: doc('Mark current image and return',
					function(){
						toggleImageMark('on')
						directionImage(true)
						// XXX do we need this???
						//if(getImage().filter(':visible').length == 0){
						//	centerView(focusImage(getImageBefore()))
						//} 
						centerRibbons()
					}),
			},
		Ins: doc('Toggle mark on current image', function(){ toggleImageMark() }),
		'invert-marks': doc('Invert image marks', 
			function(){ invertImageMarks() }),
		A: {
			  	// XXX does not yet work with DATA (???)
				//shift: doc('Toggle marks in current contagious block', 
				//	function(){ toggleImageMarkBlock() }),

				ctrl: doc('Mark current ribbon', 
					function(){ 
						toggleMarkesView('on')
						markAll('ribbon') 
					}),
				'ctrl+shift': doc('Mark all images', 
					function(){ 
						toggleMarkesView('on')
						markAll('all') 
					}),
			},
		D: {
				ctrl: doc('Unmark current ribbon', 
					function(){ 
						event.preventDefault()
						removeImageMarks('ribbon') 
					}),
				'ctrl+shift': doc('Unmark all images', 
					function(){ removeImageMarks('all') }),
			},
		U: {
				default: doc('Unmark current image',
					function(){ toggleImageMark('off') }), 
				ctrl: doc('Unmark current ribbon', 
					function(){ removeImageMarks('ribbon') }),
				shift: doc('Unamrk all', 
					function(){ removeImageMarks('all') }),
			},


		// XXX add a non FXX key for macs...
		F2: doc('Toggle mark visibility', 
				function(){ toggleMarkesView() }),
		// XXX should we be able to toggle crop modes from single image mode???
		// 		...if yes, then remove the F2 & F3 definitions form ribbon
		// 		mode...
		// 		one way to go is to exit single-image-mode on s-f2 or f3...
		/*
		F2: {
				default: doc('Toggle mark visibility', 
					function(){ toggleMarkesView() }),
				shift: doc('Crop marked only images', 
					function(){
						toggleMarkedOnlyView('on')
					}),
			},

		F3: doc('Crop single ribbon', 
			function(){
				event.preventDefault()
				toggleSingleRibbonMode('on')
			}),
		*/

		E: doc('Open image in external software', openImage),
		// XXX make F4 a default editor and E a default viewer...
		F4: 'E',

		// info...
		I: {
				default: doc('Show current image info',
					function(){ 
						showImageInfo()
						//toggleImageInfoDrawer() 
					}),
				shift: doc('Toggle image info display',
					function(){ toggleImageInfo() }),
				alt: doc('Toggle inline image info display',
					function(){
						toggleInlineImageInfo()
					}),

				// marking...
				ctrl: 'invert-marks',
			},
		P: {
				default: doc('Show options',
					function(){ toggleOptionsUI() }),
				ctrl: doc('Print keyboard help',
					function(){
						toggleKeyboardHelp('on')
						// NOTE: on chrome this is blocking...
						print()
						toggleKeyboardHelp('off')
					}),
			},

		// Help and info...
		'?': doc('Show keyboard bindings',
			function(){ toggleKeyboardHelp() }),

		// XXX add a non FXX key for macs...
		F1: doc('Show help',
			function(){ toggleHelp() }),


		// XXX DEBUG MODE...
		// 		...remove these in production...
		//F12: doc('Show devTools', function(){ showDevTools() }),
		//F5: doc('Reload app', function(){ reload() }),

		/* testing the shift-key feature...
		'~': {
			default: function(){ alert('~') },
			// this is inaccessible...
			shift: function(){ alert('shift-~') },
			ctrl: function(){ alert('ctrl-~') },
			'ctrl+alt': function(){ alert('ctrl-alt-~') },
		},
		'`': {
			default: function(){ alert('`') },
			// this is also not accessible as it is shadowed by '''...
			shift: function(){ alert('shift-`') },
			ctrl: function(){ alert('ctrl-`') },
			'ctrl+alt': function(){ alert('ctrl-alt-`') },
		},
		*/
	}
}



/**********************************************************************
* vim:set ts=4 sw=4 :                                                */
