// group
//  .div
//  .zoomdiv
//  .overviewdiv

/* Function to allow easy switching off of logs */
/* MAYBE NOT A GREAT IDEA THOUGH */
function log () {
	// FIREBUG CONSOLE
	try {
		console.log.apply(this, arguments);
	} catch (e) {}
	// FOR NO FIREBUG...
	/*
	var logdiv = document.getElementById('debuglog'); 
	if (logdiv == null) {
		logdiv = document.createElement('div');
		logdiv.id = 'debuglog';
		logdiv.style.position="absolute";
		logdiv.style.width="100%";
		logdiv.style.height= "50px";
		logdiv.style.background="#88FF88";
		logdiv.style.bottom = "0px";
		logdiv.style.overflow = "auto";
		logdiv.style.fontFamily = "Courier, Fixed";
		logdiv.style.fontSize = "10px";
		document.body.appendChild(logdiv);
	}
	var newline = "";
	for (var i=0; i<arguments.length; i++) {
		newline += arguments[i];
		if (i+1 < arguments.length) newline += ", ";
	}
	logdiv.innerHTML = newline + "<br />\n" + logdiv.innerHTML;
	*/
}

/* SETTABLE */
var MARGIN = 150; // pixels added around edges of dragliner / zoom
var SIZES = [[60, 5]];
var ZOOM = 10; // SIZES[1][0] / SIZES[0][0];
var OVERVIEWREDUCE = 5; /* factor to reduce sizes[0] to the overview */

/* CALCULATED FROM ABOVE */
SIZES.push([SIZES[0][0] * ZOOM, SIZES[0][1] * ZOOM]);
var ZMARGIN = ZOOM * MARGIN;
var imagesize = SIZES[0][0];
var bordersize = SIZES[0][1];
var cellsize = imagesize + bordersize;
var zimagesize = imagesize * ZOOM;
var zbordersize = bordersize * ZOOM;
var zcellsize = cellsize * ZOOM;

var zoomed = false;
var imgidstoload = new Array();
var groups;
var imageDataById = {};

function onLoadImageDone(e) {
	// console.log("onLoadImageDone");
	if (imgidstoload.length > 0) {
		checkForImagesToLoad();
	} else {
		// log("done loading images");
	}
}


function isimageonscreen (id) {
	if (!zoomed) return false;
	var z = $('zoom');
	var ox = -parseInt(z.style.left);
	var oy = -parseInt(z.style.top);
	var ww = getWindowWidth();
	var wh = getWindowHeight();
	
// 	console.log("origin: ", ox+","+oy+":"+ww+"x"+wh);

	var imgdata = imageDataById[id];
	var zelt = imgdata.zoomdiv
// 	console.log("zoomdiv", zelt, zelt.parentNode);

	var zx = parseInt(zelt.parentNode.style.left) + parseInt(zelt.style.left);
	var zy = parseInt(zelt.parentNode.style.top) + parseInt(zelt.style.top);
	var zw = zimagesize;
	var zh = zimagesize;

// 	console.log("image: ", zx+","+zy+":"+zw+"x"+zh);

	return (((zx + zw) > ox) && ((zy + zh) > oy) &&
	        (zx < (ox + ww)) && (zy < (oy + wh)));
}

function checkForImagesToLoad () {
	if (!zoomed) return;
	if (imgidstoload.length == 0) return;
	// console.log("checkForImagesToLoad", imgidstoload.length);

	for (var i=0; i<imgidstoload.length; i++) {
		var imgid = imgidstoload[i];
		if (isimageonscreen(imgid)) {
			// remove item from list
			// imgidstoload.splice(i, 1);

			// load it
			loadImage(imgid);
			return;
		}
	}
	// not now? try again later
	window.setTimeout(checkForImagesToLoad, 1000);
}

// window.setInterval(checkForImagesToLoad, 1000);

function removeItem (list, thing) {
	for (var i=0; i<list.length; i++) {
		if (list[i] == thing) {
			list.splice(i, 1);
			return true;
		}
	}
	return false;
}

