var appContainer = "GoAnywhereWebClientContainer";

var savedRowStyle = null;
function highlightTableRow(row) {
	savedRowStyle = row.className;
	row.className = "Highlighted";
}
function unhighlightTableRow(row) {
	row.className = savedRowStyle;
}

$(document).ready(function() {
	var $dropArea = $("#uploadID");
	$dropArea.on({
		"drop" : makeDrop,
		"dragenter" : ignoreDrag,
		"dragover" : ignoreDrag
	});
});

function ignoreDrag(e) {
	e.preventDefault();
}

function makeDrop(e) {
	var fileList = e.originalEvent.dataTransfer.files, fileReader;

	e.preventDefault();
	if (fileList && fileList.length > 0) {
		fileReader = new FileReader();
		fileReader.readAsDataURL(fileList[0]);
	}
}

/**
 * The TableUtils object is to organize all table related actions like selecting
 * rows.
 */
var TableUtils = {
	selectRow : function(table, rowIndex, showFooter) {
		if (PF(table).paginator) {
			var currentPage = PF(table).paginator.getCurrentPage();
			var rowsPerPage = PF(table).paginator.cfg.rows;
			var rowToSelect = rowIndex - (currentPage * rowsPerPage);
			PF(table).unselectAllRows();
			PF(table).selectRow(rowToSelect, true);
			if (!showFooter) {
				notifyTableAction(table, true);
			} else {
				notifyTableAction(table);
			}
		} else {
			PF(table).unselectAllRows();
			PF(table).selectRow(rowIndex, true);
			if (!showFooter) {
				notifyTableAction(table, true);
			} else {
				notifyTableAction(table);
			}
		}
	},

	unselectAllRows : function(table) {
		PF(table).unselectAllRows();
		notifyTableAction(table);
	}
};

var AppletPopup = {
	transferCount : null,
	message : '',
	confirmed : false,

	updateCount : function(count) {
		this.transferCount = count;
	},

	activeTransfers : function() {
		return this.transferCount > 0;
	},

	appletHide : function() {
		$(".ui-dialog-titlebar-close").off("click", "*", AppletPopup.onClick);
		appletClosed();
		$('body').css("overflow", "auto");
	},

	appletShown : function(message) {
		this.message = message;
		this.confirmed = false;
		$("iframe").parents(".ui-dialog").addClass("AppletDialog");
		$(".ui-dialog-titlebar-close").on("click", "*", AppletPopup.onClick);
	},

	onClick : function(event) {
		if (AppletPopup.activeTransfers()) {
			if (!confirm(AppletPopup.message)) {
				event.stopImmediatePropagation();
				return false;
			} else {
				AppletPopup.confirmed = true;
				AppletPopup.appletHide();
			}
		} else {
			AppletPopup.appletHide();
		}
	},

	disableScrolling : function() {
		$('body').css("overflow", "hidden");
	}
}

function selectRange(field, start, end) {
	// Found script example at https://gist.github.com/beiyuu/2029907
	if (!field)
		return;
	else if (field.setSelectionRange) {
		field.focus();
		field.setSelectionRange(start, end);
	} /* WebKit */
	else if (field.createTextRange) {
		var range = field.createTextRange();
		range.collapse(true);
		range.moveEnd('character', end);
		range.moveStart('character', start);
		range.select();
	} /* IE */
	else if (field.selectionStart) {
		field.selectionStart = start;
		field.selectionEnd = end;
	}
};

function closeDialogFrameworkPopup() {
	parent.PF(
			$('iframe', parent.document).closest('.ui-dialog')
					.data('widgetvar')).hide();
}

// Override SelectOneMenu Javascript
var selectOneInit = PrimeFaces.widget.SelectOneMenu.prototype.init;
PrimeFaces.widget.SelectOneMenu.prototype.init = function(cfg) {
	selectOneInit.call(this, cfg);

	if (this.jq.is(':visible')) {
		_renderSelectOneMenu(this);
	} else {
		// If the component is hidden then we want to find its hidden container
		var container = this.jq.closest('.ui-hidden-container');
		if (container.length) {
			var $this = this;

			addDeferredRender($this, this.id, container, function() {
				return renderSelectOneMenu($this);
			});
		}
	}
};

