
function distanceBetween(x1, y1, x2, y2) {
	var dx = x2 - x1;
	var dy = y2 - y1;

	var d = Math.sqrt(dx * dx + dy * dy);

	return d;
}

var gImageEffectsMap = {
	"e0.png": "",
	"e1.png": "美肤",
	"e2.png": "素描",
	"e3.png": "自然增强",
	"e4.png": "紫调",
	"e5.png": "柔焦",
	"e6.png": "复古",
	"e7.png": "黑白",
	"e8.png": "仿lomo",
	"e9.png": "亮白增强",
	"e10.png": "灰白",
	"e11.png": "灰色",
	"e12.png": "暖秋",
	"e13.png": "木雕",
	"e14.png": "粗糙"
};

function ImageEditorApp(win) {
	var MAX_IMAGE_WIDTH = Math.min(win.w, win.h);
	var MAX_IMAGE_HEIGHT = Math.min(win.w, win.h);

	this.win = win;
	this.rotation = 0;
	this.xOffset = 0;
	this.yOffset = 0;
	this.cropX = 0;
	this.cropY = 0;
	this.cropW = 0;
	this.cropH = 0;
	this.imageOfFrame = null;
	this.imageWidth = 0;
	this.imageHeight = 0;
	this.imageOfEffect = new Image();

	this.originalImage = null;
	this.tempCanvas = document.createElement("canvas");
	this.cropImageCanvas = document.createElement("canvas");
	this.resizeImageCanvas = document.createElement("canvas");
	this.originalImageCanvas = document.createElement("canvas");
	this.finalImageCanvas = document.createElement("canvas");

	this.startWaitBox = function() {
		if(this.waitBoxTimer) {
			return;
		}

		this.win.openWindow("win-busy", function (retCode) {console.log("window closed.");}, false);

		var app = this;
		this.waitBoxTimer = setTimeout(function() {
			app.endWaitBox();	
			alert("Operation Timeout.");
		}, 15000);

		return;
	}

	this.endWaitBox = function() {
		if(this.waitBoxTimer) {
			this.win.closeWindow(0);
			clearTimeout(this.waitBoxTimer);
			delete this.waitBoxTimer;
		}

		return;
	}

	this.hasImage = function () {
		return this.originalImage != null;
	}
	
	this.getTempCanvas = function (w, h) {
		var canvas = this.tempCanvas;
		canvas.width = w;
		canvas.height = h;

		return canvas;
	}

	this.setFrameImage = function (image) {
		var src = image.src;

		if(!src || src.indexOf("f0.png") > 0) {
			this.imageOfFrame = null;
			this.updateFinalImageCanvas();

			return;
		}

		var app = this;
		var uiCanvasElement = this.win.findChildByType("ui-canvas", true);
		var xScale = uiCanvasElement.w/image.width;
		var yScale = uiCanvasElement.h/image.height;
		var scale = Math.min(xScale, yScale);

		var w = Math.floor(image.width*scale);
		var h = Math.floor(image.height*scale);
	
		var canvas = this.getTempCanvas(w, h);

		var ctx = canvas.getContext("2d");
		ctx.drawImage(image, 0, 0, image.width, image.height, 0, 0, w, h);

		this.imageOfFrame = new Image();
		this.imageOfFrame.onload = function() {
			app.updateFinalImageCanvas();
		}
		this.imageOfFrame.src = canvas.toDataURL();

		return;
	}

	this.setImage = function (image) {
		this.scale = 1;
		this.xOffset = 0;
		this.yOffset = 0;
		this.rotation = 0;
		this.effect = null;
		this.originalImage = image;

		var xScale = image.width/MAX_IMAGE_WIDTH;
		var yScale = image.height/MAX_IMAGE_HEIGHT;
		var scale = (xScale > 1 || yScale > 1) ? Math.max(xScale, yScale) : 1;
		var width = Math.floor(image.width/scale);
		var height = Math.floor(image.height/scale);

		this.originalImageCanvas.width = width;
		this.originalImageCanvas.height = height;

		var ctx = this.originalImageCanvas.getContext("2d");
		ctx.drawImage(image, 0, 0, image.width, image.height, 0, 0, width, height);

		this.imageWidth = width;
		this.imageHeight = height;
		this.crop(0, 0, width, height);

		return;
	}

	this.setEffect = function(effect, force) {
		if(!this.hasImage()) {
			this.effect = effect;
			return;
		}

		if(effect != this.effect || force) {
			var app = this;
			var win = this.win;
			this.effect = effect;

			if(effect) {
				app.startWaitBox();

				var img = this.resizeImageCanvas;
				var transImgeObj = $AI(img);
				var newPic = transImgeObj.ps(effect);

				newPic.complete(function() {
					function updateFinalImage() {
						app.endWaitBox();
						
						if(app.imageOfEffect.width) {							
							app.updateFinalImageCanvas();
							console.log("transform complete, redraw it.");
						}
						else {
							setTimeout(function() {
								updateFinalImage();
							}, 1000);
							console.log("transform complete, image not ready.");
						}
					}
					
					setTimeout(updateFinalImage, 1000);
				});
				
				newPic.replace(app.imageOfEffect);
			}
			else {
				this.imageOfEffect.src = this.resizeImageCanvas.toDataURL();
				this.imageOfEffect.onload = function() {
					app.updateFinalImageCanvas();
				}
			}
		}

		return;
	}
	
	this.setEffectByImageName = function(src) {
		var arr = src.split("/");
		var name = arr.pop();
		var effect = gImageEffectsMap[name];

		var app = this;

		setTimeout(function() {
			app.setEffect(effect);
		},600);

		return;
	}

	this.resize = function(w, h) {
		this.imageWidth = w;
		this.imageHeight = h;
		this.resizeImageCanvas.width = w;
		this.resizeImageCanvas.height = h;

		var image = this.cropImageCanvas;
		var ctx = this.resizeImageCanvas.getContext("2d");
		ctx.drawImage(image, 0, 0, image.width, image.height, 0, 0, w, h);

		this.imageOfEffect.src = this.resizeImageCanvas.toDataURL();

		this.setEffect(this.effect, true);

		return;
	}

	this.crop = function(x, y, w, h) {
		this.cropX = x;
		this.cropY = y;
		this.cropW = w;
		this.cropH = h;

		this.cropImageCanvas.width = w;
		this.cropImageCanvas.height = h;
		
		var image = this.originalImageCanvas;
		var ctx = this.cropImageCanvas.getContext("2d");

		ctx.drawImage(image, x, y, w, h, 0, 0, w, h);

		var resizeW = this.imageWidth ? this.imageWidth : w;
		var resizeH = Math.floor(resizeW * h/w);

		this.resize(resizeW, resizeH);

		return;
	}
	
	this.updateFinalImageCanvas = function() {
		var image = null;
		var ctx = this.finalImageCanvas.getContext("2d");

		if(this.imageOfFrame)	{
			this.finalImageCanvas.width = this.imageOfFrame.width;
			this.finalImageCanvas.height = this.imageOfFrame.height;
			
			var w = this.imageOfEffect.width;
			var h = this.imageOfEffect.height;
			var cx = w >> 1;
			var cy = h >> 1;

			ctx.save();
			ctx.translate(this.xOffset, this.yOffset);
			if(this.scale) {
				ctx.translate(cx, cy);
				ctx.scale(this.scale, this.scale);
				ctx.translate(-cx, -cy);
			}
			ctx.drawImage(this.imageOfEffect, 0, 0);
			ctx.restore();

			if(this.pointerDown) {
				ctx.globalAlpha = 0.5;
			}
			ctx.drawImage(this.imageOfFrame, 0, 0);
			ctx.globalAlpha = 1;
		}
		else {
			this.finalImageCanvas.width = this.imageOfEffect.width;
			this.finalImageCanvas.height = this.imageOfEffect.height;

			var w = this.imageOfEffect.width;
			var h = this.imageOfEffect.height;
			var cx = w >> 1;
			var cy = h >> 1;

			ctx.save();
			ctx.drawImage(this.imageOfEffect, 0, 0);
			ctx.restore();
		}

		this.win.postRedraw();

		return;
	}

	this.onSelectFrame = function(button) {
		if(this.hasImage()) {
			var app = this;
			button.openWindow("win-frames", 
				function (image) {
					if(image) {
						app.setFrameImage(image);
					}
				}, false);
		}
	}
	
	this.onGestureScaleStart = function() {
		this.saveScale = this.scale;
		return;
	}

	this.onGestureScaleEnd = function() {
	}

	this.onGestureScale = function(scale) {
		if(scale > 0.2 && scale < 5) {
			this.scale = scale;
		}

		return;
	}

	this.onGestureScaleStart = function() {
		this.saveScale = this.scale ? this.scale : 1;

		return;
	}

	this.onGestureScaleEnd = function() {
		delete this.saveScale;
	}

	this.onGestureScale = function(scale) {
		if(scale > 0.2 && scale < 5 && this.saveScale) {
			this.scale = this.saveScale * scale;
			this.updateFinalImageCanvas();
		}
			
		return;
	}

	this.save = function() {
		var me = this;
		var filename = this.filename;
		var canvas = this.finalImageCanvas;

		if(isFirefoxOS()) {
			canvas.toBlob(function(blob) {
				var info = {};
				info.action = "save";

				info.data = blob;
				info.filename = filename;
				
				win.openWindow("win-image-browser", 
					function (result) {
						if(result) {
							me.filename = result.filename;
						}
					}, false, info);

			});
		}
		else {
			var url = canvas.toDataURL();
			window.open(url);	
		}
	}
	
	this.share = function() {
		var canvas = this.finalImageCanvas;

		if(isFirefoxOS()) {
			canvas.toBlob(function(blob) {
				firefoxShareImage(blob);
			});
		}
		else {
			alert("Not Support Share In This Platform.");
		}

		return;
	}
	
	this.onPicture = function() {
		var me = this;

		pickImage(function(image) {
			me.setImage(image);
		});

		return;
	}

	this.onOpen = function() {
		var me = this;
		var info = {};

		info.action = "open";
		info.filename = this.filename;

		win.openWindow("win-image-browser", 
			function (result) {
				if(result) {
					var image = result.image;
					me.filename = result.filename;

					me.setImage(image);
				}
			}, false, info);

		return;
	}
	
	this.onSave = function() {
		if(this.hasImage()) {
			this.save();
		}
	}

	this.onShare = function() {
		if(this.hasImage()) {
			this.share();	
		}
		return;
	}


	this.rotate = function() {
		var oCanvas = this.originalImageCanvas;
		
		var x = 0;
		var y = 0;
		var w = oCanvas.height;
		var h = oCanvas.width;
		var cx = w >> 1;
		var cy = h >> 1;

		var angle = Math.PI * 0.5;
		var tCanvas = this.getTempCanvas(w, h);
		var ctx = tCanvas.getContext("2d");

		ctx.translate(cx, cy);
		ctx.rotate(angle);
		ctx.translate(-cx, -cy);

		x = (w - oCanvas.width) >> 1;
		y = (h - oCanvas.height) >> 1;

		ctx.drawImage(oCanvas, x, y);

		oCanvas.width = w;
		oCanvas.height = h;

		ctx = oCanvas.getContext("2d");
		ctx.drawImage(tCanvas, 0, 0);
	
		this.crop(0, 0, w, h);

		return;
	}

	this.onRotate = function() {
		if(this.hasImage()) {
			this.rotate();
		}

		return;
	}

	this.onPaint = function(canvasEl, ctx) {
		ctx.fillRect(0, 0, canvasEl.w, canvasEl.h);
		
		if(!this.hasImage()) {

			var x = canvasEl.w >> 1;
			var y = canvasEl.h >> 1;
			var str = translateText("Please Choose An Image First...");

			ctx.textAlign = "center";
			ctx.textBaseline = "bottom";
			canvasEl.style.setFontSize(16);
			ctx.font = canvasEl.style.getFont();
			ctx.fillStyle = "Gold";
			ctx.fillText(str, x, y);

			return;
		}

		var image = this.finalImageCanvas;
		var xScale = image.width/canvasEl.w;
		var yScale = image.height/canvasEl.h;
		var scale = Math.max(xScale, yScale);
		var w = scale > 1 ? Math.floor(image.width/scale) : image.width;
		var h = scale > 1 ? Math.floor(image.height/scale) : image.height;
		var x = (canvasEl.w-w)>>1;
		var y = (canvasEl.h-h)>>1;

		ctx.drawImage(image, 0, 0, image.width, image.height, x, y, w, h);

		return;
	}
	
	this.onPointerDown = function(uiCanvasElement, point) {
		this.pointerDown = true;
		this.saveXOffset = this.xOffset;
		this.saveYOffset = this.yOffset;
		this.updateFinalImageCanvas();

		return;
	}
	
	this.onPointerMove = function(uiCanvasElement, point) {
		if(this.pointerDown && this.imageOfFrame) {
			var dx = uiCanvasElement.getMoveAbsDeltaX();
			var dy = uiCanvasElement.getMoveAbsDeltaY();

			this.xOffset = this.saveXOffset + dx;
			this.yOffset = this.saveYOffset + dy;
			this.updateFinalImageCanvas();
		}
	}
	
	this.onPointerUp = function(uiCanvasElement, point) {
		this.pointerDown = false;
		this.updateFinalImageCanvas();
	}

	this.init = function() {
		var alloyJs = null;
		var scripts = document.getElementsByTagName("script");

		if(scripts) {
			for(var i = 0; i < scripts.length; i++) {
				var src = scripts[i].src;
				if(src.indexOf("alloy") >= 0) {
					alloyJs = src;
					break;
				}
			}
		}

		setTimeout(function() {
			try {
				$AI.useWorker(alloyJs);
				console.log("useWorker OK: " + alloyJs);
			}catch(e) {
				console.log("useWorker Failed: " + alloyJs);
			}
		}, 3000);
	}

	this.init();

	return;
}

