/*
* jQuery plugin for WidgetFormImageFileOrUrl
*
* @author MF
*/
(function( $ ){

	$.fn.imagePreviewer = function(method) {

		var settings = {
			// Location of the server-side upload script:
			action : null,
			// Class for locating the element to place images:
			imgContainerClass : 'div.image-wrap',
			// Class for locating the element to remove images:
			removeClass : 'div.image-wrap a',
			// Class for locating the element to store the image URL:
			hiddenInputClass : 'input[type=hidden]',
			// Class for locating the img element acting as the placeholder:
			placeholderImageClass : 'div.image-wrap img.placeholder',
			// Class to add while executing ajax request:
			loadingClass : 'submitting',
			// Animation speed:
			animationSpeed : 300,
			// The time to wait in milliseconds for the file upload to complete (Default is 5 minutes):
			uploadTimeLimit : 300000,
			// Function called to handle form errors:
			onValidationError : function(errors){
			},
			// Function to handle form save exceptions:
			onExceptionError : function(errors){
			},
			// Function called if file upload time limit is reached:
			onTimeoutError : function(){
			},
			// Function called on succesful upload
			onSuccess : function(obj, response){
			},
			onSubmit : function(obj) {
			}

		};

		var methods = {
			init : function( options ) {
				return this.each(function() {

					var $self = $(this);

					var data = $self.data('imagePreviewer');

					// If the plugin hasn't been initialized yet:
					if ( !data ) {

						if (options) {
							$.extend(settings, options);
						}

						var $fileInput = $self.find('input[type=file]:first');

						var $imgContainer = $self.find(settings.imgContainerClass).first();

						var previewMode = $imgContainer.hasClass('crop') ? 'crop' : 'fixed';

						var $hiddenInput = $self.find(settings.hiddenInputClass).first();

						var $placeholderImg = $self.find(settings.placeholderImageClass).first();

						var $removeLink = $self.find(settings.removeClass).first();

						var $formSubmit = $self.closest('form').find('input[type=submit]').first();

						var uploadTimer = null;

						$removeLink.click(function(e){
							methods.cancel.call($self);
							e.preventDefault();
						});

						// We need the placeholder's loaded width and height to center it:
						$placeholderImg.load(function() {
							centerImg($(this));
						})
						// If the image is cached this forces the load event to fire.
						.each(function() {
							if(this.complete || (jQuery.browser.msie && parseInt(jQuery.browser.version) == 6))
							$(this).trigger("load");
						});

						$placeholderImg.hide();
						$placeholderImg.detach();

						if ($imgContainer.children('img').size() > 0) {

							var initialImage = $imgContainer.children('img:first');

							// We need the thumbnail's loaded width and height to center it:
							initialImage.load(function() {
								centerImg($(this));
							})
							// If the image is cached this forces the load event to fire.
							.each(function() {
								if(this.complete || (jQuery.browser.msie && parseInt(jQuery.browser.version) == 6))
								$(this).trigger("load");
							});

							$removeLink.show();

						} else {

							$placeholderImg.prependTo($imgContainer);

							$placeholderImg.show();

							$removeLink.hide();
						}

						var $ajaxUpload = new AjaxUpload( $fileInput.attr('id'), {
							action: settings.action,
							name: $fileInput.attr('name'),
							autoSubmit: true,
							responseType: 'json',
							data: {
								'width' :   $imgContainer.outerWidth(),
								'height' :  $imgContainer.outerHeight(),
								'mode' : previewMode
							},
							onSubmit: function(file, extension) {

								data.ajaxUpload.disable();

								$formSubmit.attr('disabled', 'disabled');

								$removeLink.fadeOut(data.settings.animationSpeed);

								$self.addClass(settings.loadingClass);

								clearTimeout( data.uploadTimer );

								data.uploadTimer = setTimeout(function() {
									methods.cancel.call($self);
									settings.onTimeoutError.call($self);

									},settings.uploadTimeLimit);

									var newImage = new Image();

									$(newImage).hide();

									// Insert the new image at the back:
									if ($imgContainer.children('img').size() > 0) {

										$imgContainer.children('img').before(newImage);

										$imgContainer.children('img').last().fadeTo(settings.animationSpeed,0.3);

									} else {

										$imgContainer.append(newImage);
									}

									$(newImage).bind('load.newImage', function() {

										centerImg($(newImage));

										if ($imgContainer.children('img').size() > 1) {
											$imgContainer.children('img').last().fadeOut(settings.animationSpeed, function(){
												$(this).remove();
											});
										}

										$removeLink.fadeIn(data.settings.animationSpeed);

										$(newImage).fadeIn(settings.animationSpeed, function(){
											$self.removeClass(settings.loadingClass);

											data.ajaxUpload.enable();
										});

									});

									settings.onSubmit.call($self);
								},
								onComplete: function(file, response) {

									data.formSubmit.removeAttr('disabled');

									clearTimeout( data.uploadTimer );

									if (response.is_valid) {

										$hiddenInput.val(response.image_path);

										// This triggers the onload:
										$imgContainer.children('img').first().attr('src', response.image_path);

                                        this._settings.data.old_filename = response.filename;

										this.setData(this._settings.data);
										// do extra bits defined outside
										settings.onSuccess.call($self, response);

									} else if (!response.is_valid) {

										if (response.form_errors) {
											// Call form validation error function
											settings.onValidationError.call($self, response.form_errors);
										} else if (response.exception) {
											// There has been some sort of exception returned:
											settings.onExceptionError.call($self, response.exception);
										}

										$imgContainer.children('img').first().remove();

										$imgContainer.children('img').last().fadeTo(settings.animationSpeed, 1.0);

										$self.removeClass(settings.loadingClass);

										data.ajaxUpload.enable();
									}
								}
							});

							data = {
								target : $self,
								settings : settings,
								imgContainer : $imgContainer,
								hiddenInput : $hiddenInput,
								placeHolderImg : $placeholderImg,
								removeLink : $removeLink,
								ajaxUpload : $ajaxUpload,
								formSubmit : $formSubmit,
								uploadTimer : uploadTimer
							};

							$(this).data('imagePreviewer', data);
						}
					});
				},
				destroy : function( ) {

					return this.each(function() {

						$(this).removeData('imagePreviewer');

					});

				},
				cancel : function() {

					return this.each(function(){

						var data = $(this).data('imagePreviewer');

						data.hiddenInput.val('');
						data.formSubmit.removeAttr('disabled');

						data.removeLink.fadeOut(data.settings.animationSpeed);

						data.imgContainer.children('img').last().unbind('load.newImage')
						.fadeOut(data.settings.animationSpeed, function(){
							data.imgContainer.children('img').filter(':not(.placeholder)').remove();
							data.target.removeClass(data.settings.loadingClass);
							data.ajaxUpload.enable();
						});

						data.placeHolderImg.clone().prependTo(data.imgContainer).hide().fadeTo(settings.animationSpeed,1.0);
					});
				}
			}

			if ( methods[method] ) {

				return methods[ method ].apply( this, Array.prototype.slice.call( arguments, 1 ));

			} else if ( typeof method === 'object' || ! method ) {

				return methods.init.apply( this, arguments );

			} else {

				$.error( 'Method ' + method + ' does not exist on jQuery.imagePreviewer' );
			}

			function centerImg(el) {
				$(el).css('left', '50%');
				$(el).css('margin-left', '-'+($(el).outerWidth() / 2)+'px');

				$(el).css('top', '50%');
				$(el).css('margin-top', '-'+($(el).outerHeight() / 2)+'px');
			}

		}

		})( jQuery );

