function ItemLoader(editor) {
	
	function Item(x, y,  data) {
		
		this.getX = function() { return x; }
		this.getY = function() { return y; }
		this.getData = function() { return data; }
	}
	
	var items = [];
	var current = 0;
	var progressBar = $('#progressBar');
	
	this.addElement = function(x, y, data) {
		items.push ( new Item (x, y, data) );
	}
	
	this.run = function() {
		progressBar.progressBar({ 
			barImage: editor.getImageDir() + 'progressbg_green.gif',
			boxImage: editor.getImageDir() + 'progressbar.gif'
		}).show();

		loadNext();
		
	}
	
	function loadNext() {
		
		for (var n = 0; n < 25; n++) {
			if (current < items.length) {
				var item = items[current]
				
				if (item) {
					editor.addElement( item.getX(), item.getY(), item.getData() );
				}
				current++;
			}
			else {
				progressBar.fadeOut(500);
				editor.refresh();
				editor.show();
				return;
			}
		}
		showProgress();
		window.setTimeout(loadNext, 1);
		
	}
	
	function showProgress() {
		progressBar.progressBar(Math.ceil(100 / items.length * current));
	}
	
	
}
function CellFactory() {

	var cellPrototype = document.createElement('div');
	cellPrototype.setAttribute('class', 'cell');
	cellPrototype.setAttribute('className', 'cell');
	
	this.newCell = function() {
		return cellPrototype.cloneNode(false);		
	}
}

function CellBuilder(opts) {

	var cells = [];
	
	var canvas = opts.canvas;
	var columns = opts.width;
	var rows = opts.height;
	var parcelSize = opts.parcelSize;
	var baseDir = opts.baseDir;
	
	var currentRow = 0;
	var progressBar = $('#progressBar');
	var cellFactory = new CellFactory();
	
	this.run = function() {
		progressBar.progressBar({ 
			barImage: baseDir + '/images/progressbg_yellow.gif',
			boxImage: baseDir + '/images/progressbar.gif'
		});
		
		progressBar.show();
		
		canvas.innerHTML = '';
		go();
	}
	
	function go() {
		
		showProgress();
		buildRow(currentRow++);
		
		if (isFinish()) {
			
			progressBar.progressBar(100);
			
			progressBar.hide();
			if (opts.onFinish) {
				opts.onFinish(cells);
			}
			
		}
		else {
			window.setTimeout(go, 10);
		}
	}
	
	function showProgress() {
		progressBar.progressBar(Math.round(100 / rows * currentRow));
	}
	
	function isFinish() {
		return currentRow == rows;	
	}
	
	function buildRow(row) {
		
		cells[row] = {}
		
		for (var col = 0; col < columns; col++) {
			var cell = cellFactory.newCell();
			
			cell.style.top = (row * parcelSize) + "px";
			cell.style.left = (col * parcelSize) + "px";
			cell.setAttribute('x', row);
			cell.setAttribute('y', col);
			canvas.append(cell);

			cell.item = { kind: null, id: 0}
			
			cells[row][col] = cell;
		}
	}
}

function ImageFactory(imageDir, cellSize) {
	
	var images = {}; 
	
	this.getOrCreate = function(imageName) {
		
		if (!images[imageName]) {
			var img = document.createElement('img');
			img.setAttribute('src', imageDir + imageName + '.gif');
			img.setAttribute('height', cellSize);
			images[imageName] = img;
		}
		
		return images[imageName].cloneNode(false);
	}
}