///////////////////////////////////////////////////////////////////

function CropImageController(uiCanvasElement, image) {
	this.cropX = 0;
	this.cropY = 0;
	this.cropW = 0;
	this.cropH = 0;
	this.image = image;
	this.hitTest = -1;

	this.init = function(uiCanvasElement, image) {
		var imageW = image.width;
		var imageH = image.height;
		var rotation = image.rotation;
		var canvasW = uiCanvasElement.w;
		var canvasH = uiCanvasElement.h;

		if(imageW > 0 && imageH > 0) {
			var scale = 1;

			if(!rotation || rotation == 180) {
				scale = Math.min(canvasW/imageW, canvasH/imageH);
			}
			else {
				scale = Math.min(canvasW/imageH, canvasH/imageW);
			}
		
			if(scale > 1) {
				scale = 1;
			}

			
			imageW = imageW * scale;
			imageH = imageH * scale;

			this.scale = scale;
			this.imageW = imageW;
			this.imageH = imageH;
			this.imageX = (canvasW - imageW)/2;
			this.imageY = (canvasH - imageH)/2;

			if(imageW > 100) {
				this.cropX = this.imageX + imageW/4;
				this.cropW = imageW/2;
			}
			else {
				this.cropX = this.imageX;
				this.cropW = imageW;
			}

			if(imageH > 100) {
				this.cropY = this.imageY + imageH/4;
				this.cropH = imageH/2;
			}
			else {
				this.cropY = this.imageY;
				this.cropH = imageH;
			}
		}
	
		this.rotation = rotation;
		this.canvasW = canvasW;
		this.canvasH = canvasH;

		return;
	}

	this.handlePointerDown = function(x, y) {
		var D = isMobile() ? 40 : 20;
		if(distanceBetween(x, y, this.cropX, this.cropY) < D) {
			this.hitTest = C_HIT_TEST_TL;
		}
		else if(distanceBetween(x, y, this.cropX+this.cropW, this.cropY) < D) {
			this.hitTest = C_HIT_TEST_TR;
		}
		else if(distanceBetween(x, y, this.cropX, this.cropY+this.cropH) < D) {
			this.hitTest = C_HIT_TEST_BL;
		}
		else if(distanceBetween(x, y, this.cropX+this.cropW, this.cropY+this.cropH) < D) {
			this.hitTest = C_HIT_TEST_BR;
		}
		else if(x > this.cropX && x < (this.cropX + this.cropW) && y > this.cropY && y < (this.cropY + this.cropH)) {
			this.hitTest = C_HIT_TEST_MM;
		}
		else {
			this.hitTest = -1;
		}

		this.lastX = x;
		this.lastY = y;
		this.mouseDown = true;

		return;
	}
	
	this.handlePointerMove = function(x, y) {
		if(!this.mouseDown) {
			return;
		}

		var dx = x - this.lastX;
		var dy = y - this.lastY;

		switch(this.hitTest) {
			case C_HIT_TEST_TL: {
				this.cropX = this.cropX + dx;
				this.cropY = this.cropY + dy;
				this.cropW = this.cropW - dx;
				this.cropH = this.cropH - dy;
				break;
			}
			case C_HIT_TEST_TR: {
				this.cropY = this.cropY + dy;
				this.cropW = this.cropW + dx;
				this.cropH = this.cropH - dy;
				break;
			}
			case C_HIT_TEST_BL: {
				this.cropX = this.cropX + dx;
				this.cropW = this.cropW - dx;
				this.cropH = this.cropH + dy;
				break;
			}
			case C_HIT_TEST_BR: {
				this.cropW = this.cropW + dx;
				this.cropH = this.cropH + dy;
				break;
			}
			case C_HIT_TEST_MM: {
				this.cropX = this.cropX + dx;
				this.cropY = this.cropY + dy;
				break;
			}
			default: {
				return;
			}
		}
	
		if(this.cropW < 40) {
			this.cropW = 40;
		}

		if(this.cropH < 40) {
			this.cropH = 40;
		}

		if((this.cropX + this.cropW) > (this.imageX + this.imageW)) {
			this.cropX = this.imageX + this.imageW - this.cropW;
		}
		
		if((this.cropY + this.cropH) > (this.imageY + this.imageH)) {
			this.cropY = this.imageY + this.imageH - this.cropH;
		}
		
		if(this.cropX < this.imageX) {
			this.cropX = this.imageX;
		}
		
		if(this.cropY < this.imageY) {
			this.cropY = this.imageY;
		}
		
		if(this.cropW > this.imageW) {
			this.cropW = this.imageW;
		}
		
		if(this.cropH > this.imageH) {
			this.cropH = this.imageH;
		}
		
		this.lastX = x;
		this.lastY = y;

		return;
	}
	
	this.handlePointerUp = function(x, y) {
		this.hitTest = 0;
		this.mouseDown = false;
	}

	this.paintCropRect = function(canvas) {
		var r = 0;
		var R = 20;
		var highlightR = isMobile() ? 40 : 30;

		var w = this.canvasW;
		var h = this.canvasH;
		
		canvas.globalAlpha = 0.4;
		canvas.fillStyle = "Blue";
		canvas.beginPath();
		canvas.rect(0, 0, w, this.cropY);
		canvas.fill();
		
		canvas.beginPath();
		canvas.rect(0, this.cropY, this.cropX, this.cropH);
		canvas.fill();
		
		canvas.beginPath();
		canvas.rect(this.cropX + this.cropW, this.cropY, w-(this.cropX + this.cropW), this.cropH);
		canvas.fill();
		
		canvas.beginPath();
		canvas.rect(0, this.cropY+this.cropH, w, h - (this.cropY + this.cropH));
		canvas.fill();
		canvas.globalAlpha = 1;

		////////////////////////////////////////////////

		canvas.fillStyle = "Orange";
		canvas.strokeStyle = "Green";
		canvas.beginPath();
		canvas.rect(this.cropX, this.cropY, this.cropW, this.cropH);
		canvas.stroke();

		r = (this.hitTest == C_HIT_TEST_TL) ? highlightR : R;
		canvas.beginPath();
		canvas.arc(this.cropX, this.cropY, r, 0, Math.PI * 2);
		canvas.fill();
		canvas.stroke();
		
		r = (this.hitTest == C_HIT_TEST_TR) ? highlightR : R;
		canvas.beginPath();
		canvas.arc(this.cropX+this.cropW, this.cropY, r, 0, Math.PI * 2);
		canvas.fill();
		canvas.stroke();
		
		r = (this.hitTest == C_HIT_TEST_BL) ? highlightR : R;
		canvas.beginPath();
		canvas.arc(this.cropX, this.cropY+this.cropH, r, 0, Math.PI * 2);
		canvas.fill();
		canvas.stroke();

		r = (this.hitTest == C_HIT_TEST_BR) ? highlightR : R;
		canvas.beginPath();
		canvas.arc(this.cropX+this.cropW, this.cropY+this.cropH, r, 0, Math.PI * 2);
		canvas.fill();
		canvas.stroke();

		return;
	}

	this.paint = function(uiCanvasElement, canvas) {
		if(image.width > 0 && image.height > 0) {
			var str = "";
			var x = 0;
			var y = 0;
			var w = this.canvasW;
			var h = this.canvasH;
			var scale = this.scale ? (1/this.scale) : 1;

			canvas.save();
			canvas.drawImage(image, 0, 0, image.width, image.height, this.imageX, this.imageY, this.imageW, this.imageH);	
			canvas.restore();

			this.paintCropRect(canvas);
		

			x = Math.round((this.cropX - this.imageX) * scale);
			y = Math.round((this.cropY - this.imageY) * scale);
			w = Math.round(this.cropW * scale);
			h = Math.round(this.cropH * scale);

			str = "x=" + x + " y=" + y + " w=" + w + " h=" + h;
		
			canvas.textAlign = "center";
			canvas.textBaseline = "bottom";
			uiCanvasElement.style.setFontSize(16);
			canvas.font = uiCanvasElement.style.getFont();
			canvas.fillStyle = "Gold";
			canvas.fillText(str, uiCanvasElement.w>>1, uiCanvasElement.h); 
		}
	}

	this.crop = function(onOK) {
		var image = this.image;
		var scale = this.scale ? (1/this.scale) : 1;
		var x = (this.cropX - this.imageX) * scale;
		var y = (this.cropY - this.imageY) * scale;
		var w = this.cropW * scale;
		var h = this.cropH * scale;
	
		x = Math.abs(x);
		y = Math.abs(y);

		var r = {};
		r.x = x;
		r.y = y;
		r.w = w;
		r.h = h;

		onOK(r);

		return image;
	}

	this.init(uiCanvasElement, image);

	return;
}

