/**
 * service to wrap $uibModal for simple dialogs including widgets
 * 
 * Browser alternatives
 *  alert(title)
 *  confirm(title)
 *  prompt(title, defaultValue)
 * 
 * More control
 *  open(options)
 * 
 * Options
 *  title - goes in header - can be HTML
 *  message - goes in the body - can be HTML
 *  buttons - array of buttons
 *  input - true or false - want an input area?
 *  size - 'sm' or 'lg'
 *  value
 *  widget - id or sys_id
 *  widgetInput - input options 
 * 
 * 
 * All calls return a promise
 * 
 * See sp_modal.xml for template
 */
angular.module('sn.$sp').factory('spModal', function($q, spUtil, $http, $uibModal, i18n, $document, $uibModalStack, $window, $location) {
	"use strict";
	/* browser alternatives */
	function alert(message, appendTo) {
		var options = {
			title: message,
			buttons: [ {label: i18n.getMessage('OK'), primary: true} ],
			appendTo : appendTo
		};
		return alertConfirm(options);
	}
	
	function confirm(message, appendTo) {
		var options = {title: message, appendTo: appendTo};
		return alertConfirm(options);
	}
	
	// common to the above
	function alertConfirm(options) {
		options.messageOnly = true;
		if (options.title.length < 25)  // short message, small dialog
			options.size = 'sm'
				
		var defer = $q.defer();
		open(options).then(function() {
			defer.resolve(true);
		}, function() {
			defer.reject(false);
		})
		return defer.promise;		
	}
	
	/* get input, can be nil */
	function prompt(message, defaultValue, appendTo) {
		var options = {	
			title: message,
			input: true,
			value: defaultValue,
			appendTo : appendTo,
			headerStyle: {border: 'none', 'padding-bottom': 0},
			footerStyle: {border: 'none', 'padding-top': 0}
		};
		
		var defer = $q.defer();
		open(options).then(function(value) {
			defer.resolve(value);
		}, function() {
			defer.reject(null);
		})
		return defer.promise;
	}
	
	function open(options) {
		options = initOptions(options);
		var defer = $q.defer();
		// if widget, get it, else good to go
		if (options.widget) {
			var widgetURL = spUtil.getWidgetURL(options.widget);
			$http.post(widgetURL, options.widgetInput).success(function(response) {
				options.widget = response.result;
				if(options.widget.options) {
					options.widget.options.shared = options.shared;
					_open(options, defer);
				}
				else
					$window.location = $location.absUrl();
				
			});			
		} else
			_open(options, defer);
		return defer.promise;
	}
	
	function _open(options, defer) {
		var pageRoot = angular.element('.sp-page-root');
		var modal = $uibModal.open({
			templateUrl:'sp-modal.html',
			controller: spModalCtrl,
			size: options.size,
			appendTo: options.appendTo,
			backdrop: options.backdrop != undefined ? options.backdrop : true,
			keyboard: options.keyboard != undefined ? options.keyboard : true,
			resolve: {
				options: function() {
					return options;
				}
			}
		});

		modal.result.then(function(result) {
			if (options.input) {
				defer.resolve(result.input, result.button);
			} else {
				defer.resolve(result.button);
			}
		}, function(){
			defer.reject();
		});

		modal.rendered.then(function() {
			var h1 = angular.element('#modal-title');
			var modal = h1.closest('div.modal');
			modal.attr('aria-labelledby', 'modal-title');
			// PRB1170147: hide the root page headings when modal is active
            pageRoot.attr('aria-hidden', 'true');
		});
		
		modal.closed.then(function() {
			// PRB1170147: activate root page aria when modal is closed
			pageRoot.attr('aria-hidden', 'false');
		});
	}

	function initOptions(options) {
		var defaults = {
			title: '',
			message: '',
			messageOnly: false,
			errorMessage: '',
			input: false,
			label: '',
			size: '',
			value: '',
			required: false,
			values: false,
			onSubmit: null,
			widget: null,
			widgetInput: null,
			noDismiss: false,
			buttons: [
				{label: i18n.getMessage('Cancel'), cancel:true},
				{label: i18n.getMessage('OK'), primary:true}
			]
		};
		options = options || {};
		for (var key in defaults) {
			if (options[key] === undefined) {
				options[key] = defaults[key];
			}
		}
		if (options.messageOnly) {
			options.headerStyle = {border: 'none'}
			options.footerStyle = {border: 'none', 'padding-top': 0}			
		}
		if (options.noDismiss)
			options.headerStyle = {display: 'none'};
		return options;
	}

	function spModalCtrl($scope, options) {
		// ng-model="input.name"
		$scope.input = {value: options.value};
		$scope.options = options;
		$scope.form = {};
		// figure out what to focus
		if (!options.input) {
			options.buttons.forEach(function (b) {
				if (b.primary)
					b.focus = true;
			})
		}
		$scope.buttonClicked = function(button){
			if (button.cancel) {
				$scope.$dismiss();
				return;
			}
			if (options.input && $scope.form.xpForm.$invalid) {
				$scope.changed = true;
				return;
			}
			
			if(options.onSubmit) {
				var promise = options.onSubmit();
				promise.then(function(res) {
					if(!res.status) {
						$scope.options.errorMessage = res.errorMessage;
						return;					
					} else {
						$scope.$close({button:button, input: $scope.input.value});
					}					
				});
			} else {
				$scope.$close({button:button, input: $scope.input.value});
			}
		}
		$scope.clearFocusListCache = function() {
			$uibModalStack.clearFocusListCache();
		}
		$scope.submit = function(){
			var ok;
			angular.forEach($scope.options.buttons, function(button) {
				if (button.primary)
					ok = button;
			})
			if (ok) $scope.buttonClicked(ok);
		}
		
		$scope.keyPress = function(keyCode) {
			if(keyCode === 13) {
				$scope.submit();
			}
		}
	}
	var spModal = {alert: alert, confirm: confirm, prompt: prompt, open: open};
	return spModal;
})

/**
 * Like autofocus BUT evaluated 
 * 
 * <button sp-focus-if="bing.focus">Bing<button>
 * 
 * @param $timeout
 * @returns directive description
 */
angular.module('sn.$sp').directive('spFocusIf', function focusIf($timeout) {
	function link($scope, $element, $attrs) {
		var dom = $element[0];
		if ($attrs.spFocusIf)
			$scope.$watch($attrs.spFocusIf, focus);
		else
			focus(true);

		function focus(condition) {
			if (condition) {
				$timeout(function() {
					dom.focus();
				}, $scope.$eval($attrs.spFocusDelay) || 0);
			}
		}
	}

	return {
		restrict : 'A',
		link : link
	}
})