function Editor() {
	var tools = [];
	var width = 0;
	var height = 0;
	var cells = [];
	var cellSize;
	
	var canvas = null;
	var imgDir = './';
	var parcelSize;
	var baseDir;
	
	var currentTool = null;
	var paletteItems = {};
	
	var that = this;
	
	var imageFactory;
	
	this.init = function(opts) {
		canvas = $('#canvas');
		canvas.hide();
		
		width = opts.width;
		height = opts.height;
		imgDir = opts.imgDir;
		mode = opts.mode;
		cellSize = opts.cellSize;
		parcelSize = cellSize + 3;
		baseDir = opts.baseDir;
		
		imageFactory = new ImageFactory(imgDir, cellSize);
		
		if (mode == 'edit') {
			setupPalette();
		}
		
		canvas.css({ height: (height * parcelSize) + "px" });
		
		var cellBuilder = new CellBuilder({
			baseDir: baseDir,
			canvas: canvas, 
			width: width, 
			height:height, 
			parcelSize: parcelSize,
			onFinish: function(result) {

				cells = result;
				
				initListeners();
				if (opts.onReady) {
					opts.onReady(that);
				}
			}
		});
		
		cellBuilder.run();
		
	};
	
	this.getImageDir = function() {
		return imgDir;
	}
	
	function initListeners() {

		var cellElements = $('.cell', canvas);
		
		cellElements.bind('click', function() {
			that.onClick(this);
		});
		
		var editMode = mode == 'edit';
		if (editMode) {
			
			cellElements.droppable({
				accept: '.item',
				hoverClass: 'hovered',
				drop: function(ev, ui) {
					
					var source = ui.draggable.get(0);
					var target = this;
					
					if (!isCellProtected( target )) {
						moveElement(source.getAttribute('x'), source.getAttribute('y'), target.getAttribute('x'), target.getAttribute('y'));
					}
					
					refreshRow( source.getAttribute('x') );
					refreshRow( target.getAttribute('x') );							
				}
			});

		}
		
	}
	
	this.hide = function() {
		canvas.hide();
	};
	
	this.show = function() {
		canvas.show();
	}

	this.addElement = function(x, y, item) {
		
		if (cells[x] && cells[x][y]) {
			cells[x][y].item = item;
		}
	}

	function moveElement(oldX, oldY, newX, newY) {
		if (newX == oldX && newY == oldY) {
			refreshRow(newX);
			return;
		}
		
		cells[newX][newY].item = cells[oldX][oldY].item;
		cells[oldX][oldY].item = {}
		cells[oldX][oldY].item.kind = null;
		cells[oldX][oldY].item.id = 0;
		refreshRow(newX);
		refreshRow(oldX);
	}

	
	this.refresh = function() {
		for (var x = 0; x < height; x++) {
			refreshRow(x);
		}
	};
	
	function refreshRow(x) {
		for (var y = 0; y < width; y++) {
			refreshCell(x,y)
		}
	}
	
	function getCell(x, y) { 
		if ( typeof x == "object" && typeof y == "undefined" ) {
			return x;
		}
		else {
			return cells[x][y];
		}
	}
	
	function refreshCell(x, y) {
		
		var cell = getCell(x, y);
		
		if (!cell) {
			return;
		}
		
		that.onDraw(cell);

		cell.innerHTML = "";

		if (cell.item && cell.item.kind) {
			var container = document.createElement('div');

			//var img = document.createElement('img');
			//img.setAttribute('src', imgDir + cell.item.image + '.gif');
			
			var img = imageFactory.getOrCreate(cell.item.image);
			
			img.setAttribute('class', cell.item.className);
			img.setAttribute('className', cell.item.className);
			container.appendChild(img);
			container.setAttribute('x', x);
			container.setAttribute('y', y);
			
			container.setAttribute('class', 'item');
			
			cell.appendChild(container);
			//console.info("appending", container);
			
			if ( mode == 'edit' && !isCellProtected(cell) ) {
				$(container).draggable({
					revert: 'invalid'
				});
			}
			// console.info(cell.item);
			if (cell.item.leaser) {
				//Prepare(cell, cell.item.leaser, cell.item.slogan);
				cell.onmouseover = function() {
					var tipContent = '<div style="width:152px;"><center>';
					
					if (cell.item.avatar) {
						tipContent += '<img style="width:150px;border:1px #ccc solid;margin-left:4px" src="' + baseDir + '/image/stream/' + cell.item.avatar + '" />';
					}
					tipContent += "<small>Parzelle " + cell.item.parcelNumber + "</small>";
					
					tipContent += "<p><b>" + cell.item.leaser + "</b></p>" + "<em>" + cell.item.slogan + "</em></center></div>"
					
					Tip(tipContent, FADEIN, 400, FADEOUT, 400, BGCOLOR, '#ffffff', PADDING, 15, WIDTH, 160);
				}
				cell.onmouseout = function() {
					UnTip();
				}
			}
			else if ( (mode != 'select') && cell.item.kind == 'parcel')  {
				// empty parcels in edit-mode must show their ids
				cell.onmouseover = function() {
					Tip("<center><p><b>Parzelle Nummer " + cell.item.parcelNumber + " (frei)</b></p>", FADEIN, 400, FADEOUT, 400, BGCOLOR, '#ffffff', PADDING, 15);
				}
				cell.onmouseout = function() {
					UnTip();
				}
				
			}
		}		
	}

	function setupPalette() {
		var items = $('.palette_item');
		
		items.each(function() {
			paletteItems[this.id] = this;
			this.setAttribute('kind', 'paletteItem');
			this.setAttribute('itemKind', this.id);
		});
		
		items.css({
			 border: '1px #ccc solid',
			 padding: '3px'
		});
		
		var handler = function() {
			that.setTool(this);
		}
		
		items.bind('mousedown', handler);
	}

	this.setTool = function(tool) {
		console.info("setting tool to ", tool);
		
		tool.style.border='1px red solid';
		
		if (currentTool) {
			currentTool.style.border='1px #ccc solid';
		}
		
		currentTool = tool;
	};

	this.getItems = function() {
		var result = "";
		for (var x = 0; x < height; x++) {
			for (var y = 0; y < width; y++) {
				if (cells[x][y].item.kind) {
					var cell = cells[x][y];
					result += x + ";" + y + ";" + cell.item.kind + ";" + cell.item.id + "#";
				}
			}
		}
		return result;
	};

	this.onClick = function(cell) {

		var x = cell.getAttribute('x');
		var y = cell.getAttribute('y')
		
		if (currentTool) {
			
			var kind = currentTool.getAttribute("itemKind");
			
			if (!isCellProtected(cell)) {
				if (cell.firstChild && cell.firstChild.firstChild && cell.firstChild.firstChild.getAttribute('className') == kind) {
					console.debug('removing element of kind ', kind);
					cells[x][y].item = {};
				}
				else {
					console.debug('adding new element of tool ', currentTool);
					that.addElement( x, y, { kind: kind, image: kind, id: 0, className: kind } );
				}
			}
			else {
				console.info('cannot edit element on this cell');
			}
			refreshCell( x, y );
		}
	};
	
	function isCellProtected(x, y) {
		
		var cell = getCell(x, y);
		
		if (cell.item) {
			if (cell.item.kind == "parcel" && cell.item.leaser) {
				//return true;
			}
		}
		
		return false;
	}
	
	this.onMouseOver = function(cell) {
	};
	
	this.onDraw = function(cell) {
		
	};
}

var editor = new Editor();