function cropImageInit(win, image) {
	var uiCanvasElement = win.findChildByType("ui-canvas");
	var controller = new CropImageController(uiCanvasElement, image);

	win.controller = controller;

	return;
}

function cropImagePaint(uiCanvasElement, canvas) {
	var controller = uiCanvasElement.getWindow().controller;
	if(controller) {
		controller.paint(uiCanvasElement, canvas);
	}

	return;
}

function cropHandlePointerDown(uiCanvasElement, x, y) {
	var controller = uiCanvasElement.getWindow().controller;
	if(controller) {
		controller.handlePointerDown(x, y);
	}

	return;
}

function cropHandlePointerMove(uiCanvasElement, x, y) {
	var controller = uiCanvasElement.getWindow().controller;
	if(controller) {
		controller.handlePointerMove(x, y);
	}

	return;
}

function cropHandlePointerUp(uiCanvasElement, x, y) {
	var controller = uiCanvasElement.getWindow().controller;
	if(controller) {
		controller.handlePointerUp(x, y);
	}

	return;
}

function cropItAndReturn(uiCanvasElement) {
	var controller = uiCanvasElement.getWindow().controller;
	if(controller) {
		controller.crop(
			function(cropRect) {
				uiCanvasElement.closeWindow(cropRect);
			}
		);
	}

	return;
}

