/* *******
Parts of this code
    Copyright (c) 2005 Michal Migurski <mike-gsv@teczno.com>
******* */

function getEvent(event){
	if(!event) {
		return window.event;
	}else{ return event;}
}

function localizeCoordinates(elem, client){
	var local = {'x': client.x, 'y': client.y};
	for(var node = elem; node; node = node.offsetParent) {
		local.x -= node.offsetLeft;
		local.y -= node.offsetTop;
	}
	return local;
}

function surfaceMouseMove(event){
	var ev = getEvent(event);
	var relTarg;
	var target;
	target = ev.target;
		var mouse;
		if (target === this){
			mouse = localizeCoordinates(this, {'x': ev.clientX, 'y': ev.clientY});
			//displayStatus('SURFACE (x:'+ mouse.x + ', y:' + mouse.y + ')');
		}
}

function prepareViewer(mapViewer, tileDir, tileSize){
	for(var child = mapViewer.firstChild; child; child = child.nextSibling) {
		if(child.className === 'surface') {
			mapViewer.activeSurface = child;
			child.id = 'surface';
			child.mapViewer = mapViewer;
			child.onmousemove = surfaceMouseMove;
		} else if(child.className === 'well') {
			mapViewer.tileWell = child;
			child.id = 'tileWell';
			child.mapViewer = mapViewer;
		} 
	}
    
	//var mapData =  document.body.mapData;
	var initScale = mapData.initial.scale;
	var imgWidth = mapData.scales[initScale].width;
	var imgHeight = mapData.scales[initScale].height;

	var viewerWidth = mapViewer.clientWidth;
	var viewerHeight = mapViewer.clientHeight;
	mapViewer.map = { 'width': imgWidth, 'height': imgHeight, 'center': {'x': mapData.initial.center.x, 'y': mapData.initial.center.y,
				'col': 0, 'row': 0, 'world': {'x': 0, 'y': 0}, 'tile': {'x': 0, 'y': 0}}};
	var map = mapViewer.map;
	mViewer = mapViewer;
	mapViewer.dimensions = {
		// width and height of the viewer in pixels
		'width': viewerWidth, 'height': viewerHeight,
		// location and height of each tile; they're always square
		'tileDir': tileDir, 'tileSize': tileSize,
		'cols': Math.ceil(viewerWidth / tileSize) %  2 === 0 ? Math.ceil(viewerWidth / tileSize) + 1: Math.ceil(viewerWidth / tileSize) + 2,
		'rows': Math.ceil(viewerHeight / tileSize) % 2 === 0 ? Math.ceil(viewerHeight / tileSize) + 1: Math.ceil(viewerHeight / tileSize) + 2,
		'scale': mapData.initial.scale,
		 //position of upper left corner of upper left tile relative to upper left corner of viewer.
		 //usually negative. when the map is panned or resized, it is adjusted negative back out of the viewer.	
		'x': 0,
		'y': 0
	};
	mapViewer.start = {'x': 0, 'y': 0}; // this is reset each time that the mouse is pressed anew
	mapViewer.pressed = false;
	var dim = mapViewer.dimensions;
	map.center.col =  Math.floor(map.center.x/dim.tileSize);
	map.center.row =  Math.floor(map.center.y/dim.tileSize);
	map.center.tile.x = map.center.x - map.center.col * dim.tileSize;
	map.center.tile.y = map.center.y - map.center.row * dim.tileSize;
	dim.x = Math.floor(dim.width / 2) - (Math.floor(dim.cols / 2) * dim.tileSize + map.center.tile.x);
	dim.y = Math.floor(dim.height / 2) - (Math.floor(dim.rows / 2) * dim.tileSize + map.center.tile.y);

	if(!document.body.mapViewer) {
		document.body.mapViewer = mapViewer;
		//mapViewer.activeSurface.onmouseover = cursorChange;
		mapViewer.activeSurface.onmousedown = pressViewer;
		mapViewer.activeSurface.onmouseup = releaseViewer;
		mapViewer.activeSurface.ondblclick =  addUserLandmark;
		//mapViewer.activeSurface.onmouseover = surfaceMouseOver;
		document.body.sitesData = [];
		//sData = document.body.sitesData;
		//sData = document.body.sitesData;
		document.body.siteLookup = [];
		document.body.selectedSites = [];
		document.body.siteClips = [];
		var ul = document.createElement('ul');
		ul.id = 'surfaceUL';
		ul.style.zIndex = highestFloor + 2;
		ul.style.visibility = 'hidden';
		ul.onmouseout = ulMouseOut;
		document.body.mapViewer.activeSurface.appendChild(ul);
		ul = document.createElement('ul');
		ul.id = 'selectionList';
		ul.className = 'selectionUL';
		ul.style.marginBottom = '3em';
		document.getElementById('selection-list').appendChild(ul);
		ul = document.createElement('ul');
		ul.id = 'searchResults';
		ul.className = 'searchUL';
		ul.style.marginBottom = '3em';
		//ul.style.overflow = 'hidden';
		document.getElementById('search-results').appendChild(ul);
	}
	var thumb = document.getElementById('thumb');
	thumb.style.top = ((dim.scale + 1) * 30 - 4)+'px';
	prepareTiles(mapViewer);
	if (sData.length > 0){
		recreateSites();
	}
	if (sid){
		labelSitesHere({'x': Math.round(dim.width / 2), 'y': Math.round(dim.height / 2)});
	}
}

