/*
	Плагин для загрузки изобрадений. Разработан под ileete CMS.
	После завершения будет возможность портировать плагин под дургие системы.
	Автор некто Siriel.
	
	Принцип работы: плагин применяется к полю типа input, 
	в которое после загрузки картинки будет помещен либо URL или название 
	(в зависимости от того, что вернет плагину ваш backend)
*/

(function($) {
	
	$.ileeteImageUploader = function (element, options) {
		var element = $(element);
		
		var default_options = {
			parent: element.parent(), // контейнер, в который будет выводится содержимое, генерируемое плагином. По-умолчанию, содержимое будет добавляться туда же, где находится input, к которому был применен плагин.
			images_url: '', // URL к папке, в которую будут заливаться картинки. Данный параметр будет добавляться в начало значения, которое вернет ваш backend. Если backend возвращает полный URL или правильный относительный - эту опцию следует оставить пустой.
			preview_url: '', // URL к папке, куда попадает preview изображения (обработанная версия)
			thumb_url: '', // URL к папке, куда попадает thumb изображения (уменьшенная версия)
			add_image_url: '', // URL для изображения "Нет изображения. Добавить"
			backend_url: '', // URL backend'а, по которому будет высылаться картинка
			auto_init: false, // Если true - после иниализации плагина открывается диалоговое окно для загрузки
			aspect_ratio: '', // соотношение сторон изображения для live crop'а. Пример '4 : 3'
			min_height: null, // минимальная высота изображения для live crop'а
			min_width: null, // минимальная ширина изображения для live crop'а
			callback: null, // callback функция, которая будет вызвана после завершения работы плагина (после выбора изображения, удаления, или отмены)
			actions: {'add' : true, 'edit' : true, 'delete' : true, 'info' : false, 'insert' : false}, // массив с доступными действиями над картинкой: добавление (отврывает окно кропа), редактирование (отврывает окно кропа), удаление (удаляет плагин), инфо (открывает предпросмотр с кнопками готово, изменить, удалить, отмена)
			default_action: 'info' // дейслвие по умолчанию, если установлен параметр auto_init; принимает "info" или "edit"
		};
		
		var parent = options.parent || default_options.parent;
		var images_url = options.images_url || default_options.images_url;
		var preview_url = options.preview_url || default_options.preview_url;
		var thumb_url = options.thumb_url || default_options.thumb_url;
		var add_image_url = options.add_image_url || default_options.add_image_url;
		var backend_url = options.backend_url || default_options.backend_url;
		var auto_init = options.auto_init || default_options.auto_init;
		var aspect_ratio = options.aspect_ratio || default_options.aspect_ratio;
		var min_height = options.min_height || default_options.min_height;
		var min_width = options.min_width || default_options.min_width;
		var callback = options.callback || default_options.callback;
		var actions = options.actions || default_options.actions;
		var default_action = options.default_action || default_options.default_action;
		
		
		var plugin_html = $('<div class="-ileete-image-uploader-wrapper"></div>'); // инициализация тела плагина
		
		plugin_html.html(
			'<img class="-ileete-image-uploader-preview" width="120" height="90" src="">' +
			'<div class="-ileete-image-uploader-preview-actions">' + 
				'<a href="javascript:void(0);" class="-ileete-upload-image-action" rel="add" style="display: none;">Добавить</a>' + 
				'<a href="javascript:void(0);" class="-ileete-upload-image-action" rel="insert" style="display: none;">Вставить</a>' + 
				'<a href="javascript:void(0);" class="-ileete-upload-image-action" rel="edit" style="display: none;">Изменить</a>' + 
				'<a href="javascript:void(0);" class="-ileete-upload-image-action" rel="delete" style="display: none;">Удалить</a>' + 
				'<a href="javascript:void(0);" class="-ileete-upload-image-action" rel="info" style="display: none;">Инфо</a>' + 
			'</div>'
		);
		
		var blank_file_input = '<input size="34" type="file" id="" name="image_file" class="-ajax-image-file-button" />';
		var blank_url_input = '<input type="text" id="" class="-ajax-image-url" name="image_url" />';
		
		var plugin_dialog_crop_html = $(
			'<div class="-ajax-image-form-wrapper">' + 
				'<h1>Загрузка изображения</h1>' + 
				'<form class="-ajax-image-form" action="' + backend_url + '" method="POST" enctype="multipart/form-data" >' + 
					'<table class="-ajax-image-form-table">' +
						'<tr>' +
							'<td>1.</td>' +
							'<td class="-ajax-image-left-column"><label class="-ajax-image-form-label">Введите URL</label></td>' + 
							'<td>' + blank_url_input + '</td>' + 
						'</tr>' +
						'<tr>' +
							'<td></td>' +
							'<td class="-ajax-image-left-column"><label class="-ajax-image-form-label">или загрузите</label></td>' + 
							'<td>' + blank_file_input + '</td>' + 
						'</tr>' +  
						'<tr>' +
							'<td>2.</td>' +
							'<td class="-ajax-image-left-column"><label class="-ajax-image-form-label">И нажмите</label></td>' + 
							'<td><input type="submit" value="Загрузить" class="-ajax-upload-image" /></td>' + 
						'</tr>' + 
					'</table>' +
					
					'<input type="hidden" class="-uploaded-image-name" name="image_image_name" value="' + element.val() + '" />' + 
					'<input type="hidden" class="-crop-x1" name="image_x1" value="" />' + 
					'<input type="hidden" class="-crop-y1" name="image_y1" value="" />' + 
					'<input type="hidden" class="-crop-x2" name="image_x2" value="" />' + 
					'<input type="hidden" class="-crop-y2" name="image_y2" value="" />' + 
					
					'<br />' + 
					
					'<div class="-ajax-uploaded-image-wrapper" >' + 
						'<img src="" class="-ajax-uploaded-image" style="display:none;" />' + 
					'</div>' + 
				'</form>' + 
				
				'<div class="-ajax-image-buttons">' +
					'<input type="button" value="Готово" class="-ajax-confirm-image" />' + 
					'<input type="button" value="Отмена" class="-ajax-cancel-image" />' + 
				'</div>' + 
			'</div>'); // инициализация всплывающего окна для загрузки изображения
			
		var plugin_dialog_view_html = $(
			'<div class="-ajax-image-form-wrapper">' + 
				'<h1>Загруженное изображение</h1>' + 
				'<form class="-ajax-image-form" action="' + backend_url + '" method="POST" enctype="multipart/form-data" >' + 
					'<div class="-ajax-uploaded-image-wrapper" >' + 
						'<img src="" class="-ajax-uploaded-image" style="display:none;" />' +
					'</div>' +
					
					'<div class="-ajax-image-buttons">' +
						'<input type="button" value="Готово" class="-ajax-confirm-image" />' + 
						'<input type="button" value="Изменить" class="-ajax-change-image" />' + 
						'<input type="button" value="Удалить" class="-ajax-delete-image" />' + 
						'<input type="button" value="Отмена" class="-close-ajax-form" />' + 
					'</div>' + 
				'</form>' +
			'</div>'
		); // инициализация всплывающего окна для загрузки изображения
		
		bindClickEvent(); // Навешивание события на ссылку в теле плагина
		
		parent.append(plugin_html);
		
		function removePlugin()
		{
			if(element.data('ileeteImageUploader')) {
				element.removeData('ileeteImageUploader');
				plugin_html.remove();
			}
		}
		
		function refresh()
		{
			if(element.val()) {
				if(actions['add']) { plugin_html.find('.-ileete-upload-image-action[rel="add"]').hide(); }
				if(actions['insert']) { plugin_html.find('.-ileete-upload-image-action[rel="insert"]').show(); }
				if(actions['edit']) { plugin_html.find('.-ileete-upload-image-action[rel="edit"]').show(); }
				if(actions['delete']) { plugin_html.find('.-ileete-upload-image-action[rel="delete"]').show(); }
				if(actions['info']) { plugin_html.find('.-ileete-upload-image-action[rel="info"]').show(); }
				
				plugin_html.find('img.-ileete-image-uploader-preview').attr('src', thumb_url + element.attr('value'));
			}
			else {
				if(actions['add']) { plugin_html.find('.-ileete-upload-image-action[rel="add"]').show(); }
				if(actions['insert']) { plugin_html.find('.-ileete-upload-image-action[rel="insert"]').hide(); }
				if(actions['edit']) { plugin_html.find('.-ileete-upload-image-action[rel="edit"]').hide(); }
				if(actions['delete']) { plugin_html.find('.-ileete-upload-image-action[rel="delete"]').hide(); }
				if(actions['info']) { plugin_html.find('.-ileete-upload-image-action[rel="info"]').hide(); }
				
				plugin_html.find('img.-ileete-image-uploader-preview').attr('src', add_image_url);
			}
		}
		refresh();
		
		this.removePlugin = removePlugin;
		this.refresh = refresh;
		
		// ========================================== //
		// AJAX загрузка и live-crop картинок. Начало //
		function bindClickEvent()
		{
			var imageAreaSelectInstance = null;
			
			var new_image = null; /* Имя загруженной или перемасштабированной картинки */
			var current_image = element.attr('value'); /* Имя картинки в форме добавления (после загрузки и масштабирования) */
			
			function removeAjaxImagesUploadForm(event_name) {
				current_image = element.attr('value');
				if(imageAreaSelectInstance) {
					imageAreaSelectInstance.remove();
				}
				$('.-ajax-image-form-wrapper').remove();
				if(typeof(callback) == 'function') {
					callback(event_name, null, element);
				}
			}
				
			function showViewForm() {
				var dialog_image_name = new_image || current_image; // имя изображения, для которого отображается preview

				if(!dialog_image_name) {
					removeAjaxImagesUploadForm('close');
					return false;
				}
				else {
					removeAjaxImagesUploadForm();
				}
				
				$('body').append(plugin_dialog_view_html);
				
				var dialog_image_wrapper = plugin_dialog_view_html.find('.-ajax-uploaded-image-wrapper');
				var dialog_image = plugin_dialog_view_html.find('img.-ajax-uploaded-image'); // объект img в всплывающем окне
				
				var delete_button = plugin_dialog_view_html.find('.-ajax-delete-image');
				var edit_button = plugin_dialog_view_html.find('.-ajax-change-image');
				var confirm_button = plugin_dialog_view_html.find('.-ajax-confirm-image');
				var close_button = plugin_dialog_view_html.find('.-close-ajax-form');
				
				if(!new_image) {
					/* Скрыть кнопку "готово", если картинку не загружали */
					confirm_button.hide();
					close_button.show();
				}
				else {
					/* Иначе скрыть кнопку "отмена" */
					confirm_button.show();
					close_button.hide();
				}
				
				delete_button.bind('click', function() {
					element.attr('value', '');
					new_image = null;
					refresh();
					removeAjaxImagesUploadForm('delete');
				});
				
				edit_button.bind('click', function() {
					showCropForm();
				});
				
				confirm_button.bind('click', function() {
					element.attr('value', new_image);
					new_image = null;
					refresh();
					removeAjaxImagesUploadForm('confirm');
				});
				
				close_button.bind('click', function() {
					new_image = null;
					refresh();
					removeAjaxImagesUploadForm('close');
				});
				
				var imgPreloader = new Image();
				random_number = Math.floor(Math.random()*100501);
				imgPreloader.src = preview_url + dialog_image_name + '?' + random_number;
				
				imgPreloader.onload = function() {
					imgPreloader.onload = null;
					
					var imageRealWidth = imgPreloader.width;
					var imageRealHeight = imgPreloader.height;
					// Resizing large images - orginal by Christian Montoya edited by Cody Lindley.
						var de = document.documentElement;
						var w = window.innerWidth || self.innerWidth || (de&&de.clientWidth) || document.body.clientWidth;
						var h = window.innerHeight || self.innerHeight || (de&&de.clientHeight) || document.body.clientHeight;
						var pagesize = [w,h];
						
						var x = pagesize[0]*0.5;
						var y = pagesize[1]*0.5;
						
						if (imageRealWidth > x) {
							imageHeight = imageRealHeight * (x / imageRealWidth); 
							imageWidth = x; 
							if (imageRealHeight > y) { 
								imageWidth = imageRealWidth * (y / imageRealHeight); 
								imageHeight = y; 
							}
						} else if (imageRealHeight > y) { 
							imageWidth = imageRealWidth * (y / imageRealHeight); 
							imageHeight = y; 
							if (imageRealWidth > x) { 
								imageHeight = imageRealHeight * (x / imageRealWidth); 
								imageWidth = x;
							}
						} else {
							imageHeight = imageRealHeight; 
							imageWidth = imageRealWidth;
						}
					// End Resizing
							
					plugin_dialog_view_html.css('margin-top', '-' + imageHeight/2 + 'px');
					plugin_dialog_view_html.css('margin-left', '-' + imageWidth/2 + 'px');
					
					dialog_image.attr('src', preview_url + dialog_image_name + '?' + random_number);
					dialog_image.attr('height', imageHeight);
					dialog_image.attr('width', imageWidth);
					dialog_image.show();
				}
			}
			
			function showCropForm() {
				removeAjaxImagesUploadForm();
				$('body').append(plugin_dialog_crop_html);
				
				var dialog_image_name = current_image; // имя изображения, для которого отображается crop.
				
				var dialog_image_wrapper = plugin_dialog_crop_html.find('.-ajax-uploaded-image-wrapper');
				
				var dialog_image_wrapper = plugin_dialog_crop_html.find('.-ajax-uploaded-image-wrapper');
				var dialog_image = plugin_dialog_crop_html.find('img.-ajax-uploaded-image'); // объект img в всплывающем окне
				var dialog_image_name_input = plugin_dialog_crop_html.find('.-uploaded-image-name'); // имя загруженного изображения
				dialog_image_name_input.val(dialog_image_name);
				
				var confirm_button = plugin_dialog_crop_html.find('.-ajax-confirm-image');
				var cancel_button = plugin_dialog_crop_html.find('.-ajax-cancel-image');
				
				var dialog_image_url_input = plugin_dialog_crop_html.find('.-ajax-image-url');
				var dialog_image_file_input = plugin_dialog_crop_html.find('.-ajax-image-file-button');
				
				var dialog_form = plugin_dialog_crop_html.find('form.-ajax-image-form');
				
				if(!dialog_image_name) {
					/* Скрыть кнопку "готово", если картинку не загружали */
					confirm_button.hide();
				}
				else {
					confirm_button.show();
				}
				
				setImageToCrop(dialog_image_name);
				
				confirm_button.bind('click', function() {
					if(dialog_image_name) {
						dialog_form.triggerHandler('submit');
					}
					else {
						element.attr('value', '');
						refresh();
						removeAjaxImagesUploadForm();
					}
				});
				
				cancel_button.bind('click', function() {					
					refresh();
					removeAjaxImagesUploadForm('close');
				});
				
				function setImageToCrop(image_name) {
					if(dialog_image.data('imgAreaSelect')) {
						dialog_image.data('imgAreaSelect').remove();
					}
					
					if(imageAreaSelectInstance) {
						imageAreaSelectInstance.remove();
					}
					
					if(image_name) {
						var imgPreloader = new Image();
						imgPreloader.src = images_url + image_name;
						
						imgPreloader.onload = function() {
							imgPreloader.onload = null;
							
							var imageRealWidth = imgPreloader.width;
							var imageRealHeight = imgPreloader.height;
							
							if((imageRealWidth < min_width) || (imageRealHeight < min_height)) {
								setImageToCrop();
								alert('Ошибка: Вы пытаетесь загрузить слишком маленькое изображение. Минимальный размер ' + min_width + ' ' + min_height);
								return false;
							}
							
							// Resizing large images - orginal by Christian Montoya edited by Cody Lindley.
								var de = document.documentElement;
								var w = window.innerWidth || self.innerWidth || (de&&de.clientWidth) || document.body.clientWidth;
								var h = window.innerHeight || self.innerHeight || (de&&de.clientHeight) || document.body.clientHeight;
								var pagesize = [w,h];
								
								var x = pagesize[0]*0.5;
								var y = pagesize[1]*0.5;
								
								if (imageRealWidth > x) {
									imageHeight = imageRealHeight * (x / imageRealWidth); 
									imageWidth = x; 
									if (imageRealHeight > y) { 
										imageWidth = imageRealWidth * (y / imageRealHeight); 
										imageHeight = y; 
									}
								} else if (imageRealHeight > y) { 
									imageWidth = imageRealWidth * (y / imageRealHeight); 
									imageHeight = y; 
									if (imageRealWidth > x) { 
										imageHeight = imageRealHeight * (x / imageRealWidth); 
										imageWidth = x;
									}
								} else {
									imageHeight = imageRealHeight;
									imageWidth = imageRealWidth;	
								}
							// End Resizing
							
							plugin_dialog_crop_html.css('margin-top', '-' + (200 + imageHeight)/2 + 'px');
							plugin_dialog_crop_html.css('margin-left', '-' + (imageWidth)/2 + 'px');
							
							dialog_image.attr('src', images_url + image_name);
							dialog_image.attr('height', imageHeight);
							dialog_image.attr('width', imageWidth);
							dialog_image.show();
							
							var selectionX1 = null;
							var selectionY1 = null;
							var selectionX2 = null;
							var selectionY2 = null;
							
							if(aspect_ratio) {
								aspectRatioNum = (d = (aspect_ratio || '').split(/:/))[0] / d[1];
								if((imageRealWidth / imageRealHeight) > aspectRatioNum) {
									//ширина больше, отталкиваемся от высоты
									if(imageRealHeight * 0.94 > min_height) {
										selectionX1 = imageRealHeight * 0;// * aspectRatioNum * 0.03;
										selectionY1 = imageRealHeight * 0;// * 0.03;
										selectionX2 = imageRealHeight * aspectRatioNum ;//* 0.97;
										selectionY2 = imageRealHeight;// * 0.97;
									}
									else {
										selectionX1 = 0;
										selectionY1 = 0;
										selectionX2 = min_width;
										selectionY2 = min_height;
									}
								}
								else {
									//высота больше отталкиваемся от ширины
									if(imageRealWidth * 0.94 > min_width) {
										selectionX1 = imageRealWidth * 0;// * 0.03;
										selectionY1 = imageRealWidth/aspectRatioNum * 0;// * 0.03;
										selectionX2 = imageRealWidth;// * 0.97;
										selectionY2 = imageRealWidth/aspectRatioNum;// * 0.97;
									}
									else {
										selectionX1 = 0;
										selectionY1 = 0;
										selectionX2 = min_width;
										selectionY2 = min_height;
									}
								}
							}
							else {
								selectionX1 = imageRealWidth * 0;// * 0.03;
								selectionY1 = imageRealHeight * 0;// * 0.03;
								selectionX2 = imageRealWidth;// * 0.97;
								selectionY2 = imageRealHeight;// * 0.97;
							}
							
							if((imageRealHeight > imageHeight) && min_height) {
								min_height = imageHeight * min_height / imageRealHeight;
							}
							if((imageRealWidth > imageWidth) && min_width) {
								min_width = imageWidth * min_width / imageRealWidth;
							}
							
							imageAreaSelectInstance = dialog_image.imgAreaSelect({
								instance: true,
								aspectRatio: aspect_ratio, 
								parent: dialog_image_wrapper, 
								persistent: true, 
								handles: true, 
								resizable: true, 
								movable: true, 
								enable: true,
								minHeight: min_height,
								minWidth: min_width,
								
								imageHeight: imageRealHeight,
								imageWidth: imageRealWidth,
								
								x1: selectionX1, y1: selectionY1, x2: selectionX2, y2: selectionY2,
								onInit: function(img, selection) {
									plugin_dialog_crop_html.find('.-crop-x1').val(selection.x1);
									plugin_dialog_crop_html.find('.-crop-y1').val(selection.y1);
									plugin_dialog_crop_html.find('.-crop-x2').val(selection.x2);
									plugin_dialog_crop_html.find('.-crop-y2').val(selection.y2);
								},
								onSelectEnd: function(img, selection) {
									plugin_dialog_crop_html.find('.-crop-x1').val(selection.x1);
									plugin_dialog_crop_html.find('.-crop-y1').val(selection.y1);
									plugin_dialog_crop_html.find('.-crop-x2').val(selection.x2);
									plugin_dialog_crop_html.find('.-crop-y2').val(selection.y2);
								}
							});
							
							if(!image_name) {
								/* Скрыть кнопку "готово", если картинку не загружали */
								confirm_button.hide();
							}
							else {
								/* Иначе скрыть кнопку "отмена" */
								confirm_button.show();
							}
						}
					}
					else {
						plugin_dialog_crop_html.css('margin-top', '-' + plugin_dialog_crop_html.height() + 'px');
						plugin_dialog_crop_html.css('margin-left', '-' + plugin_dialog_crop_html.width()/2 + 'px');
							
						new_image = null;
						dialog_image_name_input.val('');
						dialog_image.attr('src', '');
						dialog_image.hide();
					}
				}
				
				// pre-submit callback 
				function showRequest(formData, jqForm, options) {
					
				}
				
				// post-submit callback 
				function showResponse(responseText, statusText, xhr, $form) {
					if(responseText.data) {
						new_image = responseText.data;
						dialog_image_name = new_image;
						
						if(dialog_image_file_input.val() || dialog_image_url_input.val()) {
							/* Если картинка загружалась - масштабируем */
							dialog_image_name_input.val(new_image);
							setImageToCrop(new_image);
						}
						else {
							/* Иначе она должна быть уже отмасштабирована: показываем preview */
							showViewForm();
						}
						
						/* Очищаем поля ввода файла и урла */
						dialog_image_file_input.replaceWith(blank_file_input);
						dialog_image_file_input = plugin_dialog_crop_html.find('.-ajax-image-file-button');
						dialog_image_url_input.val('');
						
					}
					else {
						setImageToCrop();
						alert('Ошибка: изображение не загружено. Возможно вы указали неправильный ресурс.');
					}
				}
				
				dialog_form.bind('submit', function() {
			    	var options = { 
				        //target:        '#output1',   // target element(s) to be updated with server response 
				        beforeSubmit:  showRequest,  // pre-submit callback 
				        success:       showResponse,  // post-submit callback 
				 		data: { 'download_image' : 'download_image', 'mode': 'ajax' },
				 		dataType: 'json' // 'xml', 'script', or 'json' (expected server response type) 
				        // other available options: 
				        //url: site_url + 'image-manager/upload-image/' // override for form's 'action' attribute 
				        //type:      type        // 'get' or 'post', override for form's 'method' attribute 
				        
				        //clearForm: true        // clear all form fields after successful submit 
				        //resetForm: true        // reset the form after successful submit 
				 
				        // $.ajax options can be used here too, for example: 
				        //timeout:   3000
				    };
			    
					// inside event callbacks 'this' is the DOM element so we first 
					// wrap it in a jQuery object and then invoke ajaxSubmit
					$(this).ajaxSubmit(options);
					
					// !!! Important !!! 
					// always return false to prevent standard browser submit and page navigation
					return false;
			    });
		    	
				return false;
			}
			
			function insertImage() {
				removeAjaxImagesUploadForm('insert');
			}
			
			plugin_html.find('.-ileete-upload-image-action').bind('click', function() {
				var action = $(this).attr('rel');
				
				if(current_image) {
					if(action == 'add') {
						return false;
					}
					else if(action == 'edit') {
						showCropForm();
					}
					else if(action == 'info') {
						showViewForm();
					}
					else if(action == 'delete') {
						element.attr('value', '');
						new_image = null;
						refresh();
						removeAjaxImagesUploadForm('delete');
					}
					else if(action == 'insert') {
						insertImage();
					}
					else {
						showViewForm();
					}
				}
				else {
					if(action != 'add') {
						return false;
					}
					showCropForm();
				}
			});
			
			if(auto_init) {
				auto_init = false;
				
				if(current_image) {
					plugin_html.find('.-ileete-upload-image-action[rel=' + default_action + ']').triggerHandler('click');
				}
				else {
					plugin_html.find('.-ileete-upload-image-action[rel=add]').triggerHandler('click');
				}
			}
		}
		// AJAX загрузка и live-crop картинок. Конец //
		// ========================================= //
		
		refresh();
	}
	
	$.fn.ileeteImageUploader = function(options) {
		options = options || {};
		
		return this.each(function () {
			if (!$(this).data('ileeteImageUploader')) {
				$(this).data('ileeteImageUploader', new $.ileeteImageUploader(this, options));
			}
		});
	};
	
})(jQuery);
