var body=null;
var backCanvas=null, backCtx=null, frontCanvas=null, frontCtx=null, middleCanvas=null, middleCtx=null;

var innavbar=null;
var navLeft, navTop, navRight;

var photoCount = 0;
var gimgs=new Array();
var imglinks=new Array();
var photos=new Array();
var zorder=new Array();

var loadedPhotos = 0;
var loadingPhotosInterval = null;

var ctxWid, ctxHei, ctxLeft, contentLeft;

var pageXplus=0, pageYplus = 0;

var mdPhoto=-1, mdX=0, mdY = 0, mdXabs, mdYabs;
var anglePointX=0, anglePointY=0, anglePointAngle = 0;

var redrawLeft, redrawRight, redrawBottom, redrawTop;

var mmX=0, mmY=0;
var mouseMoved = false;

var lastX=0, lastY=0;
var busy = false;

var tryAgainRefresh = false;
var activePhotoOrder = -1;

var cursorChangeTimer = null;

var hasBeenMoved = false;

var piH=Math.PI/2, pi = Math.PI, piD = 2*Math.PI;

var aCursor = 0; //0 - arrow; 1 - pointer; 2 - move

//Transition zu Fotoanzeige
var transStartLeft, transStartTop, transStartWidth, transStartHeight, transStartAngle, transStartScroll;
var transEndLeft, transEndTop, transEndWidth, transEndHeight;
var aTransitionStep = 0;
var transitionInterval = null;

function loader() {
	if(isIE) {
		aniFadeDown(document.getElementById("submenu"),10,null, easeInOutAni);
		return;
	}
	body=document.body;   

	backCanvas=document.createElement("canvas");
	backCanvas.style.position="absolute"; backCanvas.style.zIndex="100";
	document.getElementById("content").appendChild(backCanvas);
	backCtx = backCanvas.getContext("2d");

	middleCanvas=document.createElement("canvas");
	middleCanvas.style.position="absolute"; middleCanvas.style.zIndex="101";
	document.getElementById("content").appendChild(middleCanvas);
	middleCtx = middleCanvas.getContext("2d");

	frontCanvas=document.createElement("canvas");
	frontCanvas.style.position="absolute"; frontCanvas.style.zIndex="102";
	document.getElementById("content").appendChild(frontCanvas);
	frontCtx = frontCanvas.getContext("2d");

	var innavbar2 = document.getElementById("innavbar2");
	innavbar = document.getElementById("innavbar");

	innavbar2.style.position="relative";
	innavbar.style.position="absolute";
	innavbar.style.width="100%";
//	innavbar.style.backgroundColor="#ffffff";
	innavbar.style.backgroundImage="url('semitransp.png')";
	innavbar.style.zIndex="200";

	resize();


	// Für jedes Bild ein Photo-Objekt anlegen
	var lp = document.getElementById("loadedPhotos");
	photoCount=gimgs.length;
	photos = new Array(photoCount);
	for(var i = 0; i<photoCount;i++) {
		var img = document.createElement("img");
		img.src = gimgs[i];
		lp.appendChild(img);
		photos[i]=new Photo(img);
		zorder[i] = i;
	}
	loadingPhotosInterval = setInterval("checkPhotosLoaded();", 100);
	setInterval("checkMouseMoved();", 1000/25);

	aniFadeDown(document.getElementById("submenu"),10,null, easeInOutAni);

	addEventHandler(frontCanvas,"mousedown", md);

	addEventHandler(frontCanvas,"mousemove", mh);

	window.onresize=function(evt) {
		resize();
		redrawScene(0);
	};

}

function resize() {
	
	var nContentLeft = absLeft(document.getElementById("content"));

	if(photos.length>0) {
		for(var i = 0; i < photos.length; i++) {
			photos[i].rect.move(photos[i].rect.left+nContentLeft-contentLeft,photos[i].rect.top);
		}
	}

	contentLeft = nContentLeft;
	ctxLeft = absLeft(document.getElementById("book1"));
	ctxWid = viewWidth(document.getElementById("aroundall")) + ctxLeft;
	ctxHei = Math.max(browserClientHeight() - 51, viewHeight(document.getElementById("aroundall"))+15);
	resizeCanvas(backCanvas);
	resizeCanvas(middleCanvas);
	resizeCanvas(frontCanvas);
	pageXplus=0;//absLeft(frontCanvas);
	pageYplus=absTop(frontCanvas);
	
	navLeft = absLeft(innavbar);
	navTop = absTop(innavbar);
	navRight = navLeft + viewWidth(innavbar);

	window.onpageshow = function(evt) {
		redrawScene(0);
		document.getElementById("title").innerHTML="Photoalbum";
		document.getElementById("incontent").style.visibility="visible";
		backCanvas.style.visibility="visible";
		frontCanvas.style.visibility="visible";
	}
	
}