function prepareTiles(mapViewer){
	var tileWell = mapViewer.tileWell;
	var dim = mapViewer.dimensions;
	mapViewer.style.width = '100%';
	mapViewer.style.height = '100%';
	tileWell.style.overflow = 'hidden';
	mapViewer.style.overflow = 'hidden';
	mapViewer.tiles = [];
 	for(var c = 0; c < dim.cols; c++) {
		var tileCol = [];
		for(var r = 0; r < dim.rows; r++) {
			var tile = {'c': c, 'r': r, 'img': document.createElement('img'), 'mapViewer': mapViewer};
			tile.img.className = 'tile';
			tile.img.style.width = dim.tileSize+'px';
			tile.img.style.height = dim.tileSize+'px';
			tileWell.appendChild(tile.img);
			tileCol.push(tile);
		}
		mapViewer.tiles.push(tileCol);
	}
	positionTiles(mapViewer);
}

function positionTiles(mapViewer){
	var tiles = mapViewer.tiles;
	var dim = mapViewer.dimensions;
	var map = mapViewer.map;
	//var mapData =  document.body.mapData;
	var mapTileCols = Math.ceil(mapData.scales[dim.scale].width / dim.tileSize);
	var mapTileRows = Math.ceil(mapData.scales[dim.scale].height / dim.tileSize);
	var mapCol;
 	var mapRow;
	for(var c = 0; c < dim.cols; c++) {
		for(var r = 0; r < dim.rows; r++) {
			var tile = tiles[c][r];
			tile.x = (tile.c * dim.tileSize) + dim.x;
			tile.y = (tile.r * dim.tileSize) + dim.y;
			tile.img.style.top = tile.y+'px';
			tile.img.style.left = tile.x+'px';
			mapCol = (map.center.col - Math.floor(dim.cols / 2)) +  c;
			mapRow = (map.center.row - Math.floor(dim.rows / 2)) +  r;
			if (mapRow >= 0 && mapRow < mapTileRows && mapCol >= 0 && mapCol < mapTileCols){
				if (tileExists(mapData.scales[dim.scale].tileMap[0], dim.scale, mapRow, mapCol)){
					tile.img.src = dim.tileDir + '/S' + dim.scale + '/S' + dim.scale + '-R' + mapRow + '-C' + mapCol + '.gif';
				}else{
					tile.img.src = dim.tileDir + '/blank.gif';
				}
			}
		}
	}
/* /   
    displayStatus('map.center.x: ' + map.center.x + ' map.center.y: ' + map.center.y +
     '<br>dim.x: ' + dim.x + ' dim.y: ' + dim.y + '<br>map.center.col: ' + map.center.col + ' map.center.row: ' + 
     map.center.row + '<br>map.center.tile.x: ' + map.center.tile.x + ' map.center.tile.y: ' + map.center.tile.y +
     '<br>dim.width: ' + dim.width + ' dim.height: ' + dim.height);
			displayInViewer(boxes[i]);

*/
			//if (!mapViewer.pressed){ flushSitesDisplay();displaySites();}
}

