function UserLayers() {
	}

UserLayers.prototype.startup = function () {
	this.node = dojo.byId("Canvas");
	this.layers = new Array();
	this.images = new Array();
	this.lastlayer = 0;
	
	this.selector = new Object();
	this.selector.border = 1;
	this.selector.node = document.createElement("div");
	dojo.addClass(this.selector.node, "selector");
	this.selector.node.style.borderWidth = this.selector.border + "px";
	this.selector.node.style.zIndex = 999;
	dojo.byId("Canvas").appendChild(this.selector.node);
	this.selector.toggler = new dojo.fx.Toggler({
		node : this.selector.node,
		hideDuration: 500,
		showDuration: 250
		});

	dojo.connect(this.node, "onmousedown", this, "onMouseDown");
	this.list = new dojo.dnd.Source("LayerList",{
			singular: true,
			creator: this.listCreator
			});
	
	// Select a layer on canvas when one is clicked in the list.
	dojo.connect(this.list, "onMouseDown", this, function () {
		if (this.list.getSelectedNodes()[0]) {
			this.selectLayer(this.list.getItem(this.list.getSelectedNodes()[0].id).data);
		}
	});

		// Key listeners.
	this.interval = 0;
	dojo.connect(dojo.body(), "onkeydown", this, function (e) {
		var layer = this.getSelectedLayer();
		if (!layer) {
			// If no layer selected, or if an interval is already in effect, nothing to do.
			return;
		}
		var action;
		switch (e.keyCode) {
			case 37: // LEFT
				action = function () { layer.moveNode(-1, 0); }; break;
			case 38: // UP
				action = function () { layer.moveNode(0, -1); }; break;
			case 39: // RIGHT
				action = function () { layer.moveNode(1, 0); }; break;
			case 40: // DOWN
				action = function () { layer.moveNode(0, 1); }; break;
			case 107: // KP PLUS
			case 187: // KB PLUS
				action = function () { layer.scaleNode(1); }; break;
			case 109: // KP MINUS
			case 189: // KB MINUS
				action = function () { layer.scaleNode(-1); }; break;
		}
		if (action) {
			dojo.stopEvent(e);
			if (!this.interval) {
				this.interval = setInterval(action, 47);
			}
		}
	});
	
	// Reorder layers on canvas when drop
	dojo.subscribe("/dnd/drop", this, function (source, nodes, copy, target) {
		if (target == this.list) {
			var allnodes = this.list.getAllNodes();
			var layers = new Array();
			for (var i in allnodes) {
				// Not all nodes returned correspond to layer nodes. Only the ones
				// that have a "dojo unique" id.
				if (allnodes[i].id) {
					layers.push(this.list.getItem(allnodes[i].id).data);
				}
			}
			// Order layers in reverse order then in the list.
			var o = 0;
			var i = layers.length - 1;
			do {
				o++;
				layers[i].setOrder(o);
			} while (i--);
		}
	});
	

	dojo.connect(dojo.body(), "onkeyup", this, function (e) {
		if (this.interval) {
			clearInterval(this.interval);
			this.interval = 0;
			dojo.stopEvent(e);
		}
	});
	
	user.rpc.listRemoteImages().addCallback(this, function(res) {
		this.images = res;
	}).addErrback(this, function(msg) {
		user.alert("Could not retreive images.<br />" + msg);
	});


	user.rpc.listFonts().addCallback(this, function(res) {
		this.fonts = res;
	}).addErrback(this, function(msg) {
		user.alert("Could not retrieve fonts list.<br />" + msg);
	});

	this.createLayerControls();
	this.updateCoords();
	
	this.selectLayer();

}

// LAYER CREATION & MANIPULATION


UserLayers.prototype.listCreator = function(item, hint) {
	var container = document.createElement("div");
	var node = document.createElement("div");
	dojo.addClass(node, item.type);
	if (item.name.length > 20) {
		node.innerHTML = item.name.substr(0, 17) + "...";
	} else {
		node.innerHTML = item.name;
	}
	container.appendChild(node);
	return {
		node: container,
		data: item,
		type: ["layer"]
		};
}

UserLayers.prototype.onMouseDown = function(e) {
	// When the mask or selector is clicked, the event should be passed
	// down to the next topmost movable layer. So figure out
	// what that should be by finding the intersecting layers.
	this.updateCoords();
	var x = e.pageX - this.x;
	var y = e.pageY - this.y;
	
	var maxOrder = 0;
	var layer, topmost;
	for (var i in this.layers) {
		layer = this.layers[i];
		if (layer.move && x >= layer.coords.l && x <= layer.coords.r && y >= layer.coords.t && y <= layer.coords.b) {
			if (layer.order >= maxOrder) {
				maxOrder = layer.order;
				topmost = layer;
			}
		}
	}

	// If found something...
	if (topmost) {
		this.selectLayer(topmost.id);
		
		// Check if it was actually a resize handle that was clicked instead.
		if (topmost.resize && x >= topmost.coords.handle.l && x <= topmost.coords.handle.r && y >= topmost.coords.handle.t && y <= topmost.coords.handle.b) {
			topmost.resizer._beginSizing(e);
		} else {
			topmost.mover.onMouseDown(e);
		}
	} else {
		this.selectLayer();
	}

	dojo.stopEvent(e);
}