// Render
var _renderSelectOneMenu = function(select) {
	// do not adjust width of container if there is user width defined
	var userStyle = select.jq.attr('style');
	if (!userStyle || userStyle.indexOf('width') == -1) {
		select.jq.width(select.input.outerWidth(true));
	}

	select.label.width(select.jq.width() - select.menuIcon.width());

	var jqWidth = select.jq.innerWidth();
	if (select.panel.outerWidth() < jqWidth) {
		select.panel.width(jqWidth);
	}

};

var renderSelectOneMenu = function(select) {
	if (select.jq.is(':visible')) {
		_renderSelectOneMenu(select);
		return true;
	} else {
		return false;
	}
};

function addDeferredRender(comp, widgetId, container, callback) {
	PrimeFaces.addDeferredRender(widgetId, container.attr('id'), callback);
	if (container.is(':hidden')) {
		var parentContainer = container.parent()
				.closest('.ui-hidden-container');

		if (parentContainer.length) {
			this.addDeferredRender(comp, widgetId, parentContainer, callback);
		}
	}
};
// End Override SelectOneMenu JavaScript

var _resolveCompSelector = PrimeFaces.expressions.SearchExpressionFacade.resolveComponentsAsSelector;
PrimeFaces.expressions.SearchExpressionFacade.resolveComponentsAsSelector = function(
		expressions) {
	// Override this method for now to remove an issue with duplicate slashes.
	// When PrimeFaces fixes the issue
	var expression = expressions.replace(/\\\\/g, '\\');
	return _resolveCompSelector.call(this, expression);
}

// When clicking on the link button for the text editor update the text field so
// that the entire field is shown on the screen
var TextEditorOverride = {
	initialized : false,
	bindLinkLocationFix : function() {
		if (this.initialized) {
			return;
		}
		$(document).on('click', 'button.ql-link', function() {
			var container = $(this).closest('.ui-editor-toolbar').parent().children('.ql-container');
			var tooltip = container.children('.ql-tooltip');
			// Get the left style, if it less than 0 than make it 0 so it fully
			// appears on the screen
			var left = tooltip.css('left');
			if (left != 'auto') {
				left = (left.substring(0, left.length - 2)) * 1;
				if (left < 0) {
					left = 0;
					tooltip.css('left', left);
				}
			}
		});
		
		this.initialized = true;
	}
};