function moveViewer(event){
	var mapViewer = this.mapViewer;
	if (mapViewer.pressed){
		var ev = getEvent(event);
		var mouse = localizeCoordinates(mapViewer, {'x': ev.clientX, 'y': ev.clientY});
		var dim = mapViewer.dimensions;
		var map = mapViewer.map;
		var start = mapViewer.start;
		var offset = adjustBoundaryOverflow(mapViewer, mouse);
		mapViewer.tileWell.style.cursor = mapViewer.activeSurface.style.cursor = 'move';
		map.center.col =  Math.floor((map.center.x - offset.x)/dim.tileSize);
		map.center.row =  Math.floor((map.center.y - offset.y)/dim.tileSize);
		map.center.tile.x = map.center.x - offset.x - map.center.col * dim.tileSize;
		map.center.tile.y = map.center.y - offset.y - map.center.row * dim.tileSize; 
		dim.x = Math.floor(dim.width / 2) - (Math.floor(dim.cols/2) * dim.tileSize + map.center.tile.x);
		dim.y = Math.floor(dim.height / 2) - (Math.floor(dim.rows/2) * dim.tileSize + map.center.tile.y);
		positionTiles(mapViewer);
	}
}

function pressViewer(event){
	var mapViewer = this.mapViewer;
	var dim = mapViewer.dimensions;
	var ev = getEvent(event);
	var mouse;
	/*
	var target = ev.target;
	if (target){
		if (target !== this){
			return;
		}
	}
	*/
	mouse = localizeCoordinates(mapViewer, {'x': ev.clientX, 'y': ev.clientY});
	mapViewer.pressed = true;
	hideSitesDisplay();
	mapViewer.tileWell.style.cursor = mapViewer.activeSurface.style.cursor = 'move';
	mapViewer.start = {'x': mouse.x, 'y': mouse.y};
	this.onmousemove = moveViewer;
}

function releaseViewer(event){
	var ev = getEvent(event);
	var mapViewer = document.body.mapViewer;
	var mouse = localizeCoordinates(mapViewer, {'x': ev.clientX, 'y': ev.clientY});
	var dim = mapViewer.dimensions;
	mapViewer.pressed = false;
	mapViewer.tileWell.style.cursor = mapViewer.activeSurface.style.cursor = 'default';
	mapViewer.map.center.x -= (mouse.x - mapViewer.start.x);
	mapViewer.map.center.y -= (mouse.y - mapViewer.start.y);
	mapViewer.start = {'x': mouse.x, 'y': mouse.y};
	positionTiles(mapViewer, {'x': mouse.x, 'y': mouse.y});
	displaySites();
	this.onmousemove = surfaceMouseMove;
}

function displayStatus(message){
	var status = document.getElementById('display-status');
	status.innerHTML = message;
}


function dumpInfo(mapViewer){
	var dim = mapViewer.dimensions;
	var tiles = mapViewer.tiles;
	var statusTextLines = ['mapViewer '+(i + 1), 'current window position: '+dim.x+','+dim.y+'.', '----'];
	for(var c = 0; c < tiles.length; c += 1) {
		for(var r = 0; r < tiles[c].length; r += 1) {
			statusTextLines.push('map ('+c+','+r+') has tile ('+dim.scale+','+tiles[c][r].c+','+tiles[c][r].r+')');
		}
	}
 	alert(statusTextLines.join('\n'));
}

function dumpAllInfo(){
        dumpInfo(document.body.mapViewer);
}