function loadImage (id) {
/*	console.log("loadImage", id);*/
	var idata = imageDataById[id];
	var zdiv = idata.zoomdiv;
	var group = idata.group;
	var imgsrc = idata.imgsrc;
	zdiv.className = "image";
	idata.zoomimg.onload = onLoadImageDone;
	idata.zoomimg.src = "imagesizer.php?w="+zimagesize+"&h="+zimagesize+"&src=" + group.path + "/" + imgsrc;
	removeItem(imgidstoload, id);
	// data.zoomimg.border = "0";
}

function setZoomed (z, imgid) {
	if (zoomed == z) return;
	zoomed = z;

	$('zoomout').style.visibility = zoomed ? 'visible' : 'hidden';

	var d = $('dragliner');
	var z = $('zoom');

	var ww = getWindowWidth();
	var wh = getWindowHeight();

	if (scrollToIntervalID) {
		window.clearInterval(scrollToIntervalID);
		scrollToIntervalID = undefined;
	}

	if (zoomed) {
		// going unzoomed to zoomed
		// set zoom layer position based on dragliner
		// use zoomElement

		var d = $('dragliner');
		var ox = -parseInt(d.style.left);
		var oy = -parseInt(d.style.top);

		var zelt = $(imgid);
		var zx = parseInt(zelt.parentNode.style.left) + parseInt(zelt.style.left);
		zx += (cellsize/2);
		var zy = parseInt(zelt.parentNode.style.top) + parseInt(zelt.style.top);
		zy += (cellsize/2);

//      SET POSITION SUCH THAT it stays where it was on screen
// 		var nox = (zx * ZOOM) + (ox - zx);
// 		var noy = (zy * ZOOM) + (oy - zy);

//		SET POSITION SO THAT IT BECOMES CENTERED ON THE SCREEN
		var nox = (zx * ZOOM) - (ww/2);
		var noy = (zy * ZOOM) - (wh/2);
 
		setScrollOrigin(Math.round(nox), Math.round(noy));
		d.style.visibility = "hidden";
		z.style.visibility = "visible";
		
		// IMAGE LOADING
		if (imgid) {
			var idata = imageDataById[imgid];
			if (idata.zoomdiv.className == "image_notloaded") {
				loadImage(imgid);
			} else {
				checkForImagesToLoad();
			}
		}

	} else {
		var zx = -parseInt(z.style.left);
		var zy = -parseInt(z.style.top);
		zx += (ww/2);
		zy += (wh/2);
		zx /= ZOOM;
		zy /= ZOOM;
		zx -= (ww/2);
		zy -= (wh/2);

		setScrollOrigin(Math.round(zx), Math.round(zy));

		$('dragliner').style.visibility = "visible";
		$('zoom').style.visibility = "hidden";
	}	
}

function imageOnMouseDown (evt) {
	var elt = Event.element(evt);
	var div = Event.findElement(evt, "div");
	imageClickPosX = Event.pointerX(evt);
	imageClickPosY = Event.pointerY(evt);
}

function imageOnClick (evt) {
	var elt = Event.element(evt);
	var div = Event.findElement(evt, "div");
	// log("imageOnClick", elt, div, div.id);
	var dx = Math.abs(Event.pointerX(evt) - imageClickPosX);
	var dy = Math.abs(Event.pointerY(evt) - imageClickPosY);
	// DO CLICK WHEN NOT DRAGGED
	if ((dx < 2) && (dy < 2)) {
		doImageClick(div.id);
	}
}

var imageClickPosX = undefined;
var imageClickPosY = undefined;

function zoomImageOnMouseDown (evt) {
	var elt = Event.element(evt);
	var div = Event.findElement(evt, "div");
	// log("imageOnClick", elt, div, div.id);
	// doImageClick(div.id.substr(1));
	
	imageClickPosX = Event.pointerX(evt);
	imageClickPosY = Event.pointerY(evt);
}

function zoomImageOnClick (evt) {
	var dx = Math.abs(Event.pointerX(evt) - imageClickPosX);
	var dy = Math.abs(Event.pointerY(evt) - imageClickPosY);
	// DO CLICK WHEN NOT DRAGGED
	if ((dx < 2) && (dy < 2)) {
		var elt = Event.element(evt);
		var div = Event.findElement(evt, "div");
		// log("imageOnClick", elt, div, div.id);
		doImageClick(div.id.substr(1));
	}
}

