/**
 * MediaManager, a model for Fly's media manager and uploader.
 *
 * Note: private functions are indicated by a leading underscore.
 */
var MediaManager = function () {

	var self = this;
	// Set of extendable defaults including a selector the media-manager dialog
	var defaults = {
		'manager' : '#media-manager',
		'width'   : 900,
		'height'  : 550,
		'title'   : 'Media Manager'
	};
	var options = {};
	var manager = null;
	var currentGallery = null;
	var uploader = null;

	
	/**
	 * Shows the MediaManager's uploader whenever an upload icon or button is
	 * clicked.
	 * @param int galleryId optional id for the currently selected gallery.
	 * Defaults to the MediaManager's currentGallery placeholder.
	 */
	function _showUpload ( galleryId ) {
		uploader = MediaManager.Upload();
		
		if ( galleryId ) {
			uploader.init({ 
				'currentGallery' : galleryId,
				'manager'        : options.manager
			});
		}
		else {
			uploader.init({ 
				'currentGallery' : self.currentGallery,
				'manager'        : options.manager
			});
		}
		
		uploader.open();
	};
	
	/**
	 * Sets up the media manager's buttons and bindings.
	 */
	function _initButtons () {
		// create dialog div if it does not already exist
		if(!$('#media-dialog').length){
			$('body').append('<div id="media-dialog"></div>');
		}
		
		$( options.manager ).find('#uploadMedia')
			.button({disabled:true, icons: {primary: "ui-icon-arrowthick-1-n"}})
			.click(function () {
				_showUpload(self.currentGallery);
			});
		
		$( '#backToGalleries' )
			.button({icons: {primary: "ui-icon-arrowreturnthick-1-w"}})
			.click(function () {
				$( options.manager ).find('#gallery-content').html('<div class="loading">Loading...</div>');
				_refreshManager();
			});
		
		// Bind a click event for the add gallery button and display the add
		// gallery naming dialog.
		$( options.manager ).find('#addGallery')
			.button({icons: {primary: "ui-icon-plus"}})
			.click(function () {
//				$( '#attach' ).button();

				$( '#galleryNameDialog' ).dialog({
					modal   : true,
					buttons : {
						Add   : function () {
							var newGallery = $(this).find('input[name=galleryName]').val();
							var attach = $(this).find('#attach').attr('checked');

							$.ajax ({
								type : 'POST',
								url  : baseUrl + 'gallery/ajax/create',
								data : {
									galleryName : newGallery,
									casUid : casUid,
									objId  : ( attach ) ? options.id : '',
									objType : ( attach ) ? options.type : ''
								},
								success : function ( response ) {
									$('#galleryNameDialog').find('input[name=galleryName]').val('');
									$('#galleryNameDialog').find('#attach').removeAttr('checked').button('refresh');
									$('#galleryNameDialog').dialog('close');
									_refreshManager();
								}
							});
						}
					}
				});
			});
			
			// init delete button
			$('.media-control-delete', options.manager)
				.button({icons: {primary: "ui-icon-trash"}})
				.click(function(){
					var selected = $('.media.ui-selected', options.manager);
					var message = 'Are you sure you wish to delete this piece of media?';
					if(selected.length > 1) {
						message = 'Are you sure you wish to delete these ' + selected.length + ' pieces of media?';
					}
					
					if (confirm(message)) {
						var ids = selected.map(function(){return $(this).data('id')}).get().join('-');
						var types = selected.map(function(){return $(this).data('mediatype')}).get().join('-');

						$(options.manager).find('#gallery-content').html('<div class="loading">Deleting...</div>');

						$.post(baseUrl + 'media/edit/delete',
							{ id: ids, type: types },
							_refreshGallery
						);
					}
				});
			
			// init default button
			$('.media-control-default', options.manager)
				.button({icons: {primary: "ui-icon-star"}})
				.click(function(){
					if ( confirm("Are you sure you'd like to change the default image?") ) {
						var url = $(options.manager).find('.media.ui-selected .media-icon-default').attr('href');
						$.post(url, _refreshGallery);
					}
				});
				
			// init private button
			$('.media-control-private', options.manager)
				.button({icons: {primary: "ui-icon-locked"}})
				.click(function(){
					var selected = $('.media.ui-selected', options.manager);
					var message = 'Marking this piece of media as private will remove its visibility from other users. Are you sure you want to do this?';
					if(selected.length > 1) {
						message = 'Marking these ' + selected.length + ' pieces of media as private will remove their visibility from other users. Are you sure you want to do this?';
					}
					
					if (confirm(message)) {
						var ids = selected.map(function(){return $(this).data('id')}).get().join('-');
						var types = selected.map(function(){return $(this).data('mediatype')}).get().join('-');

						$(options.manager).find('#gallery-content').html('<div class="loading">Deleting...</div>');

						$.post(baseUrl + 'media/edit/private',
							{ id: ids, type: types },
							_refreshGallery
						);
					}
					
				});
				
			// init public button
			$('.media-control-public', options.manager)
				.button({icons: {primary: "ui-icon-unlocked"}})
				.click(function(){
					var selected = $('.media.ui-selected', options.manager);
					var message = 'Marking this piece of media as public will allow anyone to see it. Are you sure you want to do this?';
					if(selected.length > 1) {
						message = 'Marking these ' + selected.length + ' pieces of media as public will allow anyone to see them. Are you sure you want to do this?';
					}
					
					if (confirm(message)) {
						var ids = selected.map(function(){return $(this).data('id')}).get().join('-');
						var types = selected.map(function(){return $(this).data('mediatype')}).get().join('-');

						$(options.manager).find('#gallery-content').html('<div class="loading">Deleting...</div>');

						$.post(baseUrl + 'media/edit/public',
							{ id: ids, type: types },
							_refreshGallery
						);
					}
					
				});
	};
	
	/**
	 * Refreshes the media manager and its tabs
	 * TODO: add in a hook that will reselect whichever tab was selected
	 * pre-refresh
	 */
	function _refreshManager () {
		$( options.manager ).find('#gallery-content').html('<div class="loading">Refreshing...</div>');
		
		$.ajax({
			type     : 'GET',
			url      : baseUrl + 'gallery/ajax/galleries',
			data     : {
				disableHelper : true,
				casUid : casUid,
				objId  : options.id,
				objType : options.type
			},
			success  : function ( response ) {				
				$(options.manager).find('#gallery-content').html( response );
				$('#addGallery').show();
				$('#backToGalleries').hide();
				$('.media-controls').hide();
				
				$( '#galleryTabs' ).tabs();
				
				_initGalleryIcons();
							
				// Add selectable functionality to gallery and media objects
				_initSelectable();
			},
			dataType : 'html'
		});
	};
	
	/**
	 * Refreshes individual galleries whenever media is changed within them.
	 */
	function _refreshGallery ()
	{
		$('#gallery-content', options.manager).html('<div class="loading">Refreshing...</div>');
				
		$.ajax({
			type : 'GET',
			url  : baseUrl + 'gallery/ajax/gallery-grid',
			data : {
				disableHelper : true,
				gallery : self.currentGallery,
    			objId   : options.id,
        		objType : options.type
			},
			success : function ( response ) {
				$('#gallery-content', options.manager).html(response);
				$('#addGallery').hide();
				$('#backToGalleries' ).show();
				$('#uploadMedia').button('enable');
				
				$('.media-controls', options.manager)
					.show()
					.find(':button').blur().button('disable');
				
				_initMediaIcons();
				_initSelectable();
			}
		});
	};
	
	
	/**
	 * Initializes the click events for each icon located on a visible gallery.
	 * It should only be called AFTER the media manager (options.manager) as
	 * recieved content in the form of galleries.
	 */
	function _initGalleryIcons () {
		// Delegate a click event now and after refreshes to the uploadIcon of a gallery
		// This icon will allow users to upload to individual galleries once clicked
		$('.uploadIcon', options.manager).click(function (event) {
			event.preventDefault();
			_showUpload($(this).parents('.gallery').data('id'));
		});
		
		// Delegate a click event now and after refreshes to the attachIcon of a gallery
		// This icon will attach the gallery to whatever object is currently selected
		$('.attachIcon', options.manager).click(function (event) {
			event.preventDefault();
			var galleryId = $(this).parents('.gallery').data('id');
			
			$( options.manager ).find('#gallery-content').html('<div class="loading">Attaching...</div>');
			
			$.ajax({
				type : 'POST',
				url  : baseUrl + 'gallery/ajax/attach-gallery',
				data : {
					disableHelper : true,
					casUid : casUid,
					objId  : options.id,
					objType : options.type,
					gallery : galleryId
				},
				success : function ( response ) {
					_refreshManager();
				}
			});
		});
		
		// Delegate a click event now and after refreshes to the detach icon of an objects gallery
		// This icon is reponsible for removing an attached gallery of an object from that object
		$('.detachIcon', options.manager).click(function ( event ) {
			event.preventDefault();
    	    var answer = confirm('Are you sure you wish to detach (unassociate) this gallery?');
            
            if ( answer ) {   
    			var galleryId = $(this).parents('.gallery').data('id');

    			$( options.manager ).find('#gallery-content').html('<div class="loading">Removing...</div>');
    			
    			$.ajax({
    				type : 'POST',
    				url  : baseUrl + 'gallery/ajax/detach-gallery',
    				data : {
    					disableHelper : true,
    					casUid : casUid,
    					objId  : options.id,
    					objType : options.type,
    					gallery : galleryId
    				},
    				success : function ( response ) {
    					_refreshManager();
    				}
    			});
            }
		});
		
		// Delegate a click event now and after refreshes to the deleteIcon of a gallery
		// This icon will delete a user gallery and only a user gallery when clicked
		$('.deleteIcon', options.manager).click(function ( event ) {
			event.preventDefault();
			var answer = confirm('Are you sure you wish to delete this gallery and its associations? This will also delete all media that is part of this gallery.');
			
			if ( answer ) {
				var galleryId = $(this).parents('.gallery').data('id');

				$( options.manager ).find('#gallery-content').html('<div class="loading">Deleting...</div>');
				
				$.ajax({
					type : 'POST',
					url  : baseUrl + 'gallery/ajax/delete-gallery',
					data : {
						disableHelper : true,
						casUid  : casUid,
						objId   : options.id,
						objType : options.type,
						gallery : galleryId
					},
					success : function ( response ) {
						_refreshManager();
					}
				});
			}
		});
		
		// Delegate click for a gallery's viewing icon
		$('.viewIcon', options.manager).click(function ( event ) {
			event.preventDefault();
			var galleryId = $(this).parents('.gallery').data('id');

			// Set the currentGallery as a simple pointer for gallery refresh whenever a gallery is being viewed
			self.currentGallery = galleryId;			
			_refreshGallery();
		});
		
		//Delegate to the galleries private icons in order to mark the gallery as private
		$('.privateGalleryIcon', options.manager).click(function ( event ) {
			event.preventDefault();
			var answer = confirm("Marking this gallery as private will remove its visibility from other users. Are you sure you want to do this?");
			
			if ( answer ) {
				var galleryId = $(this).parents('.gallery').data('id');

				$( options.manager ).find('#gallery-content').html('<div class="loading">Marking private...</div>');
				
				$.ajax({
					type : 'POST',
					url  : baseUrl + 'gallery/ajax/private',
					data : {
						casUid  : casUid,
						objId   : options.id,
						objType : options.type,
						gallery : galleryId
					},
					success : function ( response ) {
						_refreshManager();
					}
				});
			}
		});
		
		// Delegate to the galleries public icons in order to mark the gallery as public
		$('.publicGalleryIcon', options.manager).click(function ( event ) {
			event.preventDefault();
			var answer = confirm("Marking this gallery as public will allow anyone to see it. Are you sure you want to do this?");
			
			if ( answer ) {
				var galleryId = $(this).parents('.gallery').data('id');

				$( options.manager ).find('#gallery-content').html('<div class="loading">Marking private...</div>');
				
				$.ajax({
					type : 'POST',
					url  : baseUrl + 'gallery/ajax/public',
					data : {
						casUid  : casUid,
						objId   : options.id,
						objType : options.type,
						gallery : galleryId
					},
					success : function ( response ) {
						_refreshManager();
					}
				});
			}
		});
		
		// Delegate to all gallery headers to respond to a click event
		// embed a text field and setup events for blur and enter key press
		$('.galleryHeader', options.manager).click(function ( event ) {
			event.preventDefault();
			event.stopImmediatePropagation();
			
			var self = $(this);
			
			var galleryId = $(this).parents('.gallery').data('id');

			var title = $(this).text();
			var input = $('<input type="text" />');
			$(this).html(input);
			
			$( input )
				.val(title)
				.select()
				.bind('blur', function ( event ) {
    			    var newName = input.val();
					
					/** If the text is the same return and don't sumbit */
					if ( newName === title || newName === '') {
						input.remove();
						self.text(title);
						return;
					}
    				
        			// Perform some basic XSS prevention here
            		newName = newName.replace(/</g, "&lt;").replace(/>/g, "&gt;");
                	newName = newName.replace(/[\"\'][\s]*javascript:(.*)[\"\']/gi, "\"\"");
                    newName = newName.replace(/script(.*)/gi, "");    
                    newName = newName.replace(/eval\((.*)\)/gi, "");
					
					/* Submit the changes */
					$.ajax({
						type : 'POST',
						url  : baseUrl + 'gallery/ajax/rename-gallery',
						data : {
							casUid      : casUid,
							gallery     : galleryId,
							galleryName : newName
						},
						success : function ( title ) {
							input.remove();
							self.text(title);
						}
					})
				})
				.bind('keypress', function ( event ) {
					var code = ( event.keyCode ) ? event.keyCode : event.which;
					
					if ( code == 13 ) {
    				    var newName = input.val();
        			    
						/** If the text is the same return and don't sumbit */
						if ( newName === title || newName === '' ) {
							input.remove();
							self.text(title);
							return;
						}
    					
        				// Perform some basic XSS prevention here
            			newName = newName.replace(/</g, "&lt;").replace(/>/g, "&gt;");
            			newName = newName.replace(/[\"\'][\s]*javascript:(.*)[\"\']/gi, "\"\"");
            			newName = newName.replace(/script(.*)/gi, "");    
            			newName = newName.replace(/eval\((.*)\)/gi, "");
						
						/* Submit the changes */
						$.ajax({
							type : 'POST',
							url  : baseUrl + 'gallery/ajax/rename-gallery',
							data : {
								casUid      : casUid,
								gallery     : galleryId,
								galleryName : newName
							},
							success : function ( title ) {
								input.remove();
								self.text(title);
							}
						})
					}
				});
		});
	};
	
	/**
	 * Media Icon Bindings
	 * Private function that will init the event delegations for each media icon
	 * These sets of icons are separate from the gallery icons
	 */
	function _initMediaIcons ()
	{
		// Bind delete icon
		$('.media-icon-delete', options.manager).click(function ( event ) {
			event.preventDefault();
			
			if ( confirm('Are you sure you wish to delete this piece of media?') ) {
				$.post(this.href, _refreshGallery);
			}
		});
		
		// Delegate for privateIcons on pieces of media.
		// Clicking will mark that piece of media as private
		$('.privateIcon', options.manager).click(function ( event ) {
			event.preventDefault();
			
			if ( confirm("Marking this piece of media as private will remove its visibility from other users. Are you sure you want to do this?") ) {
				$.post(this.href, _refreshGallery);
			}
		});
		
		// Delegate for publicIcons on pieces of media.
		// Clicking will mark that piece of media as public
		$('.publicIcon', options.manager).click(function ( event ) {
			event.preventDefault();

			if ( confirm("Marking this piece of media as public will allow anyone to see it. Are you sure you want to do this?") ) {
				$.post(this.href, _refreshGallery);
			}
		});
		
		// Delegate for media viewing icons on a piece of media. Should open a shadowbox containing the embedded media
		$('.media-icon-view', options.manager).colorbox({
			rel: true,
			current:false,
			title: function(){
				return $(this).parents('.media').find('.mediaHeader').text();
			}
		});
//		$('.media-icon-view', options.manager).click(function ( event ) {
//			event.preventDefault();
//			var title = $(this).parents('.media').find('.mediaHeader').text();
//			$(this).colorbox({title: title});
//		});
    	
        // Delegate clicks to the make this image the default media icon, forces override for any previous default image
		$('.media-icon-default', options.manager).click(function ( event ) {
			event.preventDefault();

			if ( confirm("Are you sure you'd like to change the default image?") ) {
				$.post(this.href, _refreshGallery);
			}
		});
		
		// Allow users to edit media title in place
		$('.mediaHeader', options.manager).click(function ( event ) {
			event.preventDefault();
			var self = $(this);
			
			var mediaId   = $(this).parents('.media').data('id');
			var mediaType = $(this).parents('.media').data('mediatype');

			var title = $(this).text();
			var input = $('<input type="text" />');
			$(this).html(input);
			
			input
				.val(title)
				.select()
				.bind('blur', function ( event ) {
					var $newName = $(input).val();
    				
					// If the text is the same return and don't sumbit
					if ( $newName === title || $newName === '' ) {
						$(input).remove();
						self.text(title);
						return;
					}
					
    				
        			// Perform some basic XSS prevention here
            		$newName = $newName.replace(/</g, "&lt;").replace(/>/g, "&gt;");
            		$newName = $newName.replace(/[\"\'][\s]*javascript:(.*)[\"\']/gi, "\"\"");
            		$newName = $newName.replace(/script(.*)/gi, "");    
            		$newName = $newName.replace(/eval\((.*)\)/gi, "");
					
					// Submit the changes
					$.ajax({
						type : 'POST',
						url  : baseUrl + 'media/edit/rename',
						data : {
							casUid : casUid,
							media  : mediaId,
							type   : mediaType,
							title  : $newName
						},
						success : function ( title ) {
							$(input).remove();
							self.text(title);
						}
					})
				})
				.bind('keypress', function ( event ) {
					var code = ( event.keyCode ) ? event.keyCode : event.which;
					
					console.log(code);
					
					if ( code == 13 ) {
    				    var $newName = $(input).val();
        			    
						// If the text is the same return and don't sumbit
						if ( $newName === title || $newName === '') {
							$(input).remove();
							self.text(title);
							return;
						}
						
    					// Perform some basic XSS prevention here
    					$newName = $newName.replace(/</g, "&lt;").replace(/>/g, "&gt;");
    					$newName = $newName.replace(/[\"\'][\s]*javascript:(.*)[\"\']/gi, "\"\"");
    					$newName = $newName.replace(/script(.*)/gi, "");    
    					$newName = $newName.replace(/eval\((.*)\)/gi, "");
        				
						// Submit the changes
						$.ajax({
							type : 'POST',
							url  : baseUrl + 'media/edit/rename',
							data : {
								casUid : casUid,
								media  : mediaId,
								type   : mediaType,
								title  : $newName
							},
							success : function ( title ) {
								$(input).remove();
								self.text(title);
							}
						})
					}
				});
		});
	};
	
	// Initialize the selectable functionality for galleries and media
	function _initSelectable()
	{		
		$('#gallery-content', options.manager).selectable({
			filter   : '.gallery',
			cancel   : 'a, .galleryHeader, .mediaHeader',
			selected : function ( event, ui ) {
				self.currentGallery = $( event.target ).find('.ui-selected').data('id');
			},
			stop : function ( event, ui ) {
				$('#uploadMedia', options.manager).button({disabled:true});
				
				if ( $('div.ui-selected', this).length == 1 ) {
					$('#uploadMedia', options.manager).button({disabled:false});
				}
			}
		});
		
		// handle image selection
		$('#mediaGallery', options.manager).selectable({
			cancel   : 'a, .mediaHeader',
			stop : function ( event, ui ) {
				$('.media-control-default', options.manager).button({disabled:true});
				$('.media-control-delete', options.manager).button({disabled:true});
				$('.media-control-private', options.manager).button({disabled:true});
				$('.media-control-public', options.manager).button({disabled:true});
					
				var selected = $('div.ui-selected', this);
				if ( selected.length) {
					$('.media-control-delete', options.manager).button({disabled:false});
					$('.media-control-private', options.manager).button({disabled:false});
					$('.media-control-public', options.manager).button({disabled:false});
					
					if(selected.length === 1 && selected.data('mediatype') === 'IMAGE') {
						$('.media-control-default', options.manager).button({disabled:false});
					}
				}
				
			}
		});
	};
	
	// Public Methods
	// --------------
	//

	/**
	 * Opens the Media Manager window
	 */
	function open() {
		
        if ( $( options.manager ).dialog('isOpen') ) {
            return;
        }
        
		$( options.manager ).html('<div class="loading">Loading...</div>');
		
		if ( casUid > 0 ) {
			// Init manager display
			$.ajax({
				type     : 'GET',
				url      : baseUrl + 'gallery/ajax/manage',
				data     : {
					casUid : casUid,
					objId  : options.id,
					objType : options.type,
					disableHelper : true
				},
				success  : function ( managerResponse ) {            	    
					$.ajax({
						type     : 'GET',
						url      : baseUrl + 'gallery/ajax/galleries',
						data     : {
							disableHelper : true,
							casUid  : casUid,
							objId   : options.id,
							objType : options.type
						},
						success  : function ( response ) {
							// Wait until everything has been retrieved and then bind/add
							$( options.manager ).html( managerResponse );
							
							// Bind the side buttons of the media manager or disable them
							_initButtons();
							
							$( options.manager ).find('#gallery-content').html( response );
							
							// Tab out the media manager into object galleries and user galleries
							$( '#galleryTabs' ).tabs();
							
							// Initialize the gallery icons and their event bindings
							_initGalleryIcons();
							
							// Initialize the media icons for galleries
							_initMediaIcons();
							
							// Add selectable functionality to gallery and media objects
							_initSelectable();
														
							
							
						},
						dataType : 'html'
					});
					
					// Setup the default gallery id
					self.currentGallery = $( options.manager ).find('#defaultGallery').parent().attr('data-id');
				},
				dataType : 'html'
			});
		}
		
		
		// Bind to the custom event for the uploader whenever the queue completes
		$( options.manager ).bind('onQueueComplete', function (event) {
			_refreshManager();
		});
			
		// Open the manager
		manager.dialog('open');
	};
	
	/**
	 * Initializes the media manager.
	 * Creates an easily accessible dialog that contains all controls for
	 * uploading, removing, and changing media.
	 * @param object config An object of key value pairs that can be used to
	 * alter the function and display the manager
	 */
	function init ( config ) {
		$.extend( options, defaults, config );
		
		// Create a manager node if it doesn't exist
		if ( $( options.manager ).length == 0 ) {
			$('body').append('<div id="' + options.manager.split('#')[1] + '" style="display:none;"></div>');
		}
		
		// Initialize the dialog with from the module's options
		$( options.manager ).dialog({
			autoOpen  : false,
			title     : options.title,
			width     : options.width,
			height    : options.height,
			minWidth  : options.width,
			minHeight : options.height,
			modal     : true,
			resizable : false,
    		close     : function () {
        	    window.location.reload();
    		},
			buttons   : {
				Close  : function () {
					$(this).dialog('close');
				}
			}
		});
		
		manager = $( options.manager );
	};
	
	// Module Return
	// -------------
	return {
		init : init,
		open : open,
		currentGallery : self.currentGallery
	}
};