function zoomMap(mapViewer, scale){
	//var mapData =  document.body.mapData;
	var map = mapViewer.map;
	var dim = mapViewer.dimensions;
	dim.cols = Math.ceil(dim.width / dim.tileSize) % 2 === 0 ? Math.ceil(dim.width / dim.tileSize) + 1: 
					Math.ceil(dim.width / dim.tileSize) + 2;
	dim.rows = Math.ceil(dim.height / dim.tileSize) % 2 === 0 ? Math.ceil(dim.height / dim.tileSize) + 1: 
					Math.ceil(dim.height / dim.tileSize) + 2;
	map.width = mapData.scales[scale].width;
	map.height = mapData.scales[scale].height;
	mapViewer.dimensions.scale = scale;
	if ((map.center.x + dim.width / 2) > map.width){
		map.center.x = map.width - Math.floor(dim.width / 2);
	}
	if ((map.center.x - dim.width / 2) < 0){
		map.center.x = Math.floor(dim.width / 2);
	}
	if ((map.center.y + dim.height / 2) > map.height){
		map.center.y = map.height - Math.floor(dim.height / 2);
	}
	if ((map.center.y - dim.height / 2) < 0){
		map.center.y = Math.floor(dim.height / 2);
	}
	map.center.col =  Math.floor(map.center.x / dim.tileSize);
	map.center.row =  Math.floor(map.center.y / dim.tileSize);
	map.center.tile.x = map.center.x - map.center.col * dim.tileSize;
	map.center.tile.y = map.center.y - map.center.row * dim.tileSize; 
	dim.x = Math.floor(dim.width / 2) - (Math.floor(dim.cols/2) * dim.tileSize + map.center.tile.x);
	dim.y = Math.floor(dim.height / 2) - (Math.floor(dim.rows/2) * dim.tileSize + map.center.tile.y);
	flushSitesLayerUL();
	hideSitesDisplay();
	positionTiles(mapViewer);
	displaySites();
}

function zoomOut(){
	var mapViewer = document.getElementById('map-viewport');
	var scale = mapViewer.dimensions.scale;
	if (scale < scaleMax){
		//var mapData =  document.body.mapData;
		var map = mapViewer.map;
		var thumb = document.getElementById('thumb');
		scale++;
		map.center.x = Math.ceil(map.center.x * (mapData.scales[scale].width / mapData.scales[scale - 1].width));
		map.center.y = Math.ceil(map.center.y * (mapData.scales[scale].height / mapData.scales[scale - 1].height));
		thumb.style.top = (26 + (scale * 30))+'px';
		zoomMap(mapViewer, scale);	
	}
}

function zoomIn(){
	var mapViewer = document.getElementById('map-viewport');
	var scale = mapViewer.dimensions.scale;
	if (scale > scaleMin){
		//var mapData =  document.body.mapData;
		var map = mapViewer.map;
		scale--;
		map.center.x = Math.ceil(map.center.x * (mapData.scales[scale].width / mapData.scales[scale + 1].width));
		map.center.y = Math.ceil(map.center.y * (mapData.scales[scale].height / mapData.scales[scale + 1].height));
		thumb.style.top = (26 + (scale * 30))+'px';
		zoomMap(mapViewer, scale);	
	}
}

function prepareSlider(slider){
	slider.onclick = zoomTo;
}

function zoomTo(event){
	var slider = document.getElementById('slider');
	var thumb = document.getElementById('thumb');
	var thumbNotch;
	var ev = getEvent(event);
	var mouse = localizeCoordinates(slider, {'x': ev.clientX, 'y': ev.clientY});
	if (mouse.y > 10) {   
		if (mouse.y < 30) {
			thumbNotch = 30;
		}
		else if  (mouse.y > 270) {
			thumbNotch = 270;
		}
		else {
			thumbNotch = Math.round(mouse.y/30)*30;
		}
		thumb.style.top = (thumbNotch - 4)+'px';
		var mapViewer = document.getElementById('map-viewport');
		var fromScale = mapViewer.dimensions.scale;
		//var mapData =  document.body.mapData;
		var map = mapViewer.map;
		var scale = (thumbNotch / 30) - 1;
		map.center.x = Math.ceil(map.center.x * (mapData.scales[scale].width / mapData.scales[fromScale].width));
		map.center.y = Math.ceil(map.center.y * (mapData.scales[scale].height / mapData.scales[fromScale].height));
		zoomMap(mapViewer, scale);
	}	
 }