UserLayers.prototype.addLayer = function(layer) {
	if (!layer.id) {
		return;
	};
	this.layers[this.layers.length] = layer;
	this.reorderLayers();
	this.list.selectAll();
	this.list.deleteSelectedNodes();
	this.list.insertNodes(false, this.getOrderedLayers().reverse());
	this.selectLayer(layer);
}

UserLayers.prototype.reorderLayers = function () {
	// Reorders the *same* array with each layer assigned an order according
	// to their index in the array.
	var n = 1;
	for (var i in this.layers) {
		this.layers[i].setOrder(n);
		n++;
	}
}

UserLayers.prototype.getOrderedLayers = function () {
	// Returns a *new* array with the layers in order according to their
	// *existing* orders.
	var layers = this.layers.slice();
	layers.sort(function (a, b) {
		if (a.order < b.order) {
			return -1;
		} else if (a.order > b.order){
			return 1;
		} else {
			return 0;
		}
	});
	return layers;
}

UserLayers.prototype.findLayer = function (layer) {
	if (typeof(layer) == "number") {
		return this.layers[layer];
	} else if (typeof(layer) == "string") {
		for (var i in this.layers) {
			if (this.layers[i].id == layer) {
				return this.layers[i];
			}
		}
	} else if (typeof(layer) == "object") {
		return layer;
	}
}

UserLayers.prototype.findLayerByOrder = function (order) {
	for (var i in this.layers) {
		if (this.layers[i].order == order) {
			return this.layers[i];
		}
	}
}

UserLayers.prototype.switchLayers = function (layer1, layer2) {
	if (layer1 && layer2) {
		var order1 = layer1.order;
		var order2 = layer2.order;
		layer1.setOrder(order2);
		layer2.setOrder(order1);
	}
}

UserLayers.prototype.changeLayerOrder = function (layer, jump) {
	layer = this.findLayer(layer);
	if (jump > 0) {
		for (var j = 1; j <= jump; j++) {
			this.switchLayers(layer, this.findLayerByOrder(layer.order + 1));
		}
	} else if (jump < 0) {
		for (var j = -1; j >= jump; j--) {
			this.switchLayers(layer, this.findLayerByOrder(layer.order - 1));
		}
	}
}

UserLayers.prototype.getSelectedLayer = function () {
	for (var i in this.layers) {
		if (this.layers[i].selected) {
			return this.layers[i];
		}
	}
}

UserLayers.prototype.selectLayer = function (whichlayer) {
	layer = this.findLayer(whichlayer);
	var show = false;
	var hide = true;
	for (var i in this.layers) {
		if (layer && layer.id == this.layers[i].id) {
			if (!this.getSelectedLayer()) {
				// If there was nothing selected before, show the selector.
				show = true;
			} else {
				// If there's something to select now and it's movable, don't hide the selector.
				hide = false;
			}
			this.layers[i].onSelect();
		} else {
			this.layers[i].onUnselect();
		}
	}
	if (show) {
		this.selector.toggler.show();
	} else 	if (hide) {
		this.selector.toggler.hide();
	}
	
	// Select the layer in the list.
	// Unfortunately, there is no programatic way of doing this
	// in the Dojo DND Selector.js, so gotta hack in the selection.
	this.list.selectNone();
	var listnodes = this.list.getAllNodes();
	for (var i in listnodes) {
		// Find what node in the list corresponds to this layer.
		if (layer && listnodes[i].id && layer.id == this.list.getItem(listnodes[i].id).data.id) {
			this.list._addItemClass(dojo.byId(listnodes[i].id), "Selected");
			this.list.selection[listnodes[i].id] = 1;
		}
	}
	
	this.createLayerControls(layer);
}

UserLayers.prototype.createLayerControlButton = function (x, y, w, h, action, repetitive) {
	var node = document.createElement("div");
	dojo.addClass(node, "control");
	node.style.left = x + "px";
	node.style.top = y + "px";
	node.style.backgroundImage = "url('images/layercontrols_fg.png')";
	node.style.backgroundPosition = (-x) + "px " + (-y) + "px";
	node.style.width = w + "px";
	node.style.height = h + "px";
	dojo.connect(node, "onmouseover", function () {
		node.style.backgroundPosition = (-x) + "px " + (-105 - y) + "px";
	});
	dojo.connect(node, "onmouseout", function () {
		node.style.backgroundPosition = (-x) + "px " + (-y) + "px";
	});
	var interval = 0;
	dojo.connect(node, "onmousedown", function () {
		action();
		if (repetitive) {
			interval = setInterval(action, 15);
		}
	});
	dojo.connect(node, "onmouseup", function () {
		clearInterval(interval);
	});
	return node;
}