function doImageClick(id) {
	// log("doImageClick", id);
	if (!zoomed) {
		// imagesize = SIZES[0][0];
		// bordersize = SIZES[0][1];
		// cellsize = imagesize + bordersize;
		// console.log("doImageClick", id, zelt);
		setZoomed(true, id);
	} else {
		// center on image
		var zelt = imageDataById[id].zoomdiv;
		var zx = parseInt(zelt.parentNode.style.left) + parseInt(zelt.style.left);
		zx += (zimagesize/2);
		var zy = parseInt(zelt.parentNode.style.top) + parseInt(zelt.style.top);
		zy += (zimagesize/2);
		zx -= (getWindowWidth()/2);
		zy -= (getWindowHeight()/2);
		// console.log("zx, zy", zx, zy);
		scrollTo(Math.round(zx), Math.round(zy));
		// setZoomed(false);
	}
}

function linerOnDrag () {
	if (scrollToIntervalID) {
		window.clearInterval(scrollToIntervalID);
		scrollToIntervalID = undefined;
	}
	updateCurrentFocus();
}

function zoomOnDrag () {
	if (scrollToIntervalID) {
		window.clearInterval(scrollToIntervalID);
		scrollToIntervalID = undefined;
	}
	updateCurrentFocus();
}

function init() {
	new Draggable("dragliner", { starteffect: undefined, onDrag: linerOnDrag, endeffect: undefined } );
	new Draggable("zoom", { starteffect: undefined, onDrag: zoomOnDrag, endeffect: undefined } );
	new Ajax.Request('getlayout.php', {
		onFailure: function() {
			alert('Something went wrong...')
	}});
}

function pathToGroupName (path) {
	// strip "f/"
	path = path.substr(2);
	return path.replace("/", "&gt;<br /> ");
}

var scrollToIntervalID = undefined;
var scrollToX = 0, scrollToY = 0;

function setScrollOrigin (x, y) {
	if (!zoomed) {
		var d = $('dragliner');
		d.style.left = -x + "px";
		d.style.top = -y + "px";
		updateCurrentFocus();
		// set legend position
		/*
		var l = $('overviewlegend');
		l.setStyle({left: Math.round(x / OVERVIEWREDUCE),
					top: Math.round(y / OVERVIEWREDUCE)});
		*/
	} else {
		var z = $('zoom');
		z.style.left = -x + "px";
		z.style.top = -y + "px";
		updateCurrentFocus();
	}
}

function divhaspoint (d, x, y) {
	var dx = parseInt(d.style.left);
	var dy = parseInt(d.style.top);
	var dw = parseInt(d.style.width);
	var dh = parseInt(d.style.height);
	return ((x >= dx) && (x < (dx + dw)) && (y >= dy) && (y < (dy + dh)));
}

var curFocusGroup = null;
function setFocusGroup (fg) {
	if (curFocusGroup == fg) return;
	if (curFocusGroup != null) {
		// cleanup
		// curFocusGroup.div.style.background = null;
		curFocusGroup.overviewdiv.style.background = "#444";
	}
	curFocusGroup = fg;
	// log("focusGroup", fg);
	if (curFocusGroup != null) {
		// setup
		// console.log("setFocusGroup: " + fg.name + " / " + fg);
		// curFocusGroup.div.style.background = "blue";
		curFocusGroup.overviewdiv.style.background = "#888";
	}
}

function updateCurrentFocus () {
	// 1. calculate the current center point of the dragliner
	var d = zoomed ? $('zoom') : $('dragliner');
	var dx = -parseInt(d.style.left);
	var dy = -parseInt(d.style.top);
	var ww = getWindowWidth();
	var wh = getWindowHeight();
	var cx = Math.round(dx + (ww/2));
	var cy = Math.round(dy + (wh/2));
	// console.log("center pos: " + cx + "," + cy);
	var focusgroup = null;
	for (var i=0; i<groups.length; i++) {
		var g = groups[i];
		if (divhaspoint(zoomed ? g.zoomdiv : g.div, cx, cy)) {
			focusgroup = g;
			break;
		}
	}
	setFocusGroup(focusgroup);
}