function resizeMap(){
	var mapViewer = document.getElementById('map-viewport');
	var surface = document.getElementById('surface');
	var tileWell = document.getElementById('tileWell');
	var dim = mapViewer.dimensions;
	var map = mapViewer.map;
	var statusTextLines = [];
	statusTextLines.push('center.world.x before: '  + map.center.x  + '<br>' + ' center.world.y before: ' + map.center.y + '<br>');
	if (isIEBrowser) {
		document.getElementById('center-container').style.width = (document.body.clientWidth < 1000 ? 1000 : document.body.clientWidth) + 'px';
		document.getElementById('center-container').style.height = (document.body.clientHeight < 600 ? 519 : document.body.clientHeight - 81) + 'px';
		document.getElementById('map-area').style.width = (document.getElementById('center-container').clientWidth - 480) + 'px';
		document.getElementById('map-area').style.height = (document.getElementById('center-container').clientHeight - 37) + 'px';
		mapViewer.style.height = surface.style.height = tileWell.style.height = mapViewer.parentNode.clientHeight + 'px';
		mapViewer.style.width = surface.style.width = tileWell.style.width = mapViewer.parentNode.clientWidth + 'px';
	}
	var offset = {'x': dim.width - mapViewer.offsetWidth, 'y': dim.height - mapViewer.offsetHeight};
	map.center.x -= Math.floor(offset.x / 2);
	map.center.y -= Math.floor(offset.y / 2);
	dim.width = mapViewer.clientWidth;
	dim.height = mapViewer.clientHeight;
	adjustBoundaryOverflow(mapViewer, mapViewer.start);
	dim.cols = Math.ceil(dim.width / dim.tileSize) % 2 === 0 ? Math.ceil(dim.width / dim.tileSize) + 1: Math.ceil(dim.width / dim.tileSize) + 2;
	dim.rows = Math.ceil(dim.height / dim.tileSize) % 2 === 0 ? Math.ceil(dim.height / dim.tileSize) + 1: Math.ceil(dim.height / dim.tileSize) + 2;
	map.center.col =  Math.floor(map.center.x / dim.tileSize);
	map.center.row =  Math.floor(map.center.y / dim.tileSize);
	map.center.tile.x = map.center.x - map.center.col * dim.tileSize;
	map.center.tile.y = map.center.y - map.center.row * dim.tileSize; 
	dim.x = Math.floor(dim.width / 2) - (Math.floor(dim.cols/2) * dim.tileSize + map.center.tile.x);
	dim.y = Math.floor(dim.height / 2) - (Math.floor(dim.rows/2) * dim.tileSize + map.center.tile.y);
	prepareTiles(mapViewer);    
	displaySites();
}

function adjustBoundaryOverflow(mapViewer, mouse){
	var dim = mapViewer.dimensions;
	var map = mapViewer.map;
	var start = mapViewer.start;
	var offset = {'x': mouse.x - start.x, 'y':mouse.y - start.y};
	if (map.center.x + (dim.width / 2) - offset.x > map.width){
		map.center.x = map.width - Math.floor(dim.width / 2);
		start.x = mouse.x;
		offset.x = 0;
	}
	if (map.center.x - (dim.width / 2) - offset.x < 0){
		map.center.x = Math.floor(dim.width / 2);
		start.x = mouse.x;
		offset.x = 0;		
	}    
	if (map.center.y + (dim.height / 2) - offset.y > map.height){
		map.center.y = map.height - Math.floor(dim.height / 2);
		start.y = mouse.y;
		offset.y = 0;
	}
	if (map.center.y - (dim.height / 2) - offset.y < 0){
		map.center.y = Math.floor(dim.height / 2);
		start.y = mouse.y;
		offset.y = 0;
	}
	return {'x': mouse.x - start.x, 'y':mouse.y - start.y};
}

function flushWell(mapViewer){
	var tileWell = mapViewer.tileWell;
	while (tileWell.childNodes.length > 0) {
		tileWell.removeChild(tileWell.lastChild);
	}
}

function tileExists(tileMap, scale, row, col){
	//var tileMap = document.body.mapData.scales[scale].tileMap[0];
	//var tileMap = mapData.scales[scale].tileMap[0];
	var intBlock = tileMap[row][Math.floor(col / 32)];
	return intBlock & Math.pow(2,(col % 32));
}