function resizeCanvas(cnv) {
	cnv.width=ctxWid;
	cnv.height=ctxHei;
	cnv.style.left=-ctxLeft + "px"; cnv.style.top="0px";
}

function bringToFront(photoIndex) {
	for(var i=0; i<photoCount - 1; i++) {
		if(zorder[i]==photoIndex) {
			zorder.splice(i,1);
			zorder.push(photoIndex);
			break;
		}     
	}
}

function mh(evt) {
	if(mdPhoto == -1) {
		if(cursorChangeTimer != null) { clearTimeout(cursorChangeTimer); cursorChangeTimer = null; }
		var x = evt.pageX - pageXplus;
		var y = evt.pageY - pageYplus;
		var found = false;
		for(var j = photoCount - 1; j>=0; j--) {
			var i = zorder[j];
			if(photos[i].rect != null && photos[i].rect.pointInside(x,y)) {
				found = true;
				setCursor(2);
				cursorChangeTimer = setTimeout("cursorToPointer()",500);
				break;
			}
		}
		if(!found) setCursor(0);
		if(found) {
			innavbar.style.zIndex=99;
		} else {
			var ax = evt.pageX, ay=evt.pageY;
			if(ax>=navLeft && ax<navRight && ay>=navTop && ay<navTop + viewHeight(innavbar))  {
				innavbar.style.zIndex=200;
			} else {
				innavbar.style.zIndex=99;
			}
		}
	}
}

function cursorToPointer() {
	setCursor(1);
}

function setCursor(newCursor) {
	if(newCursor!=aCursor) {
		switch(newCursor) {
			case 0: frontCanvas.style.cursor="default"; break;
			case 1: frontCanvas.style.cursor="pointer"; break;
			case 2: frontCanvas.style.cursor="move"; break;
		}
		aCursor = newCursor;
	}
}

function md(evt) {
	if(mdPhoto!=-1) {
		return; //Wenn wir in Endanimation sind, keine Verschiebung mehr zulassen.
	}
	var x = evt.pageX - pageXplus;
	var y = evt.pageY - pageYplus;
	mdXabs=x; mdYabs=y;
	mdPhoto = -1;
	for(var j = photoCount - 1; j>=0; j--) {
		var i = zorder[j];
		if(photos[i].rect != null && photos[i].rect.pointInside(x,y)) {
			//bringToFront(i);
			hasBeenMoved = false;
			activePhotoOrder = j;
			mdPhoto = i;
			photos[i].rect.setRotPoint(x,y);
			anglePointX = x;
			anglePointY = y;
			anglePointAngle = photos[mdPhoto].rect.angle;
			lastX = x;
			lastY = y;
			mdX = x - photos[i].rect.left;
			mdY = y - photos[i].rect.top;
			addEventHandler(body, "mouseup", mu);
			addEventHandler(body, "mousemove", mm);
			redrawScene(0);
			break;
		}
	}
	stopProp(evt);
	prevDef(evt);
}

function mu(evt) {
	mmX = evt.pageX - pageXplus;
	mmY = evt.pageY - pageYplus;
	checkMouseMoved();
	removeEventHandler(body, "mouseup", mu);
	removeEventHandler(body, "mousemove", mm);
	prevDef(evt);
	stopProp(evt);
	cursorChangeTimer = setTimeout("cursorToPointer()",500);

	if(!hasBeenMoved) {
		bringToFront(mdPhoto);
		activePhotoOrder=photoCount-1;
		document.getElementById("title").innerHTML="&nbsp;";
		document.getElementById("incontent").style.visibility="hidden";
		backCanvas.style.visibility="hidden";
		frontCanvas.style.visibility="hidden";
		redrawScene(2);

		transStartLeft = photos[mdPhoto].rect.left;
		transStartTop = photos[mdPhoto].rect.top;
		transStartWidth = photos[mdPhoto].rect.width;
		transStartHeight = photos[mdPhoto].rect.height;
		transStartAngle = photos[mdPhoto].rect.angle;
		transEndWidth=viewWidth(photos[mdPhoto].imgObj);
		transEndHeight=viewHeight(photos[mdPhoto].imgObj);
		var ic = document.getElementById("incontent");
		transEndLeft=absLeft(ic)+Math.round(viewWidth(document.getElementById("incontent"))/2 - transEndWidth/2);
		transEndTop=absTop(ic)-51;

		transStartScroll = Math.max(document.documentElement.scrollTop, document.body.scrollTop);

		aTransitionStep = 0;
		transitionInterval = setInterval("doTransition();", 1000/15);
	} else {
		mdPhoto = -1;
	}
}

