var Widgets = {
	
	jQuery : $, 
	widgetWidth : 0,
	currentWidget : 0,
	oldContentScrollDistance : 0,
	widgetResizeTimer : null,
	sortStart: null,
	sortEnd: null,
	widgetQueue: [],
	
	settings : {
		widgetSelector : '.widget:visible', 
		handleSelector : '.widget-head', 
		contentSelector : '.widget-content', 
		iconsSelector : '#widget-icons',
		widgetDefault : {
			removable : true, 
			editable : true,
			refreshable: true
		}, 
		widgetIndividual : {
			//weather
			widget_1 : {
				removable : true, 
				editable : true,
				refreshable: true
			},
			//markets
			widget_2 : {
				removable : true, 
				editable : false,
				refreshable: true
			},
			//license lookup
			widget_3 : {
				removable: true,
				editable: true,
				refreshable: false
			},
			//balance forward
			widget_6 : {
				removable: true,
				editable: false,
				refreshable: false
			},
			//recent credits
			widget_8 : {
				removable: true,
				editable: false,
				refreshable: true
			},			
			//harvest data
			widget_9 : {
				removable: true,
				editable: false,
				refreshable: true
			},
			//pending shipments
			widget_10 : {
				removable: true,
				editable: false,
				refreshable: true
			},
			//downloads
			widget_11 : {
				removable: true,
				editable: false,
				refreshable: true
			},
			//events
			widget_12 : {
				removable: true,
				editable: false,
				refreshable: true
			},
			//invalid licenses
			widget_13 : {
				removable: true,
				editable: false,
				refreshable: true
			},
			//my inventory
			widget_14 : {
				removable: true,
				editable: false,
				refreshable: true
			},
			//shipment needs
			widget_15 : {
				removable: true,
				editable: false,
				refreshable: true
			}
		}
	}, 
	
	init : function () {
		var Widgets = this, 
			$ = this.jQuery, 
			settings = this.settings;
			
		Widgets.addWidgetControls();
		Widgets.createWidgetIcons();
		
		//add swipe for mobile and tablet
		$('.widgets .scroll').swipe({
			fingers: 1,
			triggerOnTouchEnd: true,
			swipeStatus: $.proxy(Widgets.widgetsSwipeStatus, Widgets),
			allowPageScroll: 'vertical',
			threshold: 100
		});
		
		//add swipe for mobile and tablet
		$('<div/>')
			.addClass('widget-scroll')
			.appendTo($(settings.widgetSelector))
			.swipe({
				fingers: 1,
				triggerOnTouchEnd: true,
				swipeStatus: $.proxy(Widgets.widgetContentSwipeStatus, Widgets),
				allowPageScroll: 'none',
				threshold: 100
			});
			
		$(window).resize(function() {
			clearTimeout(Widgets.widgetResizeTimer);
			Widgets.widgetResizeTimer = setTimeout(function() {
				Widgets.widgetsResize();
			}, 100);		
		});
		
		Widgets.setWidgetContainerHeight(true);
	}, 
	
	getWidgetSettings : function (id) {
		var $ = this.jQuery, 
			settings = this.settings;
		return (id && settings.widgetIndividual[id]) ? $.extend({}, settings.widgetDefault, settings.widgetIndividual[id]) : settings.widgetDefault;
	}, 
	
	addWidgetControls : function () {
		var Widgets = this, 
			$ = this.jQuery, 
			settings = this.settings;
		
		$(settings.widgetSelector).each(function () {
			var thisWidget = this,
				thisWidgetSettings = Widgets.getWidgetSettings('widget_' + $(this).attr('widget'));
			if (thisWidgetSettings.removable) {
				$('<a href="#" class="remove">REMOVE</a>').mousedown(function (e) {
						e.stopPropagation();
					})
					.addClass('widget-remove')
					.click(function () {
						if (confirm('Are you sure you wish to remove this widget? The widget will not be available to re-add until the page is refreshed.')) {
							$(this).parents(settings.widgetSelector).animate({
									opacity : 0
								}, function () {
									//get the pkey before removing the reference
									var pkey = $(this).attr('pkey');
									//remove the widget
									$(this).remove();
									
									if ($(settings.widgetSelector).length == 0) {
										$('.widgets').hide();
										$('#widget-help').show();
									} else {
										//reset to first widget
										Widgets.fadeWidget(0);
									}
									//rebuild the widget icons
									Widgets.createWidgetIcons();
									// update database, remove widget
									$.get('/_queries/widget_remove_post.php', { pkey: pkey });
								});
						}
						return false;
					}).appendTo($(settings.handleSelector, this));
			}
			
			if (thisWidgetSettings.editable) {
				$('<a href="#" class="edit">EDIT</a>').mousedown(function (e) {
						e.stopPropagation();
					})
					.addClass('widget-edit')
					.toggle(function () {
						$(this)
							.parents(settings.widgetSelector) 
							.find('.edit-box') 
							.slideDown();						
						return false;
					}, function () {
						$(this)
							.parents(settings.widgetSelector) 
							.find('.edit-box') 
							.slideUp();
						return false;
					}).appendTo($(settings.handleSelector, this));
			}
			
			if (thisWidgetSettings.refreshable) {
				$('<a href="#" class="refresh">REFRESH</a>').mousedown(function (e) {
						e.stopPropagation();
					})
					.addClass('widget-refresh')
					.click(function () {
						var widget = $(this).parents(settings.widgetSelector);
						var form = widget.find('.edit-box form').eq(0);
						
						//clear any previous form field data so we don't resubmit on refresh
						form.find('input[type="text"], input[type="hidden"], select, textarea').each(function(i, elm) {
							if ($(elm).attr('name') != 'submit' && $(elm).attr('name') != 'widget_pkey') {
								$(elm).val('');
							}
						});						
						
						$.post(form.attr('action'), form.serialize(), function(data) {
							widget.find(settings.contentSelector).html(data);
						});			
					}).appendTo($(settings.handleSelector, this));
			}	

			//disable enter key to submit
			$(thisWidget).find('.edit-box form').submit(function(event) {
				return false;
			});
						
			//capture and ajax post widget forms
			$(thisWidget).find('.widget-edit-submit').click(function(event) {
				var form = $(thisWidget).find('.edit-box form').eq(0);

				$(thisWidget).find(settings.handleSelector + ' .edit').click();
					
				$.post(form.attr('action'), form.serialize(), function(data) {
					$(thisWidget).find(settings.contentSelector).html(data);
				});			
			});
			
			//capture and handle widget edit cancel
			$(thisWidget).find('.widget-edit-cancel').click(function(event) {
				$(thisWidget).find(settings.handleSelector + ' .edit').click();
			});			
		});
	},
	
	createWidgetIcons : function() {
		var Widgets = this, 
			$ = this.jQuery, 
			settings = this.settings;
			
		$(settings.iconsSelector).html('');
		$(settings.iconsSelector).sortable('destroy');

		$('.widget').each(function(i, elm) {
			$('<div/>')
				.html($(elm).find('.widget-icon').html() + '<br/>' + $(elm).find(settings.handleSelector + ' h3').html())
				.addClass('widget-icon')
				.attr('pkey', $(elm).attr('pkey'))
				.click(function() {
					$('body').animate({scrollTop:0}, 'slow', function() { 
						Widgets.fadeWidget(i);
						return false;
					}); 
				})
				.appendTo(settings.iconsSelector);
		});
		$('<br/>')
			.addClass('clear')
			.appendTo(settings.iconsSelector);
		$(settings.iconsSelector).sortable({
			items: $(settings.iconsSelector + ' div'),
			containment: 'document',
			cursor: 'move',
			delay: 100,
			placeholder: 'widget-placeholder',
			connectWith: $(settings.iconsSelector),
			forcePlaceholderSize: true,
			revert: 300,
			opacity: 0.8,
			start: function(e, ui) {
				sortStart = $(ui.item).parent().children().index(ui.item);
			},
			stop: function(e, ui) {
				sortEnd = $(ui.item).parent().children().index(ui.item);
				$.get('/_queries/widget_sort_post.php', {
						pkey: $(ui.item).attr('pkey'),
						pos_start: sortStart + 1,
						pos_stop: sortEnd + 1			
					});
			}
		});
		$(settings.iconsSelector).disableSelection();
	},
	
	setWidgetContainerHeight : function(instant) {
		var Widgets = this, 
			$ = this.jQuery, 
			settings = this.settings;
			
		if ($('.widgets').height() != ($(settings.widgetSelector).slice(Widgets.currentWidget, Widgets.currentWidget+1).height()+20)) {
			$('.widgets').animate({
				height:($(settings.widgetSelector).slice(Widgets.currentWidget, Widgets.currentWidget+1).height()+20)+'px'
			}, (instant)?0:1000);		
		}
	},
	
	widgetsSwipeStatus : function(event, phase, direction, distance) {
		var Widgets = this, 
			$ = this.jQuery, 
			settings = this.settings;

		//If we are moving before swipe, and we are going L or R in X mode, or U or D in Y mode then drag.
		if( phase=="move" && (direction=="left" || direction=="right") ) {
			var duration=0;
				
			if (direction == "left") {
				Widgets.scrollWidgets((Widgets.widgetWidth * Widgets.currentWidget) + distance, duration);
			} else if (direction == "right") {
				Widgets.scrollWidgets((Widgets.widgetWidth * Widgets.currentWidget) - distance, duration);
			}
		} else if ( phase == "cancel") {
			Widgets.scrollWidgets($(settings.widgetSelector).slice(Widgets.currentWidget, Widgets.currentWidget+1).position().left, 500);
		} else if ( phase =="end" ) {
			if (direction == "right") {
				Widgets.previousWidget();
			} else if (direction == "left") {
				Widgets.nextWidget();
			}
		}
	},

	previousWidget : function() {
		var Widgets = this, 
			$ = this.jQuery, 
			settings = this.settings;
			
		Widgets.currentWidget = Math.max(Widgets.currentWidget-1, 0);
		Widgets.scrollWidgets( $(settings.widgetSelector).slice(Widgets.currentWidget, Widgets.currentWidget+1).position().left, 500);
	},

	nextWidget : function() {
		var Widgets = this, 
			$ = this.jQuery, 
			settings = this.settings;
			
		Widgets.currentWidget = Math.min(Widgets.currentWidget+1, $(settings.widgetSelector).length - 1);
		Widgets.scrollWidgets( $(settings.widgetSelector).slice(Widgets.currentWidget, Widgets.currentWidget+1).position().left, 500);
	},
					
	scrollWidgets : function(distance, duration) {
		var Widgets = this, 
			$ = this.jQuery, 
			settings = this.settings;
			
		var w = $('.widgets .scroll');		
		var value = (distance<0 ? "" : "-") + Math.abs(distance).toString();
		
		w.animate({ left: value }, duration);
		
		Widgets.setWidgetContainerHeight();
	},

	fadeWidget : function(index) {
		var Widgets = this, 
			$ = this.jQuery, 
			settings = this.settings;

		if ($(settings.widgetSelector).length == 0) {
			Widgets.currentWidget = 0;
		} else {
			Widgets.currentWidget = index;
			Widgets.scrollWidgets( $(settings.widgetSelector).slice(Widgets.currentWidget, Widgets.currentWidget+1).position().left, 0);

			$(settings.widgetSelector).slice(Widgets.currentWidget, Widgets.currentWidget+1).css({ opacity:0.0 }).animate({ opacity:1.0 }, 500);
		
			Widgets.setWidgetContainerHeight();
		}
	},
	
	widgetContentSwipeStatus : function(event, phase, direction, distance) {
		var Widgets = this, 
			$ = this.jQuery, 
			settings = this.settings;
		
		//If we are moving before swipe, and we are going L or R in X mode, or U or D in Y mode then drag.
		if( phase=="move" && (direction=="up" || direction=="down") ) {
			var duration=0;
				
			if (event == null) event = window.event;
			var thisTarget = (typeof(event.target) != 'undefined') ? event.target : event.srcElement;
			var srcElm = $(thisTarget).parents(settings.widgetSelector).eq(0).find(settings.contentSelector).eq(0);
			var curScroll = srcElm.scrollTop();
			
			if (direction == "up") {
				srcElm.scrollTop(curScroll + (Math.abs(distance) - Widgets.oldContentScrollDistance));
				
			} else if (direction == "down") {
				srcElm.scrollTop(curScroll - (Math.abs(distance) - Widgets.oldContentScrollDistance));
			}
			Widgets.oldContentScrollDistance = Math.abs(distance);
		} else if ( phase == "cancel") {
			Widgets.oldContentScrollDistance = 0;
		} else if ( phase =="end" ) {
			Widgets.oldContentScrollDistance = 0;
		}
	},
	
	widgetsResize : function() {
		var Widgets = this, 
			$ = this.jQuery, 
			settings = this.settings;
	
		Widgets.widgetWidth = $('.widgets').width() + 20;

		$('.widgetTableStack').remove();
		
		$(settings.widgetSelector).each(function(i, elm) {
			$(elm).css({ width: ($('.widgets').width() - 4)+'px' });
			
			//if mobile and small screen, reformat tables into stacks
			if (isMobile && $(window).width() < 768) {
				$(elm).find('table.grid[id]').each(function(i, grid) {
					$(grid)
						.closest('.dataTables_wrapper')
						.hide();
					
					//convert widget tables into stacks on the fly
					var newTable = $('<table/>')
						.css({ width: '100%' })
						.addClass('widgetTableStack')
						.insertAfter($(grid).closest('.dataTables_wrapper'));
					
					//loop over each row in the master table
					$(grid).find('tbody tr').each(function(i, row) {
						var newTr = $('<tr/>')
							.appendTo(newTable);
						var newTd = $('<td/>')
							.css({ padding: '10px 0px', borderBottom: '1px solid #ccc' })
							.appendTo(newTr);						
							
						//loop over reach cell in the master table
						$(row).find('td').each(function(i, cell) {
							newTd.append('<strong>' + $(grid).closest('.dataTables_wrapper').find('.dataTables_scrollHeadInner thead th').eq(i).html() + ':</strong> ' + $(cell).html()+'<br/>');
						});					
					});					
				});			
			} else {
				$(elm).find('table.grid[id]').each(function(i, grid) {					
					$(grid)
						.closest('.dataTables_wrapper')
						.show();
					$(grid)
						.dataTable()
						.fnAdjustColumnSizing();
				});
			}
		});
		Widgets.scrollWidgets( Widgets.widgetWidth * Widgets.currentWidget, 0);
	}
	
};