/*
function updateLegendPos () {
	// set legend position
	var d = $('dragliner');
	var x = -parseInt(d.style.left);
	var y = -parseInt(d.style.top);
	var l = $('overviewlegend');
	l.setStyle({left: Math.round(x / OVERVIEWREDUCE),
				top: Math.round(y / OVERVIEWREDUCE)});

}
*/

function scrollToInterval () {
	// console.log("scrollToInterval");
	var d = zoomed ? $('zoom') : $('dragliner');
	// console.log("d:", d);
	// console.log("d.style:", d.style);
	// console.log("d.style.left:", d.style.left);
	var curx = -parseInt(d.style.left);
	var cury = -parseInt(d.style.top);
	var dx = (scrollToX - curx);
	var dy = (scrollToY - cury);
	// console.log("scrollToInterval ", curx);
	// console.log("scrollToInterval dx, dy: ", dx +","+dy);
	if (Math.abs(dx) > 5 || Math.abs(dy) > 5) {
		var divx = 15; // Math.max(1, Math.abs(dx)/20);
		var stepx = (dx / divx);
		if (stepx != 0 && Math.abs(stepx) < 1) stepx = (dx < 0) ? -1 : 1;

		var divy = 15; // Math.max(1, Math.abs(dy)/20);
		var stepy = (dy / divy);
		if (stepy != 0 && Math.abs(stepy) < 1) stepy = (dy < 0) ? -1 : 1;
		setScrollOrigin(Math.round(curx + stepx), Math.round(cury + stepy));
	} else {
		setScrollOrigin(scrollToX, scrollToY);
		window.clearInterval(scrollToIntervalID);
		scrollToIntervalID = undefined;
	}
}

function scrollTo (x, y) {
	// console.log("myScrollTo", x +", "+y);
	scrollToX = x - 40;
	scrollToY = y - 20;
	if (scrollToIntervalID == undefined) {
		scrollToIntervalID = window.setInterval(scrollToInterval, 25);
	}
}

function groupForPath (path) {
	for (var g=0; g<groups.length; g++) {
		if (groups[g].path == path) return groups[g];
	}
}

function doGroupIconClick(grouppath) {
	// console.log("groupIconClick", grouppath);
	setZoomed(false);

	var g = groupForPath(grouppath);
	var gx = parseInt(g.div.style.left);
	var gy = parseInt(g.div.style.top);
	var gw = parseInt(g.div.style.width);
	var gh = parseInt(g.div.style.height);

	var sw = getWindowWidth();
	var sh = getWindowHeight();

	// center group horizontally on screen
	var newscrollleft = Math.round(gx + ((gw - sw)/2));
	// var newscrolltop = Math.round(gy + ((gh - sh)/2));
	// center group vertically -- but make sure top is visible
	// ie no more than the (gy - some border value)
	var newscrolltop = Math.min(gy - 20, Math.round(gy + ((gh - sh)/2)));
	scrollTo(newscrollleft, newscrolltop);
}

var groupIconCount = 0;
function groupIconOnClick (evt) {
	var div = Event.findElement(evt, "div");
	log("groupIconOnClick", div, div.grouppath);
	doGroupIconClick(div.grouppath);
}