function imageEditorCropImage(button) {
	if(gImageEditorApp.hasImage()) {
		var image = gImageEditorApp.originalImageCanvas;
		button.openWindow("win-crop", 
			function (cropRect) 
				{
					if(cropRect) {
						setTimeout(function() {
							gImageEditorApp.crop(cropRect.x, cropRect.y, cropRect.w, cropRect.h);
						}, 800);
					}
				}, false, image);
	}
	
	return;
}

//////////////////////////////////////////////////////////////////////

function ResizeImageController(uiCanvasElement, image) {
	this.resizeW = 0;
	this.resizeH = 0;
	this.hitTest = -1;
	this.image = image;

	this.init = function(uiCanvasElement, image) {
		var imageW = image.width;
		var imageH = image.height;
		var canvasW = uiCanvasElement.w;
		var canvasH = uiCanvasElement.h;

		if(imageW > 0 && imageH > 0) {
			var scale = Math.min(canvasW/imageW, canvasH/imageH);
		
			imageW = imageW * scale;
			imageH = imageH * scale;

			this.scale = scale;
			this.imageW = imageW;
			this.imageH = imageH;
			this.whRatio = image.width/image.height;

			if(imageW > 100) {
				this.resizeW = imageW >> 1;
			}
			else {
				this.resizeW = imageW;
			}

			if(imageH > 100) {
				this.resizeH = imageH >> 1;
			}
			else {
				this.resizeH = imageH;
			}
		}
	
		this.canvasW = canvasW;
		this.canvasH = canvasH;

		return;
	}

	this.handlePointerDown = function(x, y) {
		var D = isMobile() ? 40 : 20;
		if(distanceBetween(x, y, this.resizeW, this.resizeH/2) < D) {
			this.hitTest = C_HIT_TEST_TR;
		}
		else if(distanceBetween(x, y, this.resizeW/2, this.resizeH) < D) {
			this.hitTest = C_HIT_TEST_BL;
		}
		else if(distanceBetween(x, y, this.resizeW, this.resizeH) < D) {
			this.hitTest = C_HIT_TEST_BR;
		}
		else {
			this.hitTest = -1;
		}

		this.lastX = x;
		this.lastY = y;
		this.mouseDown = true;

		return;
	}
	
	this.handlePointerMove = function(x, y) {
		if(!this.mouseDown) {
			return;
		}

		var dx = x - this.lastX;
		var dy = y - this.lastY;

		switch(this.hitTest) {
			case C_HIT_TEST_TR: {
				this.resizeW = this.resizeW + dx;
				this.resizeH = this.resizeW / this.whRatio;
				break;
			}
			case C_HIT_TEST_BL: {
				this.resizeH = this.resizeH + dy;
				this.resizeW = this.resizeH * this.whRatio;

				break;
			}
			case C_HIT_TEST_BR: {
				this.resizeW = this.resizeW + dx;
				this.resizeH = this.resizeH + dy;
				break;
			}
			default: {
				return;
			}
		}
	
		if(this.resizeW < 60) {
			this.resizeW = 60;
		}

		if(this.resizeH < 60) {
			this.resizeH = 60;
		}
		
		if(this.resizeW > this.imageW) {
			this.resizeW = this.imageW;
		}
		
		if(this.resizeH > this.imageH) {
			this.resizeH = this.imageH;
		}
		
		this.lastX = x;
		this.lastY = y;
		this.resizeW = Math.round(this.resizeW);
		this.resizeH = Math.round(this.resizeH);

		return;
	}
	
	this.handlePointerUp = function(x, y) {
		this.hitTest = 0;
		this.mouseDown = false;
	}

	this.paintResizeRect = function(canvas) {
		var r = 0;
		var R = 20;
		var highlightR = isMobile() ? 40 : 30;
		var w = this.canvasW;
		var h = this.canvasH;
		
		canvas.globalAlpha = 0.4;
		canvas.fillStyle = "Blue";
		
		canvas.beginPath();
		canvas.rect(this.resizeW, 0, w-this.resizeW, this.resizeH);
		canvas.fill();
		
		canvas.beginPath();
		canvas.rect(0, this.resizeH, w, h - this.resizeH);
		canvas.fill();
		canvas.globalAlpha = 1;

		////////////////////////////////////////////////

		canvas.fillStyle = "Orange";
		canvas.strokeStyle = "Green";
		canvas.beginPath();
		canvas.rect(0, 0, this.resizeW, this.resizeH);
		canvas.stroke();
		
		////////////////////////////////////////////////

		r = (this.hitTest == C_HIT_TEST_TR) ? highlightR : R;
		canvas.beginPath();
		canvas.arc(this.resizeW, this.resizeH>>1, r, 0, Math.PI * 2);
		canvas.fill();
		canvas.stroke();
		
		r = (this.hitTest == C_HIT_TEST_BL) ? highlightR : R;
		canvas.beginPath();
		canvas.arc(this.resizeW>>1, this.resizeH, r, 0, Math.PI * 2);
		canvas.fill();
		canvas.stroke();

		r = (this.hitTest == C_HIT_TEST_BR) ? highlightR : R;
		canvas.beginPath();
		canvas.arc(this.resizeW, this.resizeH, r, 0, Math.PI * 2);
		canvas.fill();
		canvas.stroke();

		return;
	}

	this.paint = function(uiCanvasElement, canvas) {
		if(image.width > 0 && image.height > 0) {
			var str = "";
			var w = this.canvasW;
			var h = this.canvasH;
			var scale = this.scale ? (1/this.scale) : 1;

			canvas.drawImage(image, 0, 0, image.width, image.height, 0, 0, this.imageW, this.imageH);	
			canvas.drawImage(image, 0, 0, image.width, image.height, 0, 0, this.resizeW, this.resizeH);	
			this.paintResizeRect(canvas);

			w = Math.round(this.resizeW * scale);
			h = Math.round(this.resizeH * scale);
			str = w + " x " + h;
		
			canvas.textAlign = "center";
			canvas.textBaseline = "bottom";
			uiCanvasElement.style.setFontSize(28);
			canvas.font = uiCanvasElement.style.getFont();
			canvas.fillStyle = "Gold";
			canvas.fillText(str, uiCanvasElement.w>>1, uiCanvasElement.h); 
		}
	}

	this.resize = function(onOK) {
		var image = this.image;
		var scale = this.scale ? (1/this.scale) : 1;
		var w = this.resizeW * scale;
		var h = this.resizeH * scale;
		
		var size = {};
		size.w = Math.round(w);
		size.h = Math.round(h);

		onOK(size);

		return image;
	}

	this.init(uiCanvasElement, image);

	return;
}