UserLayers.prototype.createLayerControls = function (layer) {
	dojo.byId("LayerControls").innerHTML = "";
	if (!layer) {
		var node = document.createElement("img");
		node.src = "images/pic_layers_placeholder.jpg"
		dojo.byId("LayerControls").appendChild(node);
	} else {
		var node, container;
		
		// SUMMARY
		
		container = document.createElement("div");
		dojo.addClass(container, "summary");
		dojo.byId("LayerControls").appendChild(container);
		node = document.createElement("div");

		if(layer.type != 'template'){

			node = document.createElement("img");
			if (layer.type == "image")
				node.src = layer.src.replace(".image.", ".thumb.");
			else
				node.src = "images/textlayer.png";
			container.appendChild(node);

			node = document.createElement("div");
			dojo.addClass(node, "delete");
			dojo.addClass(node, "pseudolink");
			node.innerHTML = "delete";
			dojo.connect(node, "onclick", function () {
				user.user_layers.deleteSelectedLayer();
			});
			container.appendChild(node);

			node = document.createElement("div");
			dojo.addClass(node, "copy");
			dojo.addClass(node, "pseudolink");
			node.innerHTML = "copy";
			dojo.connect(node, "onclick", function () {
				user.user_layers.copySelectedLayer();
			});
			container.appendChild(node);
		
			if (layer.type == "text") {
				node = document.createElement("div");
				dojo.addClass(node, "change");
				dojo.addClass(node, "pseudolink");
				node.innerHTML = "change";
				dojo.connect(node, "onclick", function () {
					user.user_layers.openTextLayerDialog(true);
				});
				container.appendChild(node);
			}
		
			node = document.createElement("span");
			node.innerHTML = layer.name.length > 12 ? layer.name.substr(0, 12) + "..." : layer.name;
			container.appendChild(node);
		
			// BG
		
			container = document.createElement("div");
			dojo.addClass(container, "bg");
			dojo.byId("LayerControls").appendChild(container);
		
			container.appendChild(this.createLayerControlButton(39, 38, 14, 15, function () {
				layer.alignNode(false, true, false, false, true, false);
			}, false)); // Center
		
			container.appendChild(this.createLayerControlButton(10, 39, 16, 13, function () {
				layer.moveNode(-1, 0);
			}, true)); // Move L
		
			container.appendChild(this.createLayerControlButton(65, 39, 16, 13, function () {
				layer.moveNode(1, 0);
			}, true)); // Move R
		
			container.appendChild(this.createLayerControlButton(38, 10, 15, 17, function () {
				layer.moveNode(0, -1);
			}, true)); // Move T
		
			container.appendChild(this.createLayerControlButton(38, 65, 15, 17, function () {
				layer.moveNode(0, 1);
			}, true)); // Move B
		
			container.appendChild(this.createLayerControlButton(17, 17, 12, 13, function () {
				layer.moveNode(-1, -1);
			}, true)); // Move TL
		
			container.appendChild(this.createLayerControlButton(62, 17, 12, 13, function () {
				layer.moveNode(1, -1);
			}, true)); // Move TR
		
			container.appendChild(this.createLayerControlButton(17, 61, 12, 13, function () {
				layer.moveNode(-1, 1);
			}, true)); // Move BL
		
			container.appendChild(this.createLayerControlButton(62, 61, 12, 13, function () {
				layer.moveNode(1, 1);
			}, true)); // Move BR
		
			container.appendChild(this.createLayerControlButton(4, 4, 13, 13, function () {
				layer.alignNode(true, false, false, true, false, false);
			}, false)); // Align TL
		
			container.appendChild(this.createLayerControlButton(37, 4, 17, 3, function () {
				layer.alignNode(false, false, false, true, false, false);
			}, false)); // Align T
		
			container.appendChild(this.createLayerControlButton(74, 4, 13, 13, function () {
				layer.alignNode(false, false, true, true, false, false);
			}, false)); // Align TR
		
			container.appendChild(this.createLayerControlButton(4, 37, 3, 17, function () {
				layer.alignNode(true, false, false, false, false, false);
			}, false)); // Align L
		
			container.appendChild(this.createLayerControlButton(84, 37, 3, 17, function () {
				layer.alignNode(false, false, true, false, false, false);
			}, false)); // Align R
		
			container.appendChild(this.createLayerControlButton(4, 74, 13, 13, function () {
				layer.alignNode(true, false, false, false, false, true);
			}, false)); // Align BL
		
			container.appendChild(this.createLayerControlButton(37, 84, 17, 3, function () {
				layer.alignNode(false, false, false, false, false, true);
			}, false)); // Align B
		
			container.appendChild(this.createLayerControlButton(74, 74, 13, 13, function () {
				layer.alignNode(false, false, true, false, false, true);
			}, false)); // Align BR
		
			container.appendChild(this.createLayerControlButton(106, 3, 15, 15, function () {
				user.user_layers.rotateLayer(layer, 1);
			}, false)); // Rotate CW
		
			container.appendChild(this.createLayerControlButton(146, 3, 16, 15, function () {
				user.user_layers.rotateLayer(layer, -1);
			}, false)); // Rotate CCW
		
			if (layer.type == "text") {
				container.appendChild(this.createLayerControlButton(106, 38, 16, 17, function () {
					user.alert("To resize text layers, change the font size for that layer.");
				}, false)); // Zoom IN
			
				container.appendChild(this.createLayerControlButton(146, 38, 16, 17, function () {
					user.alert("To resize text layers, change the font size for that layer.");
				}, false)); // Zoom OUT
			} else {
				container.appendChild(this.createLayerControlButton(106, 38, 16, 17, function () {
					layer.scaleNode(1);
				}, true)); // Zoom IN
			
				container.appendChild(this.createLayerControlButton(146, 38, 16, 17, function () {
					layer.scaleNode(-1);
				}, true)); // Zoom OUT
			}
		
			container.appendChild(this.createLayerControlButton(109, 73, 11, 15, function () {
				layer.alignNode(false, false, false, false, true, false);
			}, false)); // Center V
		
			container.appendChild(this.createLayerControlButton(146, 75, 15, 11, function () {
				layer.alignNode(false, true, false, false, false, false);
			}, false)); // Center H
		
			if (layer.type == "text") {
				node = document.createElement("div");
				dojo.addClass(node, "pseudolink");
				node.innerHTML = "Update Text Curvature";
				node.style.paddingTop = "107px";
				node.style.fontSize = "9px";
				node.style.textDecoration = "underline";
				node.style.cursor = "pointer";
				dojo.connect(node, "onclick", function () {
					user.user_layers.curveLayer(user.user_layers.getSelectedLayer());
				});
				container.appendChild(node);
			}
		} else {
			node = document.createElement("img");
			node.src = layer.src.replace("_template.","_preview.");
			node.style.width = '19px';
			node.style.height = '14px';
			container.appendChild(node);

			node = document.createElement("div");
			dojo.addClass(node, "delete");
			dojo.addClass(node, "pseudolink");
			node.innerHTML = "delete";
			dojo.connect(node, "onclick", function () {
				user.user_layers.deleteSelectedLayer();
			});
			container.appendChild(node);

			node = document.createElement("div");
			dojo.addClass(node, "change");
			dojo.addClass(node, "pseudolink");
			node.innerHTML = "change";
			dojo.connect(node, "onclick", function () {
				user.templates.openTemplateSelector(true);
			});
			container.appendChild(node);
			
			node = document.createElement("span");
			node.innerHTML = "Template layer";
			container.appendChild(node);
		}
	}
}