function doTransition() {
	aTransitionStep++;
	if(aTransitionStep == 10) {
		clearInterval(transitionInterval);
	}
	var rel = aTransitionStep/10;
	rel*=rel;
	if(transStartScroll==-1) window.scrollBy(0,-7); else window.scrollTo(0,transStartScroll-transStartScroll*rel);
	photos[mdPhoto].rect.move(transStartLeft+(transEndLeft-transStartLeft)*rel,transStartTop+(transEndTop-transStartTop)*rel);
	photos[mdPhoto].rect.width = transStartWidth+(transEndWidth-transStartWidth)*rel;
	photos[mdPhoto].rect.height = transStartHeight+(transEndHeight-transStartHeight)*rel;
	photos[mdPhoto].rect.setAngle(transStartAngle+(-transStartAngle)*rel);
//	if(aTransitionStep == 7) {
//	}
	redrawScene(2);
	if(aTransitionStep == 10) {
		var a = mdPhoto
		mdPhoto = -1;
		photos[a].rect.move(transStartLeft,transStartTop);
		photos[a].rect.width = transStartWidth;
		photos[a].rect.height = transStartHeight;
		photos[a].rect.setAngle(transStartAngle);
		document.location.href=imglinks[a];
	}
}

function mm(evt) {
	setCursor(2);
	mmX = evt.pageX - pageXplus;
	mmY = evt.pageY - pageYplus;
	var dist = (mmX-mdXabs)*(mmX-mdXabs) + (mmY-mdYabs)*(mmY-mdYabs);
	if(dist>9) hasBeenMoved = true;
	mouseMoved = true;
	prevDef(evt);
	stopProp(evt);
}

function checkPhotosLoaded() {
	var loadedBefore = loadedPhotos;
	for(var i =0; i<photoCount; i++) {
		if(viewWidth(photos[i].imgObj)>80 && !photos[i].loaded) {
			loadedPhotos++;
			photos[i].wasLoaded();
		}
	}
	if(loadedPhotos > loadedBefore || tryAgainRefresh) {
		tryAgainRefresh = false;
		redrawScene(0);
	}
	if(loadedPhotos>=photoCount && !tryAgainRefresh) {
		clearInterval(loadingPhotosInterval);
	}
}



function getAngle(x1,y1,x2,y2) {
	if(x1==x2) {
		return (y2<y1?piH:-piH);
	} else {
		var dx = x2-x1; var dy=y2-y1;
		if(dy>=0) {
			if(dx>=0) {
				return Math.atan(dy/dx);
			} else {
				return pi - Math.atan(dy/-dx);
			}
		} else {
			if(dx>=0) {
				return -Math.atan(-dy/dx);
			} else {
				return -pi + Math.atan(-dy/-dx);
			}
		}
	}
}