/* INIT AND RESIZE WHEN WINDOW IS LOADED =================================== */	

$(window).load(function() {
	if (Widgets.widgetQueue.length) {
		var widgetsLoadedCount = 0;
		$('.widgets').hide();
		_(Widgets.widgetQueue).each(function(rec, i) {
			$.ajax({
				type: 'POST',
				url: rec.url,
				global: false,
				data: { widget_pkey: rec.widgetPkey },
				success: function(data, status, xhr) {
					widgetsLoadedCount++;
					$('.widgetsLoadingProgressBar').animate({ width: parseInt(widgetsLoadedCount / Widgets.widgetQueue.length * 100) + '%' }, 50);
					
					rec.loaded = true;
					$('#widget_'+rec.widgetPkey).html(data);
					
					var ready = _(Widgets.widgetQueue).all(function(rec) {
						return rec.loaded;
					});
					
					if (ready) {
						$('.widgetsLoading').remove();
						$('.widgets').show();
						Widgets.init();						
						Widgets.widgetsResize();				
						$('.widgets, #widget-icons').hide().fadeIn('slow');
					} else {
						$('.widgetsLoading').append('<div style="float:left; margin:0px 10px 10px 0px;">' + $('#widget_'+rec.widgetPkey).find('.widget-icon').html() + '</div>');
					}
				}
			});
		});
	} else {
		if (!isMobile && $('.widgets').length == 0) {
			$('#widget-help').show();
		}
	}
});
	