UserLayers.prototype.copySelectedLayer = function () {
	user.addLoaderEvent();
	user.user_layers.lastlayer++;
	var selected = user.user_layers.getSelectedLayer();
	user.rpc.copyLayer(session, selected.id, user.user_layers.lastlayer).addCallback(function(res) {
		user.removeLoaderEvent();
		user.user_layers.addLayer(new Layer(res));
	}).addErrback(function(msg) {
		user.removeLoaderEvent();
		user.alert("Could not complete layer copy.<br />" + msg);
	});
}

UserLayers.prototype.deleteSelectedLayer = function () {
	var selected = user.user_layers.getSelectedLayer();
	for (var i in user.user_layers.layers) {
		if (selected && selected.id == user.user_layers.layers[i].id) {
			user.user_layers.list.deleteSelectedNodes();
			user.user_layers.selectLayer();
			selected.onDelete();
			user.user_layers.layers.splice(i, 1);
		}
	}
	user.user_layers.reorderLayers();
}

UserLayers.prototype.replaceSelectedLayer = function (layer) {
	if (!layer.id) {
		return;
	}
	// Make sure the layers start out in the correct order.

	this.layers = this.getOrderedLayers();
	var selected = user.user_layers.getSelectedLayer();
	// Add the new layer.
	this.addLayer(layer);
	// Set the new layer's order to match the previous one.
	this.changeLayerOrder(layer, selected.order - layer.order + 1);

	this.layers = this.getOrderedLayers();
	// Redraw the layer list.
	this.list.selectAll();
	this.list.deleteSelectedNodes();
	this.list.insertNodes(false, this.getOrderedLayers().reverse());
	// Get rid of the previous layer.
	this.selectLayer(selected);
	this.deleteSelectedLayer();
	// Select the new one.
	this.selectLayer(layer);
}