function checkMouseMoved() {
	if(mouseMoved && !busy) {
		busy = true;
		mouseMoved = false;
		//Quadratische Distanz zu anglePoint
		var dist = (mmX-anglePointX)*(mmX-anglePointX) + (mmY-anglePointY)*(mmY-anglePointY);
		//Distanz zu letztem Punkt
		var dist2 = Math.sqrt((mmX-lastX)*(mmX-lastX) + (mmY-lastY)*(mmY-lastY));

		if(dist>5) {

			var ctrX = photos[mdPhoto].rect.left+photos[mdPhoto].rect.width/2;
			var ctrY = photos[mdPhoto].rect.top+photos[mdPhoto].rect.height/2;
			var rotX = photos[mdPhoto].rect.rotx;
			var rotY = photos[mdPhoto].rect.roty;

			var xOutiness = Math.abs((rotX-ctrX)/(photos[mdPhoto].rect.width/2));
			var yOutiness = Math.abs((rotY-ctrY)/(photos[mdPhoto].rect.height/2));
			var outiness = Math.max(xOutiness, yOutiness);
			outiness*=outiness;

			//Den Winkel zwischen Mittelpunkt und Ziehpunkt berechnen
			var turnAngle = getAngle(ctrX,ctrY,rotX,rotY);

			//Den aktuellen Punkt um den AnglePoint drehen, und zwar
			//- erst um -anglePointAngle, um zu berechnen, wo der Punkt auf einem geraden Photo wäre
			//- dann nochmal um -turnAngle, damit die Drehrichtung von der Anfassposition abhängt.
			var unrotX = rotateX(mmX,mmY,anglePointX,anglePointY,-anglePointAngle-turnAngle);
			var unrotY = rotateY(mmX,mmY,anglePointX,anglePointY,-anglePointAngle-turnAngle);

			//Den Zielwinkel berechnen
			var destAngle = getAngle(anglePointX,anglePointY,unrotX,unrotY);

			var turnAngle = 0;
			if(destAngle>0.1) turnAngle=(dist2*outiness)/500;
			if(destAngle<-0.1) turnAngle=(-dist2*outiness)/500;

			var newAngle = photos[mdPhoto].rect.angle+turnAngle;
			if(newAngle>pi) newAngle -= piD;
			if(newAngle<=-pi) newAngle += piD;

			photos[mdPhoto].rect.setAngle(newAngle);

		}

		
		/*var x1,x2,x3,x4,y1,y2,y3,y4;
		x1=photos[mdPhoto].rect.rotateX(photos[mdPhoto].rect.left,photos[mdPhoto].rect.top);
		y1=photos[mdPhoto].rect.rotateY(photos[mdPhoto].rect.left,photos[mdPhoto].rect.top);
		x2=photos[mdPhoto].rect.rotateX(photos[mdPhoto].rect.left+photos[mdPhoto].rect.width,photos[mdPhoto].rect.top);
		y2=photos[mdPhoto].rect.rotateY(photos[mdPhoto].rect.left+photos[mdPhoto].rect.width,photos[mdPhoto].rect.top);
		x3=photos[mdPhoto].rect.rotateX(photos[mdPhoto].rect.left+photos[mdPhoto].rect.width,photos[mdPhoto].rect.top+photos[mdPhoto].rect.height);
		y3=photos[mdPhoto].rect.rotateY(photos[mdPhoto].rect.left+photos[mdPhoto].rect.width,photos[mdPhoto].rect.top+photos[mdPhoto].rect.height);
		x4=photos[mdPhoto].rect.rotateX(photos[mdPhoto].rect.left,photos[mdPhoto].rect.top+photos[mdPhoto].rect.height);
		y4=photos[mdPhoto].rect.rotateY(photos[mdPhoto].rect.left,photos[mdPhoto].rect.top+photos[mdPhoto].rect.height);
		redrawLeft = Math.min(Math.min(x1,x2),Math.min(x3,x4)) - 1;
		redrawRight = Math.min(Math.max(x1,x2),Math.max(x3,x4)) + 1;
		redrawTop = Math.min(Math.min(y1,y2),Math.min(y3,y4)) - 1;
		redrawBottom = Math.min(Math.max(y1,y2),Math.max(y3,y4)) + 1;*/

		//Die eigentliche Verschiebung
		photos[mdPhoto].rect.move(mmX - mdX, mmY - mdY);
		lastX=mmX;
		lastY=mmY;
		//Das ganze neu zeichnen
		redrawScene(2,true);

		//anglePoint alle 20 Pixel neu setzen
		if(dist > 20*20) {
			anglePointX=mmX; anglePointY = mmY; anglePointAngle = photos[mdPhoto].rect.angle;
		}
		
		busy = false;
	}
}

function Photo(imgObj) {
	var me = this;
	this.imgObj = imgObj;
	this.rect = null;
	this.loaded = false;
	
	var navbarLeft = absLeft(document.getElementById("navbar"));
	
	this.wasLoaded = function() {
                me.srcWid=viewWidth(imgObj);
                me.srcHei=viewHeight(imgObj);
		var w = me.srcWid/2.4, h = me.srcHei/2.4;
		var l = contentLeft-20 + Math.random()*(navbarLeft-60 - w-contentLeft), t = 200 + Math.random()*(viewHeight(document.getElementById("aroundall"))-250 - h);
		var a = (Math.random()*40 - 20) * pi/180;
		me.rect = new RotatedRectangle(l,t,w, h, a, l+w/2, t+h/2);
		me.loaded = true;
	}

	this.redraw = function(ctx) {
		if(me.loaded) {
			ctx.save();
			me.rect.adaptContext(ctx);
			try {
				if(aTransitionStep>=7) {
					ctx.drawImage(me.imgObj, 10-aTransitionStep, 10-aTransitionStep, me.srcWid-(10-aTransitionStep)*2, me.srcHei-(10-aTransitionStep)*2, me.rect.left, me.rect.top, me.rect.width, me.rect.height);
				} else {
 					ctx.drawImage(me.imgObj, 3, 3, me.srcWid-6, me.srcHei-6, me.rect.left, me.rect.top, me.rect.width, me.rect.height);
				}
			} catch (e) {
				//Warum auch immer geht das manchmal nicht, wenn man im Firefox Strg+F5 gedrueckt hat
				//Also hier Exception abfangen, damit nicht das ganze Skript abraucht. Stattdessen gleich
				//nochmal probieren
				tryAgainRefresh = true;
			}
			ctx.restore();
		}
	}
}