function createGroupOverview (group) {
	// console.log("createGroupOverview", group.path);
	var d = document.createElement("div");
	d.className = "groupicon";
	d.grouppath = group.path;
	d.id = "groupicon" + (++groupIconCount);
	var dp = document.createElement("p");
	// var da = document.createElement("a");
	// da.setAttribute("href", "#");
	// da.setAttribute("onclick", "doGroupIconClick('" + group.path + "'); return false");
	// da.innerHTML = pathToGroupName(group.path);
	dp.innerHTML = pathToGroupName(group.path);
	// dp.appendChild(da);
	d.appendChild(dp);


	// da.parentNode.innerHTML = da.parentNode.innerHTML;

	var rimagesize = SIZES[0][0] / OVERVIEWREDUCE;
	var rbordersize = SIZES[0][1] / OVERVIEWREDUCE;
	var rcellsize = rimagesize + rbordersize;

	d.style.left = ((group.col-1) * rcellsize) + "px";
	d.style.top = ((group.row-1) * rcellsize) + "px";
	d.style.width = (group.cols * rcellsize) + "px";
	d.style.height = (group.rows * rcellsize) + "px";

	$('overview').appendChild(d);
	Event.observe(d.id, "click", groupIconOnClick);
	group.overviewdiv = d;
}
/*
function createOverviewLegend () {

	var totalw = parseInt($('dragliner').style.width);
	var totalh = parseInt($('dragliner').style.height);

	var overvieww = parseInt($('overview').style.width);
	var overviewh = parseInt($('overview').style.height);

	var screenw = getWindowWidth();
	var screenh = getWindowHeight();

	var legendw = Math.round((screenw / totalw) * overvieww);
	var legendh = Math.round((screenh / totalh) * overviewh);

	var d = document.createElement("div");
	d = Element.extend(d);
	d.setAttribute("id", "overviewlegend");
	d.style.width = legendw + "px";
	d.style.height = legendh + "px";
	d.setStyle({opacity : .4});
	$('overview').appendChild(d);
}
*/