UserLayers.prototype.rotateLayer = function (layer, direction) {
	user.addLoaderEvent();
	user.user_layers.lastlayer++;
	user.rpc.rotateLayer(session, layer.id, user.user_layers.lastlayer, direction).addCallback(function (res) {
		user.removeLoaderEvent();
		var selected = user.user_layers.getSelectedLayer();
		res.left = selected.coords.l;
		res.top = selected.coords.t;
		user.user_layers.replaceSelectedLayer(new Layer(res));
	}).addErrback(function(msg) {
		user.removeLoaderEvent();
		user.alert("Could not complete layer rotation.<br />" + msg);
	});
}

UserLayers.prototype.curveLayer = function (layer) {
	var productRadius = user.templates.productList[user.templates.currentProduct].file == 'Mug'? 1106: 2087;
	user.addLoaderEvent();
	user.rpc.curveLayer(session, layer.id, layer.coords.l, layer.coords.t, productRadius).addCallback(function (res) {
		user.removeLoaderEvent();
		layer.src = res.src;
		layer.uploadedsrc = res.uploadedsrc;
		layer.image.src = res.src;
		layer.width = res.width;
		layer.height = res.height;
		layer.node.style.width = res.width + "px";
		layer.node.style.height = res.height + "px";
		layer.updateCoords();
	}).addErrback(function(msg) {
		user.removeLoaderEvent();
		user.alert("Could not complete layer curvature.<br />" + msg);
	});
}

UserLayers.prototype.updateCoords = function () {
	this.x = 0;
	this.y = 0;
	var el = dojo.byId("Canvas");
	do {
		this.x += el.offsetLeft;
		this.y += el.offsetTop;
	} while ((el = el.offsetParent) != null);
}


// DIALOGS

UserLayers.prototype.openCreateImageLayerDialog = function (replace) {
	var container = document.createElement("div");
	container.id = "dImageLayerDialog";
	
	var img = document.createElement("img");
	img.src = "images/pic_images.jpg";
	container.appendChild(img);
	
	var node = document.createElement("input");
	container.appendChild(node);
	var widget = new dojox.widget.FileInputBlind({
		url: "uploader.php?session=" + session + "&nocache",
		name: "file",
		blurDelay: 0,
		label: "My Computer",
		uploadMessage: "Uploading... please wait!"
	}, node);
	widget.startup();

	var div = document.createElement("div");
	dojo.addClass(div,"bOpenRemoteSelector");
	var button = new dijit.form.Button({label: "Pics Images", layoutAlign: "center"});
	dojo.addClass(button.domNode.childNodes[0], "half");
	div.appendChild(button.domNode);
	container.appendChild(div);	
	dojo.connect(button, "onClick", this, function(){
		dialog.destroy();
		user.user_layers.openRemoteImageLayerDialog();
	});


	var dialog = user.openDialog((replace === true ? "Change Image" : "Add Image"), container);

// The dojo widget starts uploading on blur, but that's not always intuitive
	// to know what's going on, so let's destroy the onBlur stuff, and do our own.
	// A timed interval will be used to continuously check if the input already has
	// a file, and if it does and it hasn't been sent already, it will send it.
		widget._onBlur = function () {};
		var sent = false;
		var interval = setInterval(function () {
			if (!sent && widget.fileInput.value) {
				var ext = widget.fileInput.value.substr(widget.fileInput.value.lastIndexOf(".") + 1).toLowerCase();
				if (ext != "jpg" && ext != "jpeg" && ext != "png" && ext != "gif") {
					widget.destroy();
					dialog.destroy();
					user.alert("Invalid file extension. Please upload JPEG, PNG or GIF images only.");
					return;
				}
				sent = true;
				if (interval) {
					clearInterval(interval);
				}
				user.addLoaderEvent();
				widget._sendFile();
			}
		}, 500);
	
		widget.onComplete = function () {
			user.user_layers.lastlayer++;
			user.rpc.pickupImageUpload(session, user.user_layers.lastlayer).addCallback(function(res) {
				user.removeLoaderEvent();
				if (interval) {
					clearInterval(interval);
				}
				if (replace === true) {
					user.user_layers.replaceSelectedLayer(new Layer(res));
				} else {
					user.user_layers.addLayer(new Layer(res));
				}
			}).addErrback(function(msg) {
				user.removeLoaderEvent();
				if (interval) {
					clearInterval(interval);
				}
				user.alert("Could not complete image upload.<br />" + msg);
			});
			dialog.destroy();
		}
}