var ContextMenuUtils = {
	currentEvent : null,
	currentEventSet : false,
	commandCall : false,
	relativeToTarget : false,
	offsetWidth : 0,
	offsetHeight : 0,

	
	overrideOnShow : function() {
		PrimeFaces.widget.ContextMenu.prototype.show = function(e) {
			// hide other contextmenus if any
			$(document.body).children('.ui-contextmenu:visible').hide();

			if (e) {
				ContextMenuUtils.currentEvent = e;
				if (!ContextMenuUtils.currentEventSet) {
					if (ContextMenuUtils.commandCall) {
						// We only want this being called if it is going through
						// a remote command other wise funky behavior will occur
						ContextMenuUtils.currentEventSet = true;
						ContextMenuUtils.commandCall = false;
					}
					e.preventDefault();
					e.stopPropagation();
					return;
				} else {
					ContextMenuUtils.currentEventSet = false;
				}
			}

			if (this.cfg.beforeShow) {
				var retVal = this.cfg.beforeShow.call(this, e);
				if (retVal === false) {
					return;
				}
			}

			if (ContextMenuUtils.relativeToTarget) {
				var win = $(window), left = $(e.target).offset().left + ContextMenuUtils.offsetWidth, top = $(e.target).offset().top + ContextMenuUtils.offsetHeight, width = this.jq
				.outerWidth(), height = this.jq.outerHeight();
			}
			else {
				var win = $(window), left = e.pageX, top = e.pageY, width = this.jq
				.outerWidth(), height = this.jq.outerHeight();
			}

			var bottom = win.height() + win.scrollTop();

			// collision detection for window boundaries
			if ((left + width) > (win.width()) + win.scrollLeft()) {
				left = left - width;
			}
			if ((top + height) > bottom) {
				top = top - height;
				if (top < 0) {
					top = 0;
					if (height > bottom) {
						this.jq.css({
							'overflow-y' : 'auto',
							'overflow-x' : 'hidden',
							'max-height' : win.height()
						});
						this.jq.find('.ui-menu-child').css('position', 'fixed');
					}
				}
			}

			this.jq.css({
				'left' : left,
				'top' : top,
				'z-index' : ++PrimeFaces.zindex
			}).show();

			e.preventDefault();
			e.stopPropagation();
		};
		var _showSubMenu = PrimeFaces.widget.ContextMenu.prototype.showSubmenu;
		PrimeFaces.widget.ContextMenu.prototype.showSubmenu = function(
				menuitem, submenu) {
			_showSubMenu.call(this, menuitem, submenu);
			var win = $(window);

			var bottom = win.height() + win.scrollTop();
			var y = submenu.offset().top;

			if (y + submenu.height() > bottom) {
				submenu.css({
					'overflow-y' : 'auto',
					'overflow-x' : 'hidden',
					'max-height' : win.height()
				});
			}
		}
	},

	startShowingMenu : function() {
		ContextMenuUtils.commandCall = true;
		ContextMenuUtils.currentEventSet = false;
	},
	
	onContextMenuComplete : function(renderMenu, widgetVarName) {
		if(renderMenu) {
			ContextMenuUtils.relativeToTarget = false; 
			PF(widgetVarName).show(ContextMenuUtils.currentEvent);
		} else {
			ContextMenuUtils.currentEventSet = false;
		}
	},
	
	onContextMenuIconFocus : function(element) {
		$(element).find('.more-actions-gray-icon').removeClass().addClass('more_actions_icon_hover');
	},
	
	onContextMenuIconBlur : function(element) {
		$(element).find('.more_actions_icon_hover').removeClass().addClass('more-actions-gray-icon');
	},
	
	prepareContextMenuLeftClick : function(event) {
		ContextMenuUtils.currentEvent = event;
		ContextMenuUtils.currentEventSet = true;
	},
	
	onContextMenuLeftClickComplete : function(renderMenu, widgetVarName) {
		if(renderMenu) {
			ContextMenuUtils.relativeToTarget = true; 
			PF(widgetVarName).show(ContextMenuUtils.currentEvent);
		} else {
			ContextMenuUtils.currentEventSet = false;
		}
	},
	
	// Function to interact with context menus using the keyboard
	keyboardNav : function(contextMenu, $target){
		var $menuItems = $(PF(contextMenu).links);
		
		$menuItems.focus(function(){
			$(this).addClass('ui-state-hover');
		});
		$menuItems.blur(function(){
			$(this).removeClass('ui-state-hover');
		});
		
		//Removes all hover styles from the menu and sets
		//the cursor's selection as the currently selected item
		$menuItems.mouseover(function(){
			$menuItems.removeClass('ui-state-hover');
			$(this).addClass('ui-state-hover');
		});
		
		$menuItems.first().focus();
		
		// Event handler to only allow toggling of menu items with 
		// the up and down keys. Tab key hides the menu.
		$menuItems.keydown(function contextMenuHandler(e){
			var code = e.keyCode || e.which;
			var $activeElement = $(document.activeElement);

			//Tab key
		    if (code === 9){ 
		        PF(contextMenu).hide();
		        e.preventDefault();
		        $target.closest('.MoreActions').nextAll(':has(:focusable)').first().find(':focusable').focus();
		    }
		    //Left arrow key
		    else if(code === 37){
		    	$(document.activeElement).closest('.ui-menu-child').hide();
		    	$('.ui-submenu-link').focus();
		    }
		    //Up arrow key
		    else if(code === 38){
		    	$activeElement.parent().prevAll('.ui-menuitem:first').find('.ui-menuitem-link').focus();
		    }
		    //Right arrow key
		    else if(code === 39){
		    	$activeElement.siblings().find('.ui-menuitem-link:first').focus();
		    }
		    //Down arrow key
		    else if(code === 40){
		    	$activeElement.parent().nextAll('.ui-menuitem:first').find('.ui-menuitem-link').focus();
		    }
		});
	}
};