function redrawScene(onlyLevel, onlyRegion) {
	//onlyLevel: 0 - all; 1 - back; 2 - middle; 3 - front
	if(onlyLevel == 0 || onlyLevel == 1) {
		clearCtx(backCtx,onlyRegion);
		for(var i = 0; i < activePhotoOrder; i++) {
			photos[zorder[i]].redraw(backCtx);
		}
	}
	if(onlyLevel == 0 || onlyLevel == 2) {
		clearCtx(middleCtx,onlyRegion);
		if(activePhotoOrder!=-1) {
			photos[zorder[activePhotoOrder]].redraw(middleCtx);
		}
	}
	if(onlyLevel == 0 || onlyLevel == 3) {
		clearCtx(frontCtx,onlyRegion);
		for(var i = activePhotoOrder+1; i < photoCount; i++) {
			photos[zorder[i]].redraw(frontCtx);
		}
	}
}

function clearCtx(ctx, onlyRegion) {
//	if(onlyRegion) {
//		ctx.clearRect(redrawLeft,redrawTop,redrawRight-redrawLeft+1,redrawBottom-redrawTop+1);
//	} else {
		ctx.clearRect(0,0,ctxWid, ctxHei);
//	}
}

function rotateX(x,y,aroundx,aroundy,angle) {
	return aroundx + Math.cos(angle)*(x-aroundx) - Math.sin(angle)*(y-aroundy);
}
function rotateY(x,y,aroundx,aroundy,angle) {
	return aroundy + Math.sin(angle)*(x-aroundx) + Math.cos(angle)*(y-aroundy);
}


function RotatedRectangle(left,top,width,height,angle,rotx,roty) {

	//Variablen- und Funktionendeklarationen

	var co11,co12,co21,co22; //Koeffizienten der Drehmatrix

	var me = this;

	this.setRotPoint=function(nrotx, nroty) {
		//Oberen linken Punkt um alten Rotationspunkt drehen...
		rotL = me.rotateX(me.left,me.top);
		rotT = me.rotateY(me.left,me.top);

		//Neuen Rotationspunkt setzen
		me.rotx = nrotx;
		me.roty = nroty;

		//...und um neuen Rotationspunkt zurücksetzen. Dadurch bleibt die 
		//gedrehte obere linke Ecke gleich. Genial, was?
		me.left = me.rotateInvX(rotL,rotT);
		me.top = me.rotateInvY(rotL,rotT);
	}

	this.rotateX = function(x,y) {
		return me.rotx + co11*(x-me.rotx) + co12*(y-me.roty);
	}
	this.rotateY = function(x,y) {
		return me.roty + co21*(x-me.rotx) + co22*(y-me.roty);
	}
	this.rotateInvX = function(x,y) {
		return me.rotx + co11*(x-me.rotx) - co12*(y-me.roty);
	}
	this.rotateInvY = function(x,y) {
		return me.roty - co21*(x-me.rotx) + co22*(y-me.roty);
	}

	this.pointInside = function(x,y) {
		var rx=me.rotateInvX(x,y);
		var ry=me.rotateInvY(x,y);
		return(rx>=me.left && ry>=me.top && rx<me.left+me.width && ry<me.top+me.height);
	}


	this.setAngle = function(angle) {
		me.angle=angle;
		co11=Math.cos(angle);
		co12=-Math.sin(angle);
		co21=Math.sin(angle);
		co22=Math.cos(angle);
	}

	this.move = function(tox, toy) {
		//Rotationspunkt mitverschieben
		me.rotx=me.rotx+(tox-me.left);
		me.roty=me.roty+(toy-me.top);
		me.left=tox;
		me.top=toy;
	}

	this.adaptContext = function(ctx) {
		ctx.translate(me.rotx,me.roty);
		ctx.rotate(me.angle);
		ctx.translate(-me.rotx,-me.roty);
	}

	//Der eigentliche Konstruktor

	this.left = left;
	this.top = top;
	this.width = width;
	this.height = height;
	this.rotx = rotx;
	this.roty = roty;
	this.setAngle(angle);

}