UserLayers.prototype.openTextLayerDialog = function (replace) {
	if (replace === true) {
		// Must check for actually "true", as the default call sends a mouse event object...
		this.textSettings = this.getSelectedLayer().meta;
	} else {
		// If settings don't exist yet, set the defaults.
		if (!this.textSettings) {
			this.textSettings = {
				text: "",
				size: 24,
				color: "rgb(0, 0, 0)",
				font: this.fonts[0],
				curved: true
			};
		}
	}
	var node, button;
	var container = document.createElement("div");
	container.id = "dAddEditText";
	
	var img = document.createElement("img");
	img.src = "images/pic_text.jpg";
	container.appendChild(img);
	
	// Text
	var row1 = document.createElement("div");
	dojo.addClass(row1, 'row');
	
	node = document.createElement("div");
	node.innerHTML = "Enter text:";
	row1.appendChild(node);

	node = document.createElement("div");
	var textBox = new dijit.form.TextBox({trim: true, value: this.textSettings.text});
	node.appendChild(textBox.domNode);
	row1.appendChild(node);

	node = document.createElement("div");
	dojo.addClass(node, "spacer");
	row1.appendChild(node);
	
	// Size
	node = document.createElement("div");
	node.innerHTML = "Select size:";
	row1.appendChild(node);
	
	node = document.createElement("div");
	var sizeBox = new dijit.form.NumberSpinner({value: this.textSettings.size, constraints: {min:8, max:240}, style:'width: 58px'});
	node.appendChild(sizeBox.domNode);
	container.appendChild(node);
	row1.appendChild(node);
	container.appendChild(row1);
	
	node = document.createElement("div");
	dojo.addClass(node, "spacer");
	container.appendChild(node);
	
	// Font
	fontdiv = document.createElement("div");
	dojo.addClass(fontdiv,'cell');

	node = document.createElement("div");
	node.innerHTML = "Select font:";
	fontdiv.appendChild(node);

	node = document.createElement("div");
	button = new dijit.form.Button({label: "<div id='fontSelectorButton'>" + this.textSettings.font + "</div>"});
	node.appendChild(button.domNode);
	dojo.connect(button, "onClick", this, "openFontDialog");
	fontdiv.appendChild(node);
	container.appendChild(fontdiv);

	// Color and Text on Curve

	colordiv = document.createElement("div");
	dojo.addClass(colordiv,'cell');

	node = document.createElement("div");
	node.innerHTML = "Select color:";
	colordiv.appendChild(node);

	node = document.createElement("div");
	button = new dijit.form.Button({label: "<div class='color icon' id='textColorSelectorButton' style='background-color: " + this.textSettings.color + ";'></div>"});
	dojo.addClass(button.domNode.childNodes[0], "small");
	node.appendChild(button.domNode);
	dojo.connect(button, "onClick", function () {
		user.openColorDialog("Select Text Color", function (value) {
			dojo.byId("textColorSelectorButton").style.backgroundColor = value;
		}, '');
	});
	colordiv.appendChild(node);
	container.appendChild(colordiv);

	// Check-box for curvature
	curvediv = document.createElement("div");
	dojo.addClass(curvediv,'cell');

	node = document.createElement("div");
	node.innerHTML = "Text on Curve:";
	curvediv.appendChild(node);
	
	var textOnCurve = this.textSettings.curved;
	node = document.createElement("div");
	var cbox = new dijit.form.CheckBox({checked: textOnCurve});
	node.appendChild(cbox.domNode);
	dojo.connect(cbox,"onClick", function () {
		textOnCurve = !textOnCurve;
    });
	curvediv.appendChild(node);
	container.appendChild(curvediv);

	node = document.createElement("div");
	dojo.addClass(node, "spacer");
	container.appendChild(node);
	
	// Button
	node = document.createElement("div");
	node.style.textAlign = "center";
	button = new dijit.form.Button({label: "Create Text"});
	node.appendChild(button.domNode);
	container.appendChild(node);
	
	var dialog = user.openDialog((replace === true ? "Edit Text" : "Add Text"), container);
//	var dialog = user.openDialog("Edit Text", container);

	dojo.connect(button, "onClick", function () {
		if (textBox.getValue().length < 1) {
			dialog.destroy();
			return;
		}
		user.addLoaderEvent();
		// Save settings for next time.
		user.user_layers.textSettings = {
			text: textBox.getValue(),
			size: sizeBox.getValue(),
			color: dojo.byId("textColorSelectorButton").style.backgroundColor,
			font: dojo.byId("fontSelectorButton").innerHTML
		}

		// The callback will be different, depending on whether we're replacing or not... (replaceLayer instead of addLayer).
		if (replace === true) {
			selected = user.user_layers.getSelectedLayer();
			id = selected.id;
			t = selected.coords.t;
			l = selected.coords.l;
			var callback = function (res) {
				user.removeLoaderEvent();
				res.left = l;
				res.top = t;
				user.user_layers.replaceSelectedLayer(layer = new Layer(res));
				if(textOnCurve) {
					layer.meta.curved = true;
					user.user_layers.curveLayer(layer);
				} else 
					layer.meta.curved = false;
			};
		} else {
			id = ++user.user_layers.lastlayer;
			var callback = function (res) {
				user.removeLoaderEvent();
				user.user_layers.addLayer(layer = new Layer(res));
				if(textOnCurve){
					layer.meta.curved = true;
					user.user_layers.curveLayer(layer);				
				} else 
					layer.meta.curved = false;
			};
		}
		user.rpc.createTextLayer(session, id, user.user_layers.textSettings.text, user.user_layers.textSettings.size, user.user_layers.textSettings.color, user.user_layers.textSettings.font).addCallback(callback).addErrback(function (msg) {
			user.removeLoaderEvent();
			user.alert("Could not create text layer.<br />" + msg);
		});
		user.user_layers.textSettings = null;
		dialog.destroy();
	});
}

