
$_SET_DEFAULT = true;

$_URL_UPLOADS = 'upload.php';

var AvatarUploader = Class.create({

	initialize:	function(options) {
	
		if (!(this.element = $(options['element']))) return false;
		
		this.onClick = this.click.bindAsEventListener(this);
		
		this.preview = this.element.down('.avatar_preview');
		
		this.toggeler = this.element.down('.avatar_resizer_toggle').observe('click', this.onClick);
		
		this.remover = this.element.down('.avatar_remove').observe('click', this.onClick);
		
		if (!this.preview.down('img')) {
		
			this.preview.hide();
			
			this.remover.hide();
			
			this.element.down('.avatar_info').hide();
		
		} else {
		
			this.element.down('.avatar_browse').value = 'Выбрать другую картинку';
		
		}
		
		this.resizer = this.element.down('.avatar_resizer').hide();
		
		new AjaxUpload(this.element.down('.avatar_browse'), {
		
			action:		$_URL_UPLOADS,
			
			name:		'userfile',
	        
	        responseType:	'json',
	        
	        onSubmit:	function(file , ext){
	        
	        	this.ext = ext;
	        
	        	var allowed = new RegExp('^(jpg|png|bmp|gif)$');
	        
                if (! (this.ext && allowed.test(this.ext))){
                
                    alert('Ошибка: неправильный формат файла.\nРазрешенные форматы: jpg, gif, png, bmp.');
                    
                    return false;
                        
                }
                
	        }.bind(this),
	        
	        onComplete: function(file, obj) {
	        
	        	if (obj != "error") {
	        		
	        		if (obj.href) {
	        		
	        			var image = new Image();
	        			
	        			image.src = obj.href;
	        			
	        			if (!this.element.down('input[name="pict"]')) {
	        			
	        			    this.element.insert(
	        			    
		        				new Element('input', {'type': 'hidden', 'name': 'pict', 'value': 'ok'})
	        			    
	        			    ).insert(
	        			    
		        			    new Element('input', {'type': 'hidden', 'name': 'filename', 'value': obj.href})
	        			    
	        			    )
	        			
	        			} else {
	        			
	        				this.element.down('input[name="filename"]').value = obj.href;
	        			
	        			}
	        				
	        			new PeriodicalExecuter(function(pe) {
	        			
	        				if ($(image).getNaturalSize().height > 0) {
	        				
	        					pe.stop();
	        					
	        					image = null;
	        					
	        					this.render(obj.href);
	        				
	        				}
	        			
	        			}.bind(this), 0.2);
	        		
	        		}
	        		
	        	} else {
	        	
	        		alert(obj);
	        	
	        	}
	        
	        }.bind(this)
		
		});
		
		return this;
	
	},
	
	render:		function(imageSource) {
	
		if (imageSource) {
		
			if (this.ext == 'jpg') {
			
				this.element.down('.avatar_info').show();
				
				this.toggeler.value = 'Выбрать фрагмент…';
				
				if (this.resizer.visible()) {
				
					this.imageResizer.destroy();
					
					this.imageResizer = null;
				
					this.resizer.hide();
					
				}
			
			}
		
			this.element.down('.avatar_browse').value = 'Выбрать другую…';
			
			this.remover.show();
			
			var image = new Element('img', {'src': imageSource, 'alt': 'Аватар пользователя'})
			
			if (image.getNaturalSize().height > image.getNaturalSize().width) {
			
				image.setStyle({
				
					height:	'100px',
					
					width:	'auto'
				
				});
			
			} else {
			
				image.setStyle({
				
					width:	'100px',
					
					height:	'auto'
				
				});
			
			}
		
			this.preview.show().down('.image_holder').update(image);
		
		} else {
		
			this.preview.hide().down('.image_holder').update();
			
			this.remover.hide();
			
			this.element.down('.avatar_info').hide();
			
			this.toggeler.value = 'Выбрать фрагмент…';
			
			if (this.resizer.visible()) {
			
				this.imageResizer.destroy();
				
				this.imageResizer = null;
			
				this.resizer.hide();
				
			}
		
		}
	
	},
	
	click:		function(event) {
	
		var element = event.element();
		
		if (element.hasClassName('avatar_remove')) {
		
			this.render();		
		
		} else if (element.hasClassName('avatar_resizer_toggle')) {
		
			this.toggleResizer();
		
		}
		
		element.blur();
	
	},
	
	toggleResizer:	function() {
	
		if (this.resizer.visible()) {
		
			this.imageResizer.destroy();
			
			this.imageResizer = null;
		
			this.resizer.hide();
				
			this.toggeler.value = 'Выбрать фрагмент…';
		
		} else {
		
			this.resizer.show();
		
			if (!this.imageResizer) {
			
				this.imageResizer = new ImageResizer({
				
					element:	this.resizer,
					
					image:		this.element.down('.avatar_preview img'),
					
					callback:	this.apply.bind(this)
				
				});
			
			}
				
			this.toggeler.value = 'Закрыть редактор';
		
		}
	
	},
	
	apply:		function(rect) {
	
		if (!this.preview.down('input')) {
		
			this.preview.insert(new Element('input', {'type': 'hidden', 'name': 'avatar_rect'}))
		
		}
		
		this.preview.down('input').value = [rect.x0, rect.y0, rect.x1, rect.y1].join(',');
	
		var dims = this.imageResizer.clonePreview();
		
		this.preview.down('.image_holder').setStyle({
		
			width:	dims.holder.width,
			
			height:	dims.holder.height,
			
			top:	dims.holder.top,
			
			left:	dims.holder.left
		
		});
		
		this.preview.down('.image_holder img').setStyle({
		
			width:	dims.image.width,
			
			height:	dims.image.height,
			
			top:	dims.image.top,
			
			left:	dims.image.left
		
		});
	}

});