function dolayout(g) {
	groups = g;
	var totalcols = 0;
	var totalrows = 0;
	var imgid = 1;

	for (var g=0; g<groups.length; g++) {
		var group = groups[g];
		// console.log("group", group.name);
		var groupdiv = document.createElement("div");
// 		imagesize = SIZES[0][0];
// 		bordersize = SIZES[0][1];
// 		cellsize = imagesize + bordersize;

		group.div = groupdiv;
		groupdiv.obj = group;
		groupdiv.className = "group";
		groupdiv.style.left = MARGIN + ((group.col-1) * cellsize) + "px";
		groupdiv.style.top = MARGIN + ((group.row-1) * cellsize) + "px";
		groupdiv.style.width = (group.cols * cellsize)  + "px";
		groupdiv.style.height = (group.rows * cellsize) + "px";

		totalcols = Math.max(totalcols, group.col + group.cols - 1);
		totalrows = Math.max(totalrows, group.row + group.rows - 1);

		$('dragliner').appendChild(groupdiv);

		// CREATE GROUP OVERVIEW PALETTE
		createGroupOverview(group);

		// ZOOMED GROUP
		var zgroupdiv = document.createElement("div");
// 		var zimagesize = imagesize * ZOOM; // SIZES[1][0];
// 		var zbordersize = bordersize * ZOOM; // SIZES[1][1];
// 		var zcellsize = cellsize * ZOOM; // zimagesize + zbordersize;

		group.zoomdiv = zgroupdiv;
		zgroupdiv.obj = group;
		zgroupdiv.className = "group";
		zgroupdiv.style.left = ZMARGIN + ((group.col-1) * zcellsize) + "px";
		zgroupdiv.style.top = ZMARGIN + ((group.row-1) * zcellsize) + "px";
		zgroupdiv.style.width = (group.cols * zcellsize) + "px";
		zgroupdiv.style.height = (group.rows * zcellsize) + "px";
		$('zoom').appendChild(zgroupdiv);

		// PLACE IMAGES
		var c=0;
		var r=0;
		// console.log("group.images.length", group.images.length);

		for (var i=0; i<group.images.length; i++) {
			var image = group.images[i];

			var idiv = document.createElement("div");
			idiv.className = "image";
			idiv.id = "img"+imgid;

			//var a = document.createElement("a");
			// a.setAttribute("href", "#");
			// a.setAttribute("onclick", "doImageClick('"+idiv.id+"'); return false");
			
			var img = document.createElement("img");
			img.setAttribute("alt", image);
			// a.setAttribute("title", image);
			img.alt = image;
			img.src = "imagesizer.php?w="+imagesize+"&h="+imagesize+"&src=" + group.path + "/" + image;
			var GROUPPAD = 0;
			idiv.style.left = GROUPPAD + (c*cellsize)+"px";
			idiv.style.top = GROUPPAD + (r*cellsize)+"px";
			idiv.style.width = (cellsize-bordersize)+"px";
			idiv.style.height = (cellsize-bordersize)+"px";

/*			idiv.appendChild(a);
			a.appendChild(img);*/
			idiv.appendChild(img);
			// a.appendChild(img);
			groupdiv.appendChild(idiv);

			Event.observe(idiv.id, "mousedown", imageOnMouseDown);
			Event.observe(idiv.id, "click", imageOnClick);

			// wacky IE hack to re-assert the onclick handler in particular
			// a.parentNode.innerHTML = a.parentNode.innerHTML;

			var zidiv = document.createElement("div");
			zidiv.className = "image_notloaded";
			zidiv.id = "zimg"+imgid;
// 			var za = document.createElement("a");
// 			za.setAttribute("href", "#");
// 			za.setAttribute("onclick", "doImageClick('"+idiv.id+"'); return false");

			zidiv.style.left = (GROUPPAD*ZOOM) + (c*zcellsize)+"px";
			zidiv.style.top = (GROUPPAD*ZOOM) + (r*zcellsize)+"px";
			zidiv.style.width = (zcellsize-zbordersize)+"px";
			zidiv.style.height = (zcellsize-zbordersize)+"px";
			// zidiv.appendChild(za);
			var zimg = document.createElement("img");
			zidiv.appendChild(zimg);
			zgroupdiv.appendChild(zidiv);

			Event.observe(zidiv.id, "click", zoomImageOnClick);
			Event.observe(zidiv.id, "mousedown", zoomImageOnMouseDown);
			
			// za = zidiv.firstChild;
			// za.appendChild(zimg);

			// create Image data object to record refs
			var imgobj = {};
			imgobj.group = group;
			imgobj.id = idiv.id;
			imgobj.div = idiv;
			imgobj.zoomdiv = zidiv;
			imgobj.zoomimg = zimg;
			imgobj.imgsrc = image;
			imageDataById[imgobj.id] = imgobj;

			imgidstoload.push(idiv.id);

			imgid += 1;
			if (++c >= group.cols) { c = 0; r += 1; }
		}

	}
	// console.log("cols,rows:", totalcols + "," + totalrows);
	// resize stuff
	$('dragliner').style.width = (MARGIN*2) + (totalcols * cellsize) + "px";
	$('dragliner').style.height = (MARGIN*2) + (totalrows * cellsize) + "px";
// 	$('dragliner').style.left = 20 + "px";
// 	$('dragliner').style.top = 20 + "px";

	$('zoom').style.width = (totalcols * zcellsize) + "px";
	$('zoom').style.height = (totalrows * zcellsize) + "px";
// 	$('zoom').style.left = 20 + "px";
// 	$('zoom').style.top = 20 + "px";

	$('overview').style.width = (totalcols * (cellsize / OVERVIEWREDUCE)) + "px";
	$('overview').style.height = (totalrows * (cellsize / OVERVIEWREDUCE)) + "px";	
	$('overlay').style.width = (totalcols * (cellsize / OVERVIEWREDUCE)) + 40 + "px";
	$('overlay').style.height = (totalrows * (cellsize / OVERVIEWREDUCE)) + 30 + "px";	

	$('title').style.width = $('overview').style.width;
	// $('zoomout').style.right = "0px";

	// createOverviewLegend();
	// LAST THING
	// var rg = Math.floor(Math.random() * groups.length);
	// doGroupIconClick(groups[0].path); 
	// setScrollOrigin(0, 100);
}

function getWindowWidth() {
	if (window.innerWidth!=window.undefined) return window.innerWidth;
	if (document.compatMode=='CSS1Compat') return document.documentElement.clientWidth;
	if (document.body) return document.body.clientWidth;
	return window.undefined;
}

function getWindowHeight() {
	if (window.innerHeight!=window.undefined) return window.innerHeight;
	if (document.compatMode=='CSS1Compat') return document.documentElement.clientHeight;
	if (document.body) return document.body.clientHeight;
	return window.undefined;
}