UserLayers.prototype.openFontDialog = function () {
	var node = document.createElement("div");
	node.id = "fontSelector";
	var dialog = user.openDialog("Select Font", node);
	for (var i in this.fonts) {
		var div = document.createElement("div");
		var img = document.createElement("img");
		img.src = "fonts/preview/" + this.fonts[i] + ".png";
		img.font = this.fonts[i];
		div.appendChild(img);
		node.appendChild(div);
		dojo.connect(img, "onclick", function () {
			dojo.byId("fontSelectorButton").innerHTML = this.font;
			dialog.destroy();
		});
	}
}

UserLayers.prototype.openRemoteImageLayerDialog = function () {
	var currentSelection = 0;
	var layersettings = new Object();
	var imageSelected = false;
	
	var node = document.createElement("div");
	node.id = "dRemoteImageSelector";
	
	var imageContainer = document.createElement("div");
	imageContainer.id = "imagePreviewContainer";
	node.appendChild(imageContainer);

	for (var i in this.images) {
		var div = document.createElement("div");

		var img = document.createElement("img");
		img.id = "remoteImage_" + i;
		img.name = this.images[i].name;
		img.ext = this.images[i].ext;
		img.src = "pics-images/" + img.name + "_preview." + img.ext;
		img.previewnumber = i;
		
		if (i == currentSelection && imageSelected) {
			dojo.addClass(img,"selected");
		}
		
		dojo.connect(img,"onclick", function (e){
			dojo.removeClass(dojo.byId("remoteImage_" + currentSelection),"selected");
			dojo.addClass(dojo.byId("remoteImage_" + this.previewnumber),"selected");
			layersettings.src = "pics-images/" + this.name + ".image." + this.ext;
			layersettings.uploadedsrc = layersettings.src;
			layersettings.name = this.name;
			currentSelection = this.previewnumber;
			imageSelected = true;
		});
		div.appendChild(img);
		imageContainer.appendChild(div);
	}
		
	var spacer = document.createElement("div");
	dojo.addClass(spacer, "spacer");
	node.appendChild(spacer);	
	
	var button = new dijit.form.Button({label: "OK"});
	node.appendChild(button.domNode);
		
	var dialog = user.openDialog("Select Pics Images",node)	

	dojo.connect(button, "onClick", function () {
		dialog.destroy();
		if(imageSelected)
				user.user_layers.lastlayer++;
				layersettings.id = "Layer_" + user.user_layers.lastlayer + "_" + layersettings.name;
				layersettings.selected = true;
				layersettings.type = "image";
				layersettings.order = this.lastlayer;
				layersettings.left = 200;
				layersettings.top = 100;
				layersettings.rotation = 0;
			 	layersettings.move = true;
				layersettings.bounded = true;
				layersettings.resize = true;
				layersettings.keepratio = true;
				layersettings.meta = null;
				user.rpc.addLayerWithServerImage(session, layersettings).addCallback(function(res){
				layersettings = res;
				user.user_layers.addLayer(new Layer(layersettings));
			}).addErrback(function(res){
				user.alert("Could not create layer.<br />" + msg);
			});
	});
}