var ImageResizer = Class.create({

	initialize:	function (options) {
	
		if (!(this.element = $(options['element']))) return false;
		
		this.callback = options['callback'];
		
		this.element.insert(
		
			new Element('div', {'class': 'image_resizer_controls'}).insert(
			
				new Element('fieldset', {'class': 'actions'}).insert(
				
					new Element('span', {'class': 'btn'})
					
						.insert(new Element('button', {'type': 'button', 'class': 'apply'}).update($_LOCALE['resizer_action_apply']))
						
				).insert(
				
					new Element('span', {'class': 'btn'})
					
						.insert(new Element('button', {'type': 'button', 'class': 'reset'}).update($_LOCALE['resizer_action_reset']))
						
				)
			
			).insert(
			
				new Element('input', {'type': 'checkbox', 'class':'show_preview', 'id': 'resizer_show_preview'})
				
			).insert(
			
				new Element('label', {'for': 'resizer_show_preview'}).update($_LOCALE['resizer_show_preview'])
				
			)
		
		).insert(
		
			new Element('div', {'class': 'image_resizer_scroll'}).insert(
			
				new Element('div', {'class': 'image_resizer_canvas'}).insert(
			
					new Element('div', {'class': 'image_resizer_selection'}).hide()
					
						.insert(new Element('div', {'class': 'image_resizer_selection_outline'}))
					
						.insert(new Element('div', {'class': 'resize_handle handle_n'}))
						
						.insert(new Element('div', {'class': 'resize_handle handle_ne'}))
						
						.insert(new Element('div', {'class': 'resize_handle handle_e'}))
						
						.insert(new Element('div', {'class': 'resize_handle handle_se'}))
						
						.insert(new Element('div', {'class': 'resize_handle handle_s'}))
						
						.insert(new Element('div', {'class': 'resize_handle handle_sw'}))
						
						.insert(new Element('div', {'class': 'resize_handle handle_w'}))
						
						.insert(new Element('div', {'class': 'resize_handle handle_nw'}))
				
				).insert(
					
					new Element('img')
				
				)
			
			)
		
		).insert(
		
			new Element('div', {'class': 'image_resizer_preview'}).insert(
			
				new Element('div', {'class': 'image_holder'}).insert(new Element('img'))
			
			)
		
		).addClassName('image_resizer');
		
		$('resizer_show_preview').checked = true;	// IE7 hack;
		
		this.onClick = this.click.bindAsEventListener(this);
		
		this.onDragStart = this.startDragging.bindAsEventListener(this);
		
		this.onDragEnd = this.stopDragging.bindAsEventListener(this);
		
		this.onDrag = this.dragging.bindAsEventListener(this);
		
		this.onKeyPress = this.keypress.bindAsEventListener(this);
		
		this.scroll = this.element.down('.image_resizer_scroll');
		
		this.canvas = this.element.down('.image_resizer_canvas');
		
		this.selection = this.element.down('.image_resizer_selection');
		
		this.preview = this.element.down('.image_resizer_preview');
		
		this.canvas.observe('mousedown',this.onDragStart);
		
		this.element.observe('click',this.onClick);
		
		this.updateWithImage(options['image']);
		
		return this;
	
	},
	
	updateWithImage:	function(image) {
	
		this.image = image;
		
		this.canvas.down('img').src = this.image.src;
		
		this.preview.down('img').src = this.image.src;
		
		this.imageSize = this.image.getNaturalSize();
		
		this.canvas.down('img').setStyle({
		
			width:	Math.min(this.imageSize.width, this.scroll.getWidth()) + 'px'
		
		});
		
		if (this.canvas.down('img').height > this.scroll.getHeight())  {
		
			this.canvas.down('img').setStyle({
			
				width:	'auto',
			
				height:	this.scroll.getHeight() + 'px'
			
			});
		
		}
		
		this.zoomRatio = this.canvas.down('img').height / this.imageSize.height;
		
		this.canvas.setStyle({
		
			top:	this.canvas.down('img').height < this.scroll.getHeight()
			
				?	this.scroll.getHeight() / 2 - this.canvas.down('img').height / 2 + 'px'
				
				:	'0px',
		
			left:	this.canvas.down('img').width < this.scroll.getWidth()
			
				?	this.scroll.getWidth() / 2 - this.canvas.down('img').width / 2 + 'px'
				
				:	'0px',
		
			width:	this.canvas.down('img').width + 'px',
			
			height:	this.canvas.down('img').height + 'px'
					
		});
		
		this.update($_SET_DEFAULT);
	
	},
	
	destroy:	function () {
	
		this.canvas.stopObserving('mousedown',this.onDragStart);
		
		this.element.stopObserving('click',this.onClick);
		
		if (this.status) {
		
			document.stopObserving('mouseup',this.onDragEnd).stopObserving('mousemove',this.onDrag);
			
		}
		
		document.stopObserving('keydown', this.onKeyPress);
		
		document.stopObserving('keyup', this.onKeyPress);
		
		this.element.update();
	
	},
	
	startDragging:	function(event) {
		
		this.offset = this.canvas.down('img').cumulativeOffset();
		
		this.dimensions = this.canvas.down('img').getDimensions();
		
		this.startPoint = { x: event.pointerX() - this.offset.left, y: event.pointerY() - this.offset.top };
		
		if (event.element().hasClassName('image_resizer_selection') || event.element().hasClassName('image_resizer_selection_outline')) {
		
			this.status = 'move';
		
		} else if (event.element().hasClassName('resize_handle')) {
		
			this.status = 'resize';
			
			this.handlerType = event.element().className.split(/[\s]+/)[1].split('_')[1];
			
			this.resizeTop = this.handlerType.include('n') ? true : false;
			
			this.resizeLeft = this.handlerType.include('w') ? true : false;
			
			this.resizeRight = this.handlerType.include('e') ? true : false;
			
			this.resizeBottom = this.handlerType.include('s') ? true : false;
		
		} else {
		
			this.selection.show();
		
			this.status = 'draw';
			
			this.rect = {
			
				x0:		this.startPoint.x,
				
				y0:		this.startPoint.y,
				
				x1:		this.startPoint.x,
				
				y1:		this.startPoint.y
			
			};
			
			this.selection.setStyle({
			
				left:	this.rect.x0 + 'px',
				
				top:	this.rect.y0 + 'px',
				
				width:	'0px',
				
				height:	'0px'
			
			});
		
		}
		
		event.stop();
		
		document.observe('mouseup',this.onDragEnd).observe('mousemove',this.onDrag)
		
		document.observe('keydown', this.onKeyPress);
		
		document.observe('keyup', this.onKeyPress);
		
		this.skipFrames = true;		//	CPU load hack;
		
		this.timer = setTimeout(function() {
		
			clearTimeout(this.timer);
			
			this.skipFrames = false;
		
		}.bind(this),10);
	
	},
	
	stopDragging:	function(event) {
	
		this.status = false;
		
		this.rect = {
		
			x0:		this.selection.positionedOffset().left,
			
			y0:		this.selection.positionedOffset().top,
			
			x1:		this.selection.positionedOffset().left + this.selection.getWidth(),
			
			y1:		this.selection.positionedOffset().top + this.selection.getHeight()
		
		}
		
		document.stopObserving('mouseup',this.onDragEnd).stopObserving('mousemove',this.onDrag).stopObserving('keydown', this.onKeyPress);
	
	},
	
	dragging:	function(event) {
	
		if (!this.status || this.skipFrames) return;
		
		if (this.status == 'draw') {
		
			this.currentPoint = { x: event.pointerX() - this.offset.left, y: event.pointerY() - this.offset.top };
			
			this.rect.x1 = this.currentPoint.x > 0
			
				?	this.currentPoint.x < this.dimensions.width
				
					?	this.currentPoint.x
					
					:	this.dimensions.width
					
				:	0;
				
			this.rect.y1 = this.currentPoint.y > 0
			
				?	this.currentPoint.y < this.dimensions.height
				
					?	this.currentPoint.y
					
					:	this.dimensions.height
					
				:	0;
				
			if (event.shiftKey) {
			
				this.ratio = Math.abs((this.rect.x1 - this.rect.x0) / (this.rect.y1 - this.rect.y0));
			
				this.rect.x1 = this.ratio > 1 ? this.rect.x0 + (this.rect.y1 - this.rect.y0) : this.rect.x1;
				
				this.rect.y1 = this.ratio < 1 ? this.rect.y0 + (this.rect.x1 - this.rect.x0) : this.rect.y1;
			
			}
				
			this.selection.setStyle({
			
				left:	this.rect.x0 < this.rect.x1 ? this.rect.x0 : this.rect.x1 + 'px',
			
				top:	this.rect.y0 < this.rect.y1 ? this.rect.y0 : this.rect.y1 + 'px',
				
				width:	Math.abs(this.rect.x1 - this.rect.x0) + 'px',
				
				height:	Math.abs(this.rect.y1 - this.rect.y0) + 'px'
			
			});
		
		} else if (this.status == 'move') {
		
			this.currentPoint = { x: event.pointerX() - this.offset.left, y: event.pointerY() - this.offset.top };
			
			this.move = {
			
				x:	this.currentPoint.x - this.startPoint.x,
				
				y:	this.currentPoint.y - this.startPoint.y
			
			};
			
			this.selection.setStyle({
			
				top:	this.rect.y0 + this.move.y > 0
				
					?	this.rect.y1 + this.move.y < this.dimensions.height
					
						?	this.rect.y0 + this.move.y + 'px'
						
						:	this.rect.y0 + this.dimensions.height - this.rect.y1 + 'px'
						
					:	'0px',
				
				left:	this.rect.x0 + this.move.x > 0
				
					?	this.rect.x1 + this.move.x < this.dimensions.width
					
						?	this.rect.x0 + this.move.x + 'px'
						
						:	this.rect.x0 + this.dimensions.width - this.rect.x1 + 'px'
						
					:	'0px'
			
			});
		
		} else if (this.status == 'resize') {
		
			this.currentPoint = { x: event.pointerX() - this.offset.left, y: event.pointerY() - this.offset.top };
			
			if (this.resizeLeft) {

				this.rect.x0 = this.currentPoint.x > 0
				
					?	this.currentPoint.x < this.dimensions.width
					
						?	this.currentPoint.x
						
						:	this.dimensions.width
						
					:	0;
			
			};
		
			if (this.resizeTop) {

				this.rect.y0 = this.currentPoint.y > 0
				
					?	this.currentPoint.y < this.dimensions.height
					
						?	this.currentPoint.y
						
						:	this.dimensions.height
						
					:	0;
			
			};
			
			if (this.resizeRight) {

				this.rect.x1 = this.currentPoint.x > 0
				
					?	this.currentPoint.x < this.dimensions.width
					
						?	this.currentPoint.x
						
						:	this.dimensions.width
						
					:	0;
			
			};
			
			if (this.resizeBottom) {

				this.rect.y1 = this.currentPoint.y > 0
				
					?	this.currentPoint.y < this.dimensions.width
					
						?	this.currentPoint.y
						
						:	this.dimensions.width
						
					:	0;
			
			};
			
			if (event.shiftKey) {
			
				this.ratio = Math.abs((this.rect.x1 - this.rect.x0) / (this.rect.y1 - this.rect.y0));
				
				this.rect.y0 = this.resizeTop && this.ratio < 1 ? this.rect.y1 - (this.rect.x1 - this.rect.x0) : this.rect.y0;
				
				this.rect.x0 = this.resizeLeft && this.ratio > 1 ? this.rect.x1 - (this.rect.y1 - this.rect.y0) : this.rect.x0;
			
				this.rect.x1 = this.resizeRight && this.ratio > 1 ? this.rect.x0 + (this.rect.y1 - this.rect.y0) : this.rect.x1;
				
				this.rect.y1 = this.resizeBottom && this.ratio < 1 ? this.rect.y0 + (this.rect.x1 - this.rect.x0) : this.rect.y1;
			
			}
			
			this.selection.setStyle({
			
				left:	((this.rect.x0 < this.rect.x1) ? this.rect.x0 : this.rect.x1) + 'px',
			
				top:	((this.rect.y0 < this.rect.y1) ? this.rect.y0 : this.rect.y1) + 'px',
				
				width:	Math.abs(this.rect.x1 - this.rect.x0) + 'px',
				
				height:	Math.abs(this.rect.y1 - this.rect.y0) + 'px'
			
			});
		
		}
		
		this.update();
		
		this.skipFrames = true;
		
		this.timer = setTimeout(function() {
		
			clearTimeout(this.timer);
			
			this.skipFrames = false;
		
		}.bind(this),10);
	
	},
	
	moveSelection:	function(offset) {
	
		this.selection.setStyle({
		
			top:	this.rect.y0 + offset.y > 0
			
				?	this.rect.y1 + offset.y < this.dimensions.height
				
					?	this.rect.y0 + offset.y + 'px'
					
					:	this.rect.y0 + this.dimensions.height - this.rect.y1 + 'px'
					
				:	'0px',
		
			left:	this.rect.x0 + offset.x > 0
			
				?	this.rect.x1 + offset.x < this.dimensions.width
				
					?	this.rect.x0 + offset.x + 'px'
					
					:	this.rect.x0 + this.dimensions.width - this.rect.x1 + 'px'
					
				:	'0px'
		
		});
		
		this.rect = {
		
			x0:		this.selection.positionedOffset().left,
			
			y0:		this.selection.positionedOffset().top,
			
			x1:		this.selection.positionedOffset().left + this.selection.getWidth(),
			
			y1:		this.selection.positionedOffset().top + this.selection.getHeight()
		
		}
		
		this.update();
	
	},
	
	update:		function(setDefault) {
	
		if (!!setDefault) {
		
			this.ratio = this.image.width / this.image.height;
			
			this.ratioX = 100 / this.image.width;
			
			this.ratioY = 100 / this.image.height;
			
			this.preview.down('img').setStyle({
			
				width:	this.ratio > 1
				
					?	this.image.width * this.ratioX + 'px'
						
					:	this.image.width * this.ratioY + 'px',
					
				height:	this.ratio < 1
				
					?	this.image.height * this.ratioY + 'px'
						
					:	this.image.height * this.ratioX + 'px',
					
				top:	'0px',
				
				left:	'0px'
			
			});
			
			this.preview.down('.image_holder').setStyle({
			
				width:	this.ratio > 1
				
					?	'100px'
						
					:	Math.round(this.image.width * this.ratioY) + 'px',
					
				height:	this.ratio > 1
				
					?	Math.round(this.image.height * this.ratioX) + 'px'
						
					:	'100px',
					
				top:	'0px',
				
				left:	'0px'
			
			});
			
			this.selection.hide();
		
		} else {
		
			this.ratio = this.selection.getWidth() / this.selection.getHeight();
		
			this.ratioX = 100 / this.selection.getWidth() * this.zoomRatio;
			
			this.ratioY = 100 / this.selection.getHeight() * this.zoomRatio;
			
			this.preview.down('img').setStyle({
			
				width:	this.ratio > 1
				
					?	this.imageSize.width * this.ratioX + 'px'
						
					:	this.imageSize.width * this.ratioY + 'px',
					
				height:	this.ratio < 1
				
					?	this.imageSize.height * this.ratioY + 'px'
						
					:	this.imageSize.height * this.ratioX + 'px',
					
				top:	this.ratio < 1
				
					?	- this.selection.positionedOffset().top * this.ratioY / this.zoomRatio + 'px'
					
					:	- this.selection.positionedOffset().top * this.ratioX / this.zoomRatio + 'px',
				
				left:	this.ratio > 1
				
					?	- this.selection.positionedOffset().left * this.ratioX / this.zoomRatio + 'px'
					
					:	- this.selection.positionedOffset().left * this.ratioY / this.zoomRatio + 'px'
			
			});
			
			this.preview.down('.image_holder').setStyle({
			
				width:	this.ratio > 1
				
					?	'100px'
						
					:	Math.round(this.selection.getWidth() * this.ratioY / this.zoomRatio) + 'px',
					
				height:	this.ratio > 1
				
					?	Math.round(this.selection.getHeight() * this.ratioX / this.zoomRatio) + 'px'
						
					:	'100px',
					
				top:	'0px',
				
				left:	'0px'
			
			});
		
		}
	
	},
	
	keypress:	function(event) {
	
		var keyCode = Event.keyCode(event);
		
		var offsetMultiplier = event.shiftKey ? 10 : 1;
		
		if (keyCode == Event.KEY_RETURN) {
		
			console.log('enter');
		
		} else if (keyCode == Event.KEY_ESC) {
		
			this.rect = {}
			
			this.selection.hide();
			
			document.stopObserving('keydown', this.onKeyPress);
		
		} else if (event.ctrlKey && keyCode == Event.KEY_UP) {
		
			event.stop();
			
			this.moveSelection({ x: 0, y: -1 * offsetMultiplier });
		
		} else if (event.ctrlKey && keyCode == Event.KEY_DOWN) {
		
			event.stop();
			
			this.moveSelection({ x: 0, y: 1 * offsetMultiplier });
		
		} else if (event.ctrlKey && keyCode == Event.KEY_LEFT) {
		
			event.stop();
			
			this.moveSelection({ x: -1 * offsetMultiplier, y: 0 });
		
		} else if (event.ctrlKey && keyCode == Event.KEY_RIGHT) {
		
			event.stop();
			
			this.moveSelection({ x: 1 * offsetMultiplier, y: 0 });
		
		}
	
	},
	
	click:	function(event) {
	
		var element = event.element();
	
		if (element.hasClassName('show_preview')) {
		
			this.preview.toggle();
		
		} else if (element.hasClassName('apply')) {
		
			if (this.callback) {
			
				this.callback({
					
					x0: this.rect.x0 / this.zoomRatio,
					
					y0: this.rect.y0 / this.zoomRatio,
					
					x1: this.rect.x1 / this.zoomRatio,
					
					y1: this.rect.y1 / this.zoomRatio
					
				});
			
			}
		
		} else if (element.hasClassName('reset')) {
			
			this.rect = {};
			
			this.update('setDefault');
		
		}
	
	},
	
	clonePreview:	function() {
	
		var holder = this.preview.down('.image_holder');
		
		var image = this.preview.down('img');
	
		return	{
		
			holder:	{
			
				width:	holder.getStyle('width'),
				
				height:	holder.getStyle('height'),
				
				top:	holder.getStyle('top'),
				
				left:	holder.getStyle('left')
			
			},
			
			image:	{
			
				width:	image.getStyle('width'),
				
				height:	image.getStyle('height'),
				
				top:	image.getStyle('top'),
				
				left:	image.getStyle('left')
			
			}
		
		}
	
	}

});