/**
 * A global Application Storage wrapper to store front-end only data that needs to be available across multiple tabs/windows/iframes.
 *
 * This store automatically separates data by protocol, domain, and port so the same keys will point to different data if any of those three properties differ.
 */
var ApplicationStorage = {
	/**
	 * Sets a key/value pair.
	 * @access public
	 * @param {string} key - key used to reference the value
	 * @param {Object} value - an object that can be represented as a JSON string
	 */
	set : function(key, value) {
		var resolvedKey = this._resolveKey(key);
		var valueStr = JSON.stringify(value);
		if (this._isLocalStorageAvailable()) {
			window.localStorage.setItem(resolvedKey, valueStr);
		} else {
			PrimeFaces.setCookie(resolvedKey, valueStr, {
				path : '/',
				secure : window.location.protocol == 'https:'
			});
		}
	},
	/**
	 * Gets a value for the given key.
	 * @access public
	 * @param {string} key - key used to reference the value
	 * @return {Object} A value object that was parsed from a stored JSON string
	 */
	get : function(key) {
		var resolvedKey = this._resolveKey(key);
		var valueStr = '';
		if (this._isLocalStorageAvailable()) {
			valueStr = window.localStorage.getItem(resolvedKey, valueStr);
		} else {
			valueStr = PrimeFaces.getCookie(resolvedKey);
		}
		return JSON.parse(valueStr);
	},
	/**
	 * Remove a value for the given key.
	 * @access public
	 * @param {string} key - key used to reference the value
	 */
	remove : function(key) {
		var resolvedKey = this._resolveKey(key);
		if (this._isLocalStorageAvailable()) {
			window.localStorage.removeItem(resolvedKey);
		} else {
			PrimeFaces.deleteCookie(resolvedKey);
		}
	},
	/**
	 * Resolve a key to include protocol/port specific information to prevent clashes.
	 *
	 * The underlying storage methods are already separated by domain by the browser.
	 * @access private
	 * @param {string} key - key used to reference the value
	 */
	_resolveKey : function(key) {
		var prefix = location.protocol == 'https:' ? 's_' : '';
		prefix += window.location.port + '_';
		return prefix + key;
	},
	/**
	 * Determine if the local storage feature is available and enabled in this browser. We will check every time because the local storage might run out of space.
	 * 
	 * @type {boolean}
	 * @link https://developer.mozilla.org/en-US/docs/Web/API/Web_Storage_API/Using_the_Web_Storage_API#Feature-detecting_localStorage
	 */
	_isLocalStorageAvailable : function() {
		var storage;
		try {
			storage = window.localStorage;
			var x = '__storage_test__';
			storage.setItem(x, x);
			storage.removeItem(x);
			return true;
		} catch (e) {
			return e instanceof DOMException && (
			// everything except Firefox
			e.code === 22 ||
			// Firefox
			e.code === 1014 ||
			// test name field too, because code might not be present
			// everything except Firefox
			e.name === 'QuotaExceededError' ||
			// Firefox
			e.name === 'NS_ERROR_DOM_QUOTA_REACHED') &&
			// acknowledge QuotaExceededError only if there's something already stored
			(storage && storage.length !== 0);
		}
	}
};