function resizeImageInit(win, image) {
	var uiCanvasElement = win.findChildByType("ui-canvas");
	var controller = new ResizeImageController(uiCanvasElement, image);

	win.controller = controller;

	return;
}

function resizeImagePaint(uiCanvasElement, canvas) {
	var controller = uiCanvasElement.getWindow().controller;
	if(controller) {
		controller.paint(uiCanvasElement, canvas);
	}

	return;
}

function resizeHandlePointerDown(uiCanvasElement, x, y) {
	var controller = uiCanvasElement.getWindow().controller;
	if(controller) {
		controller.handlePointerDown(x, y);
	}

	return;
}

function resizeHandlePointerMove(uiCanvasElement, x, y) {
	var controller = uiCanvasElement.getWindow().controller;
	if(controller) {
		controller.handlePointerMove(x, y);
	}

	return;
}

function resizeHandlePointerUp(uiCanvasElement, x, y) {
	var controller = uiCanvasElement.getWindow().controller;
	if(controller) {
		controller.handlePointerUp(x, y);
	}

	return;
}

function resizeItAndReturn(uiCanvasElement) {
	var controller = uiCanvasElement.getWindow().controller;
	if(controller) {
		controller.resize(
			function(size) {
				uiCanvasElement.closeWindow(size);
			}
		);
	}

	return;
}

function imageEditorResizeImage(button) {
	if(gImageEditorApp.hasImage()) {
		var image = gImageEditorApp.cropImageCanvas;
		button.openWindow("win-resize", 
			function (size) {
					if(size) {
						setTimeout(function() {
							gImageEditorApp.resize(size.w, size.h);
						}, 800);
					}
				}, false, image);
	}
	
	return;
}

//////////////////////////////////////////////////////////////////////
//
var gImageEditorApp;

function getImageEditorApp(win) {
	if(!gImageEditorApp && win) {
		gImageEditorApp = new ImageEditorApp(win);
	}

	return gImageEditorApp;
}