UserLayers.prototype.openPrintDialog = function () {
	var node = document.createElement("div");
	node.style.backgroundImage = "url('images/pic_print.jpg')";
	node.style.backgroundRepeat = "no-repeat";
	node.style.width = "493px";
	node.style.height = "156px";
	node.style.textAlign = "right";
	var img = document.createElement("img");
	img.src = "images/bigloader.gif";
	img.style.marginTop = "28px";
	img.style.marginBottom = "28px";
	img.style.marginRight = "40px";
	node.appendChild(img);
	var dialog = user.openDialog("Creating Preview", node);

	var printLayers = this.getOrderedLayers();

	var reqLayers = new Array();
	for (var i in printLayers) {
		reqLayers[i] = {
			id: printLayers[i].id,
			type: printLayers[i].type,
			order: printLayers[i].order,
			coords: printLayers[i].coords
		};
	}
	
	var reqTemplate = {
		background: user.templates.layer.bg.style.backgroundColor,
		product: user.templates.templateList[user.templates.currentProduct].product
	};

	// TODO: Connect dialog's cancel/close to cancel the rpc callback?
	
	user.rpc.printPreview(session, reqLayers, reqTemplate).addCallback(function (res) {
		dialog.destroy();

		if (res.src) {
			window.open(res.src, 'userFinal', 'toolbar=0,scrollbars=1,location=0,statusbar=0,menubar=0,resizable=1,width=800,height=600');
		} else {
			user.alert("Could not get preview image.<br />Invalid object received from the server.");
		}
	}).addErrback(function (msg) {
		dialog.destroy();
		user.alert("Could not get preview image.<br />" + msg);
	});
}


UserLayers.prototype.fileoOpenDialog = function () {
	var container = document.createElement("div");
	container.id = "dOpenFileDialog";
	
	var img = document.createElement("img");
	img.src = "images/pic_open.jpg";
	container.appendChild(img);
	
	var node = document.createElement("input");
	container.appendChild(node);
	var widget = new dojox.widget.FileInputBlind({
		url: "uploader.php?session=" + session + "&nocache",
		name: "file",
		blurDelay: 0,
		label: "Browse",
		uploadMessage: "Uploading... please wait!"
	}, node);
	widget.startup();

	var dialog = user.openDialog("Open File", container);
	
	widget._onBlur = function () {};
	var sent = false;
	var interval = setInterval(function () {
		if (!sent && widget.fileInput.value) {
			var ext = widget.fileInput.value.substr(widget.fileInput.value.lastIndexOf(".") + 1).toLowerCase();
			if (ext != "ins") {
				widget.destroy();
				dialog.destroy();
				user.alert("Invalid file extension. Please upload a valid Pics settings file (file extension .ins)");
				return;
			}
			sent = true;
			if (interval) {
				clearInterval(interval);
			}
			user.addLoaderEvent();
			widget._sendFile();
		}
	}, 500);
	
	widget.onComplete = function () {
		user.user_layers.lastlayer++;
		user.rpc.fileOpen(session).addCallback(function(res) {
			user.removeLoaderEvent();
			if (interval) {
				clearInterval(interval);
			}
			setup = res.setup;
			retLayers = res.layers;
			for(var i in retLayers){
				user.user_layers.addLayer(new Layer(retLayers[i]));
			}
			user.templates.layer.bg.style.backgroundColor = setup.background;
			user.templates.setProductFromFile(setup.product);
//			if(setup.template != '')
//				user.templates.setTemplateFromFile(setup);
		}).addErrback(function(msg) {
			user.removeLoaderEvent();
			if (interval) {
				clearInterval(interval);
			}
			user.alert("Could not open file.<br />" + msg);
		});
		dialog.destroy();
	}	
}

UserLayers.prototype.fileSaveDialog = function () {
	var node = document.createElement("div");
	node.style.backgroundImage = "url('images/pic_save.jpg')";
	node.style.backgroundRepeat = "no-repeat";
	node.style.width = "493px";
	node.style.height = "156px";
	node.style.textAlign = "right";
	var img = document.createElement("img");
	img.src = "images/bigloader.gif";
	img.style.marginTop = "28px";
	img.style.marginBottom = "28px";
	img.style.marginRight = "40px";
	node.appendChild(img);
	var dialog = user.openDialog("Saveing File", node);

	var saveLayers = this.getOrderedLayers();
	var reqLayers = new Array();
	for (var i in saveLayers) {
		reqLayers[i] = {
			id: saveLayers[i].id,
			src: saveLayers[i].src,
			upsource: saveLayers[i].uploadedsrc,
			name: saveLayers[i].name,
			type: saveLayers[i].type,
			order: saveLayers[i].order,
			width: saveLayers[i].width,
			height: saveLayers[i].height,
			coords: saveLayers[i].coords,
			rotation: saveLayers[i].rotation,
			meta: saveLayers[i].meta
		};
	}
	
	var reqSetup = {
		background: user.templates.layer.bg.style.backgroundColor,
		product: user.templates.templateList[user.templates.currentProduct].product
	};

	user.rpc.fileSave(session, reqLayers, reqSetup).addCallback(function(res){
		dialog.destroy();
		if (res) {
			window.open(res, 'userSave', 'toolbar=0,scrollbars=0,location=0,statusbar=0,menubar=0,resizable=0,width=300,height=200');
		} else {
			user.alert("Could not prepare save data.<br />Invalid object received from the server.");
		}
	}).addErrback(function (msg) {
		dialog.destroy();
		user.alert("Could not prepare save data.<br />" + msg);
	});

}
