function intersectionRect(rect1, rect2, intersectRect)
{
	var ix1, iy2, iw, ih, intersect = true;
	var e1x1 = rect1.x;
	var e1x2 = e1x1 + rect1.width;
	var e1y1 = rect1.y;
	var e1y2 = e1y1 + rect1.height;
	var e2x1 = rect2.x;
	var e2x2 = e2x1 + rect2.width;
	var e2y1 = rect2.y;
	var e2y2 = e2y1 + rect2.height;
	// horizontal
	if (e1x1 <= e2x1) {
	ix1 = e2x1;
	if (e1x2 < e2x1) intersect = false;
	else iw = Math.min(e1x2, e2x2) - e2x1;
	}
	else {
	ix1 = e1x1;
	if (e2x2 < e1x1) intersect = false;
	else iw = Math.min(e1x2, e2x2) - e1x1;
	}
	// vertical
	if (e1y2 >= e2y2) {
	iy2 = e2y2;
	if (e1y1 > e2y2) intersect = false;
	else ih = e2y2 - Math.max(e1y1, e2y1);
	}
	else {
	iy2 = e1y2;
	if (e2y1 > e1y2) intersect = false;
	else ih = e1y2 - Math.max(e1y1, e2y1);
	}
	// intersected rectangle
	if (intersect && typeof(intersectRect)=='object') {
	intersectRect.x = ix1;
	intersectRect.y = iy2 - ih;
	intersectRect.width = iw;
	intersectRect.height = ih;
	}
	return intersect;
}

//var KCardNames=["","ace","two","three","four","five","six","seven","eight","nine","ten","jack","queen","king"]
var KCardNames=["","ace","2","3","4","5","6","7","8","9","10","jack","queen","king"]

var Rect=Class.create(
{
	initialize: function(x,y,width,height)
	{
		this.x=x;
		this.y=y;
		this.width=width;
		this.height=height;
	}
});

var CStack=Class.create(
{
	initialize: function()
	{
		this.entries=new Array();
		this.clear();
	},
	pop: function()
	{
		if (this.stackPointer==-1)
		{
			return null;
		}
		this.stackPointer--;
		return this.entries.pop();
	},
	push: function(entry)
	{
		this.entries.push(entry);
		this.stackPointer++;
	},
	pushStack: function(stack)
	{
		var loop;
		var length=stack.stackPointer;
		for (loop=0; loop<=length; loop++)
		{
			this.push(stack.pop());
		}
	},
	clear: function()
	{
		this.entries=[];
		this.stackPointer=-1;
	},
	reverse: function()
	{
		this.entries.reverse();
	},
	peek: function()
	{
		if (this.stackPointer==-1)
		{
			return null;
		}
		return this.entries[this.stackPointer];
	}
});

var CCard=Class.create(
{
	initialize: function(suite,value,onMouseDownFunction,onClickFunction)
	{
		this.suite=suite;
		if ((suite=='diamonds') || (suite=='hearts'))
		{
			this.colour='red';
		}
		else
		{
			this.colour='black';
		}
		this.onMouseDownFunction=onMouseDownFunction || function(event,card){};
		this.onClickFunction=onClickFunction || function(event,card){};
		this.value=value;
		this.render();
		Event.observe(this.div, "mousedown", this.onMouseDownFunction.bindAsEventListener(this,this));
		Event.observe(this.div, "click", this.onClickFunction.bindAsEventListener(this,this));
	},
	render: function()
	{
		this.div=document.createElement('div');
		this.div.className='card no_shadow';
		this.back=document.createElement('div');
		this.back.className='card back';
		this.front=document.createElement('div');
		
		this.image=document.createElement('img');
		this.image.src="/images/cards/" + KCardNames[this.value] + '_' + this.suite + "_50.png";
		this.front.appendChild(this.image);
		
//		this.front.className='card ' + KCardNames[this.value] + '_' + this.suite;
//		this.front.innerHTML="<img src='/images/cards/" + KCardNames[this.value] + '_' + this.suite + "_50.png' />";
		this.front.className='card';
		this.highlight=document.createElement('div');
		this.highlight.className='highlight';
		this.highlight.style.display='none';
		this.div.appendChild(this.back);
		this.div.appendChild(this.front);
		this.div.appendChild(this.highlight);
		this.showBack();
		this.setPosition(0,0);
//		$('game_container').appendChild(this.div);
		document.body.appendChild(this.div);
	},
	setPosition: function(x,y)
	{
		this.x=x;
		this.y=y;
		this.div.style.left=x + 'px';
		this.div.style.top=y + 'px';
	},
	setDisplacedPosition: function(x,y,maxXD,maxYD)
	{
		var xd=0;
		var yd=0;
		if (maxXD)
		{
			xd=Math.round(Math.random() * maxXD);
			if (Math.round(Math.random() * 100) < 50)
			{
				xd*=-1;
			}
		}
		if (maxYD)
		{
			yd=Math.round(Math.random() * maxYD);
			if (Math.round(Math.random() * 100) < 50)
			{
				yd*=-1;
			}
		}
		this.setPosition(x+xd,y+yd);
	},
	setZ: function(z)
	{
		this.div.style.zIndex=z;
	},
	setClass: function(className)
	{
		this.back.className="card " + className;
	},
	showBack: function()
	{
		this.front.style.display='none';
		this.back.style.display='';
	},
	showFront: function()
	{
		this.front.style.display='';
		this.back.style.display='none';
	},
	showShadow: function()
	{
		this.div.className='card shadow';
	},
	hideShadow: function()
	{
		this.div.className='card no_shadow';
	},
	showHighlight: function()
	{
		this.highlight.style.display='';
	},
	hideHighlight: function()
	{
		this.highlight.style.display='none';
	}
});


var CCardStack=Class.create(CStack,
{
	initialize: function($super,x,y,game,includeMarker,markerClickFunction)
	{
		$super();
		this.x=x || 0;
		this.y=y || 0;
		if (includeMarker)
		{
			this.markerClickFunction=markerClickFunction || function(event){};
			this.marker=document.createElement('div');
			this.marker.className='card marker';
			this.marker.style.left=this.x + 'px';
			this.marker.style.top=this.y + 'px';
//			$('game_container').appendChild(this.marker);
			document.body.appendChild(this.marker);
			Event.observe(this.marker, "click", this.markerClickFunction.bindAsEventListener(this,this));
//			Event.observe(this.marker, "click", this.markerClickFunction.bind(this));
//			Event.observe(this.marker, "click", game.onClick.bind(game));
		}
	},
	push: function($super,card)
	{
		$super(card);
		card.setPosition(this.x,this.y);
		card.setZ(this.stackPointer+50);
	},
	calculateDropHeight: function()
	{
		var loop;
		var height=0;
		for (loop=0; loop<=this.stackPointer; loop++)
		{
			if ((this.entries[loop].y+120)>height)
			{
				height=this.entries[loop].y+120;
			}
		}
		height-=this.y;
		if (height<=0)
		{
			height=120;
		}
		return height;
	},
	moveTo: function(x,y)
	{
		var loop;
		if (this.marker)
		{
			this.marker.style.left=x + 'px';
			this.marker.style.top=y + 'px';
		}
		this.x=x;
		this.y=y;
		if (this.stackPointer<0)
			return;
		var xd=this.entries[0].x-x;
		var yd=this.entries[0].y-y;
		this.entries[0].setPosition(x,y);
		for (loop=1; loop<=this.stackPointer; loop++)
		{
			this.entries[loop].setPosition(this.entries[loop].x-xd,this.entries[loop].y-yd);
		}
	},
	topCardShadowOnly: function()
	{
		this.topCardShadowsOnly(1);
	},
	topCardShadowsOnly: function(count)
	{
		var loop;
		for (loop=this.stackPointer; loop>=0; loop--)
		{
			if (count>0)
			{
				this.entries[loop].showShadow();
			}
			else
			{
				this.entries[loop].hideShadow();
			}
			count--;
		}
	},
	showTopCard: function()
	{
		if (this.stackPointer>=0)
		{
			this.entries[this.stackPointer].showFront();
		}
	},
	containsCard: function(card)
	{
		var loop;
		for (loop=0; loop<=this.stackPointer; loop++)
		{
			if (this.entries[loop]==card)
			{
				return true;
			}
		}
		return false;
	},
	popDecsendingSelecion: function(card,alternateColours)
	{
		var loop;
		var value=-1;
		var ptr=-1;
		var colour="";
		var length;
		var selection=new CStack();
		for (loop=0; loop<=this.stackPointer; loop++)
		{
			if (this.entries[loop]==card)
			{
				ptr=loop;
				value=this.entries[loop].value;
				colour=this.entries[loop].colour;
			}
			else
			{
				if (ptr!=-1)
				{
					if (this.entries[loop].value!=value-1)
					{
						return null;
					}
					if (alternateColours)
					{
						if (this.entries[loop].colour==colour)
						{
							return null;
						}
					}
					value=this.entries[loop].value;
					colour=this.entries[loop].colour;
				}
			}
		}
		if (ptr==-1)
		{
			return null;
		}
		length=this.stackPointer;
		for (loop=ptr; loop<=length; loop++)
		{
			selection.push(this.pop());
		}
//		selection.reverse();
		return selection;
	},
	showHighlight: function()
	{
		var loop;
		for (loop=0; loop<=this.stackPointer; loop++)
		{
			this.entries[loop].showHighlight();
		}
	},
	hideHighlight: function()
	{
		var loop;
		for (loop=0; loop<=this.stackPointer; loop++)
		{
			this.entries[loop].hideHighlight();
		}
	},
	showBacks: function()
	{
		var loop;
		for (loop=0; loop<=this.stackPointer; loop++)
		{
			this.entries[loop].showBack();
		}
	},
	setClass: function(className)
	{
		var loop;
		for (loop=0; loop<=this.stackPointer; loop++)
		{
			this.entries[loop].setClass(className);
		}
	}
});


var CVerticalStack=Class.create(CCardStack,
{
	initialize: function($super,x,y,game,includeMarker,markerClickFunction)
	{
		$super(x,y,game,includeMarker,markerClickFunction);
	},
	push: function($super,card)
	{
		$super(card);
		card.setDisplacedPosition(this.x,(this.y+(this.stackPointer*25)),5,5);
		card.showShadow();
	}
});

var CSelectionStack=Class.create(CCardStack,
{
	initialize: function($super)
	{
		$super();
	},
	push: function($super,card)
	{
		this.entries.push(card);
		this.stackPointer++;
		card.showShadow();
		card.setZ(this.stackPointer+500);
	},
	reverse: function($super)
	{
		$super();
		var loop;
		for (loop=0; loop<=this.stackPointer; loop++)
		{
			this.entries[loop].setZ(this.stackPointer-loop+500);
		}
	}
});

var CHorizontalStack=Class.create(CCardStack,
{
	initialize: function($super,x,y,game,includeMarker,markerClickFunction)
	{
		$super(x,y,game,includeMarker,markerClickFunction);
	},
	push: function($super,card)
	{
		$super(card);
		card.setDisplacedPosition(this.x,(this.y+(this.stackPointer*25)),5,5);
		card.showShadow();
	}
});


var CDeck=Class.create(CCardStack,
{
	initialize: function($super,x,y,game,includeMarker,markerClickFunction)
	{
		var loop;
		var card;
		$super(x,y,game,includeMarker,markerClickFunction);
		this.originalOrder=[];
		for (loop=1; loop<=13; loop++)
		{
			card=new CCard("diamonds",loop,game.onMouseDown.bind(game),game.onClick.bind(game));
			this.originalOrder.push(card)
			this.push(card);
			card=new CCard("hearts",loop,game.onMouseDown.bind(game),game.onClick.bind(game));
			this.originalOrder.push(card)
			this.push(card);
			card=new CCard("clubs",loop,game.onMouseDown.bind(game),game.onClick.bind(game));
			this.originalOrder.push(card)
			this.push(card);
			card=new CCard("spades",loop,game.onMouseDown.bind(game),game.onClick.bind(game));
			this.originalOrder.push(card)
			this.push(card);
//			this.push(new CCard("diamonds",loop,game.onMouseDown.bind(game),game.onClick.bind(game)));
//			this.push(new CCard("hearts",loop,game.onMouseDown.bind(game),game.onClick.bind(game)));
//			this.push(new CCard("clubs",loop,game.onMouseDown.bind(game),game.onClick.bind(game)));
//			this.push(new CCard("spades",loop,game.onMouseDown.bind(game),game.onClick.bind(game)));
		}
		if (includeMarker)
		{
			this.deckButton=document.createElement('div');
			this.deckButton.className='deck_button';
			this.marker.appendChild(this.deckButton);
		}
		this.shuffle();
	},
	reorder: function(deck_order)
	{
		var loop;
		for (loop=0; loop<52; loop++)
		{
			this.entries[loop]=this.originalOrder[deck_order[loop]-1];
		}
	},
	push: function($super,card)
	{
		$super(card);
		card.setDisplacedPosition(this.x,this.y,5,5);
		card.showBack();
		this.topCardShadowsOnly(10);
	},
	pop: function($super)
	{
		var card=$super();
		this.topCardShadowsOnly(10);
		return card;
	},
	shuffle: function()
	{
		var loop;
		var loop2;
		var tmp;
		var ptr1;
		var ptr2;
		for (loop2=0; loop2<Math.floor(Math.random()*25)+1; loop2++)
		{
			for (loop=0; loop<this.entries.length; loop++)
			{
				ptr1=loop;
				ptr2=Math.floor(Math.random() * this.entries.length);
				tmp=this.entries[ptr1];
				this.entries[ptr1]=this.entries[ptr2];
				this.entries[ptr2]=tmp;
				this.entries[ptr1].setZ(ptr1);
				this.entries[ptr2].setZ(ptr2);
			}
		}
	}
});

var CWaste=Class.create(CHorizontalStack,
{
	initialize: function($super,x,y,game,includeMarker,markerClickFunction)
	{
		$super(x,y,game,includeMarker,markerClickFunction);
//		this.nextX=x;
//		this.nextY=y;
		this.ptr=0;
		this.numberOfCardsToDraw=3;
	},
	beginDraw: function(numberOfCardsToDraw)
	{
		this.numberOfCardsToDraw=numberOfCardsToDraw;
		this.ptr=0;
	},
	push: function($super,card)
	{
		$super(card);
		if (this.ptr>=this.numberOfCardsToDraw)
		{
			this.ptr=0;
		}
		card.setDisplacedPosition(this.x+(this.ptr*25),this.y,5,5);
		this.topCardShadowsOnly(10);
//		this.nextX+=25;
//		this.nextX=this.x+(this.ptr*25);
		this.ptr++;
	},
	pop: function($super)
	{
		var entry=$super();
		this.ptr--;
		this.topCardShadowsOnly(10);
		return entry;
	}
});

var CFoundation=Class.create(CCardStack,
{
	initialize: function($super,x,y,game,includeMarker,markerClickFunction)
	{
		$super(x,y,game,includeMarker,markerClickFunction);
	},
	push: function($super,card)
	{
		$super(card);
		this.topCardShadowsOnly(10);
	},
	pop: function($super)
	{
		var entry=$super();
		this.topCardShadowsOnly(10);
		return entry;
	}
});

var CVerticalStackSelectButton=Class.create(
{
	initialize: function(x, y, game, verticalStack)
	{
		this.x=x;
		this.y=y;
		this.game=game;
		this.verticalStack=verticalStack;
		this.div=document.createElement('div');
		this.div.className='select_button';
		this.image=document.createElement('image');
		this.image.src="/images/solitaire/select_button.png";
		this.div.appendChild(this.image);
		this.div.style.left=this.x + 'px';
		this.div.style.top=this.y + 'px';
		document.body.appendChild(this.div);
		Event.observe(this.div, "click", this.onClick.bindAsEventListener(this));

		this.hide();
	},
	show: function()
	{
		this.div.style.display='';
	},
	hide: function()
	{
		this.div.style.display='none';
	},
	onClick: function()
	{
		var loop;
		var card=null;
		var currentValue;
		var currentSuite;
		if (this.game.selection)
		{
			this.game.restoreSelection();
		}
		if (this.verticalStack.entries.length==0)
		{
			return;
		}
		
		if (this.verticalStack.entries.length==1)
		{
			this.game.select(null,this.verticalStack.entries[this.verticalStack.entries.length-1],this.verticalStack);
			return;
		}
		
		card=this.verticalStack.entries[this.verticalStack.entries.length-1];
		currentValue=this.verticalStack.entries[this.verticalStack.entries.length-1].value;
		currentSuite=this.verticalStack.entries[this.verticalStack.entries.length-1].suite;
		
		for (loop=(this.verticalStack.entries.length-2); loop>=0; loop--)
		{

			if (this.verticalStack.entries[loop].value==(currentValue+1))
			{
				if (this.verticalStack.entries[loop].suite!=currentSuite)
				{
					card=this.verticalStack.entries[loop];
				}
			}
			else
			{
				loop=-1;
			}
			if (loop!=-1)
			{
				currentValue=this.verticalStack.entries[loop].value;
				currentSuite=this.verticalStack.entries[loop].suite;
			}
		}
		
		this.game.select(null,card,this.verticalStack);
	}
});

var CSolitaire=Class.create(
{
	initialize: function()
	{
		var loop;
		var stack;
		var button;
		this.game_number=0;
		this.showSelectButtonsOption=false;
		this.selection=null;
		this.sourceStack=null;
		this.drawNumberOfCards=1;
		this.newGameDrawNumberOfCards=1;
		this.deck=new CDeck(10,70,this,true,this.stackMarkerClicked.bind(this));
		this.waste=new CWaste(105,70,this,false,null);
		this.verticalStacks=new Array();
		this.verticalStackSelectButtons=new Array();
		this.foundations=new Array();
		for (loop=0; loop<7; loop++)
		{
			stack=new CVerticalStack((loop*100)+7,280,this,true,this.drop.bind(this));
			this.verticalStacks.push(stack);
			button=new CVerticalStackSelectButton((loop*100)+14,230,this,stack);
			this.verticalStackSelectButtons.push(button);
		}
		for (loop=0; loop<4; loop++)
		{
			this.foundations.push(new CFoundation((loop*85)+250,70,this,true,this.drop.bind(this)));
		}
		this.dealButton=document.createElement('div');
		this.dealButton.className='deal_button';
		this.dealButton.style.display='none';
		this.winButton=document.createElement('div');
		this.winButton.className='win';
		this.winButton.style.display='none';
//		$('game_container').appendChild(this.dealButton);
//		$('game_container').appendChild(this.winButton);
		document.body.appendChild(this.dealButton);
		document.body.appendChild(this.winButton);
//		this.intersectIndicator=document.createElement('div');
//		this.intersectIndicator.className='intersect_indicator';
//		document.body.appendChild(this.intersectIndicator);
		Event.observe(this.dealButton, "click", this.dealOnTimer.bindAsEventListener(this));
		Event.observe(this.winButton, "click", this.winButtonOnClick.bindAsEventListener(this));
		Event.observe(window, "resize", this.onResize.bindAsEventListener(this));
		this.dealt=false;
//		this.deal();
		this.newGame(-1);
		User.addSignInCallbackFunction(this.signIn.bind(this));
		User.addSignOutCallbackFunction(this.signOut.bind(this));
	},
	setDrawNumberOfCards: function(number)
	{
		this.newGameDrawNumberOfCards=number;
	},
	showSelectButtons: function()
	{
		var loop;
		for (loop=0; loop<7; loop++)
		{
			this.verticalStackSelectButtons[loop].show();
			this.verticalStacks[loop].moveTo((loop*100)+7,280);
		}
	},
	hideSelectButtons: function()
	{
		var loop;
		for (loop=0; loop<7; loop++)
		{
			this.verticalStackSelectButtons[loop].hide();
			this.verticalStacks[loop].moveTo((loop*100)+7,210);
		}
	},
	newGame: function(game_number,deck_order)
	{
		var loop;
		this.hideSelectButtons();
		
		$('give_up').style.display='none';
		$('game_score_cards_turned').value=this.newGameDrawNumberOfCards;
		$('game_score_game_number').value=game_number;
		setTimeout(this.hideAddressBar.bind(this),100);
		this.dealt=false;
		this.score=0;
		this.scorePoints(0);
		this.passThroughs=0;
		this.game_number=game_number;
		this.winButton.style.display='none';
		$('score_information').style.display='none';
		for (loop=0; loop<this.foundations.length; loop++)
		{
			this.deck.pushStack(this.foundations[loop]);
		}
		for (loop=0; loop<this.verticalStacks.length; loop++)
		{
			this.deck.pushStack(this.verticalStacks[loop]);
		}
		this.deck.pushStack(this.waste);
		if (game_number<0)
		{
			this.deck.shuffle();
		}
		else
		{
			this.deck.reorder(deck_order);
		}
		this.deck.showBacks();
		this.dealButton.style.display='';
		if (AjaxModalLoader)
		{
			AjaxModalLoader.hide();
		}
		if (this.game_number>=0)
		{
			$('game_number_info').innerHTML="<b>" + this.game_number + "</b>";
		}
		else
		{
			$('game_number_info').innerHTML="<b>4</b>FUN";
		}
		$('game_number_info').style.display='';
	},
	giveUp: function()
	{
		if (this.dealt)
		{
			if (!confirm("Are you sure you want to give up?"))
			{
				return;
			}
		}
		$('give_up').style.display='none';
		alert("Your aborted score was: " + this.score);
		show_new_game_options();
	},
	onOrientationChange: function()
	{
		if (window.orientation==0)
		{
//			document.body.style.display='none';
//			document.body.style.width='320px';
//		    document.body.setAttribute("orient", "portrait");
//			$('game_menu').style.display='';
			window.scrollBy(0,1);
		}
		else
		{
//			$('game_menu').style.display='none';
//			document.body.style.display='';
//			document.body.style.width='720px';
//		    document.body.setAttribute("orient", "landscape");
			window.scrollBy(0,1);
		}
	},
	scorePoints: function(points)
	{
		this.score+=points;
	},
	dealOnTimer: function()
	{
		AjaxModalLoader.show();
		setTimeout(this.deal.bind(this),100)
	},
	deal: function()
	{
		var loop;
		var loop2;
		if (this.showSelectButtonsOption)
			this.showSelectButtons();
		else
			this.hideSelectButtons();
		
//		setTimeout(this.hideAddressBar.bind(this),100);
		this.drawNumberOfCards=this.newGameDrawNumberOfCards;
		for (loop=0; loop<7; loop++)
		{
			for (loop2=0; loop2<=loop; loop2++)
			{
					this.verticalStacks[loop].push(this.deck.pop());
			}
			this.verticalStacks[loop].showTopCard();
		}
		this.dealButton.style.display='none';
		$('game_number_info').style.display='none';
		this.dealt=true;
		this.startTime=new Date();
		this.looseTenPointsTimeout=this.startTime-0+10000;
		this.updateTimeTimer=setInterval(this.updateTime.bind(this),1000);
//		this.cheat();
		AjaxModalLoader.hide();
		this.hideOptionsBar();
		$('give_up').style.display='';
	},
	cheat: function()
	{
		var ptr;
		var loop;
		var loop2;
		var length;
		for (loop=0; loop<this.verticalStacks.length; loop++)
		{
			length=this.verticalStacks[loop].entries.length;
			for (loop2=0; loop2<length; loop2++)
			{
				ptr=Math.round(Math.random() * 3);
				this.foundations[ptr].push(this.verticalStacks[loop].pop());
			}
		}
		length=this.deck.entries.length;
		for (loop=0; loop<length-2; loop++)
		{
			ptr=Math.round(Math.random() * 3);
			this.foundations[ptr].push(this.deck.pop());
		}
	},
	updateTime: function()
	{
		var now=new Date();
		var played=now-this.startTime;
//		document.title=now + " " + this.looseTenPointsTimeout;
		if (now-0>=this.looseTenPointsTimeout)
		{
			this.looseTenPointsTimeout=now-0+10000;
			this.scorePoints(-10);
		}

		$('game_time').innerHTML=Math.floor(played/1000);
	},
	stackMarkerClicked: function(event,stack)
	{
		if (stack==this.deck)
		{
			this.deck.pushStack(this.waste);
			this.passThroughs++;
			if (this.drawNumberOfCards==3)
			{
				if (this.passThroughs>=3)
				{
					this.scorePoints(-125);
				}
			}
			else
			{
				this.scorePoints(-200);
			}
		}
	},
	draw: function()
	{
		var card;
		var loop;
		if (!this.dealt)
		{
			return;
		}
		this.waste.beginDraw(this.drawNumberOfCards);
		for (loop=0; loop<this.drawNumberOfCards; loop++)
		{
			card=this.deck.pop();
			if (card)
			{
				card.showFront();
				card.showShadow();
				this.waste.push(card);
			}
		}
		this.scorePoints(0-this.drawNumberOfCards);
//		this.waste.topCardShadowsOnly(3);
		
	},
	getCardStack: function(card)
	{
		var loop;
		if (this.deck.containsCard(card))
		{
			return this.deck;
		}
		if (this.waste.containsCard(card))
		{
			return this.waste;
		}
		for (loop=0; loop<this.verticalStacks.length; loop++)
		{
			if (this.verticalStacks[loop].containsCard(card))
			{
				return this.verticalStacks[loop];
			}
		}
		for (loop=0; loop<this.foundations.length; loop++)
		{
			if (this.foundations[loop].containsCard(card))
			{
				return this.foundations[loop];
			}
		}
		return null;
	},
	isVerticalStack: function(stack)
	{
		var loop;
		for (loop=0; loop<this.verticalStacks.length; loop++)
		{
			if (this.verticalStacks[loop]==stack)
			{
				return true;
			}
		}
		return false;
	},
	isFoundationStack: function(stack)
	{
		var loop;
		for (loop=0; loop<this.foundations.length; loop++)
		{
			if (this.foundations[loop]==stack)
			{
				return true;
			}
		}
		return false;
	},
	onMouseDown: function(event,card)
	{
	},
	onClick: function(event,card)
	{
		
	},
	onMouseDown: function(event,card)
	{
		Event.stop(event);
		var stack=this.getCardStack(card);
		if (!stack)
		{
			this.restoreSelection();
			return;
		}
		if (stack==this.deck)
		{
			if (this.selection)
			{
				this.restoreSelection();
				this.clearSelection();
			}
			this.draw();
			return;
		}
		if (!this.selection)
		{
			this.select(event,card,stack);
			if (!this.selection)
			{
				return;
			}
			this.startX=parseInt(event.clientX);
			this.startY=parseInt(event.clientY);
			this.dragXD=this.selection.entries[0].x - this.startX;
			this.dragYD=this.selection.entries[0].y - this.startY;
			this.dragStarted=false;
			this.mouseMoveEvent=this.onMouseMove.bindAsEventListener(this);
			Event.observe(document, "mousemove", this.mouseMoveEvent);
			this.mouseUpEvent=this.onMouseUp.bindAsEventListener(this);
			Event.observe(document, "mouseup", this.mouseUpEvent);
		}
		else
		{
			this.drop(event,stack);
		}
	},
	onMouseMove: function(event)
	{
		var xd;
		var yd;
		Event.stop(event);
		if (!this.dragStarted)
		{
			xd=event.clientX-this.startX;
			yd=event.clientY-this.startY;
			if (xd<0)
			{
				xd*=-1;
			}
			if (yd<0)
			{
				yd*=-1;
			}
			if ((xd>10) || (yd>10))
			{
				this.dragStarted=true;
			}
		}
		else
		{
			if (this.selection)
			{
				this.selection.moveTo(event.clientX+this.dragXD,event.clientY+this.dragYD);
//				this.calculateDropTarget(this.selection.entries[0].x,this.selection.entries[0].y);
			}
		}
	},
	onMouseUp: function(event)
	{
		var target;
		if (this.mouseMoveEvent)
		{
			Event.stopObserving(document, "mousemove",this.mouseMoveEvent);
			this.mouseMoveEvent=null;
		}
		if (this.mouseUpEvent)
		{
			Event.stopObserving(document, "mouseup",this.mouseUpEvent);
			this.mouseUpEvent=null;
		}
		if (this.dragStarted)
		{
			target=this.calculateDropTarget(this.selection.entries[0].x,this.selection.entries[0].y);
			if (target)
			{
				this.drop(event,target);
			}
			this.restoreSelection();
		}
		this.dragStarted=false;
	},
	calculateDropTarget: function(x,y)
	{
		var rect=new Rect(0,0,0,0);
		var sourceRect=new Rect(this.selection.entries[0].x,this.selection.entries[0].y,80,120);
		var targetRect=new Rect(0,0,0,0);
		var loop;
		var area;
		var testArea=0;
		var target=null;
		for (loop=0; loop<this.verticalStacks.length; loop++)
		{
			targetRect.x=this.verticalStacks[loop].x;
			targetRect.y=this.verticalStacks[loop].y;
			targetRect.width=80;
			targetRect.height=this.verticalStacks[loop].calculateDropHeight();
			if (intersectionRect(sourceRect,targetRect,rect))
			{
				area=rect.width*rect.height;
				if (area>testArea)
				{
					testArea=area;
					target=this.verticalStacks[loop];
//					this.intersectIndicator.style.left=rect.x + 'px';
//					this.intersectIndicator.style.top=rect.y + 'px';
//					this.intersectIndicator.style.width=rect.width + 'px';
//					this.intersectIndicator.style.height=rect.height + 'px';
				}
			}
		}
		for (loop=0; loop<this.foundations.length; loop++)
		{
			targetRect.x=this.foundations[loop].x;
			targetRect.y=this.foundations[loop].y;
			targetRect.width=80;
			targetRect.height=120;
			if (intersectionRect(sourceRect,targetRect,rect))
			{
				area=rect.width*rect.height;
				if (area>testArea)
				{
					testArea=area;
					target=this.foundations[loop];
//					this.intersectIndicator.style.left=rect.x + 'px';
//					this.intersectIndicator.style.top=rect.y + 'px';
//					this.intersectIndicator.style.width=rect.width + 'px';
//					this.intersectIndicator.style.height=rect.height + 'px';
				}
			}
		}
		return target;
	},
	restoreSelection: function()
	{
		this.selection.hideHighlight();
		this.selection.reverse();
		if (this.sourceStack)
		{
			this.sourceStack.pushStack(this.selection);
		}
		this.clearSelection();
	},
	clearSelection: function()
	{
		if (this.selection)
		{
			this.selection=null;
			this.sourceStack=null;
		}
	},
	select: function(event,card,stack)
	{
		var selection;
		if (!stack)
		{
			stack=this.getCardStack(card);
		}
		if (this.selection)
		{
			this.drop(event,stack);
			return;
		}
		this.sourceStack=stack;
		if (stack==this.waste)
		{
			this.selection=new CSelectionStack();
			this.selection.push(this.waste.pop());
		}
		if (this.isVerticalStack(stack))
		{
			selection=stack.popDecsendingSelecion(card,true);
			if (!selection)
			{
				return;
			}
			this.selection=new CSelectionStack();
			this.selection.pushStack(selection);
		}
		if (this.isFoundationStack(stack))
		{
			this.selection=new CSelectionStack();
			this.selection.push(stack.pop());
		}
		if (this.selection)
		{
			this.selection.showHighlight();
		}
	},
	drop: function(event,stack)
	{
		if (this.selection)
		{
			this.selection.hideHighlight();
		}
		if ((!this.selection) || (!stack))
		{
			this.restoreSelection();
			return;
		}
		if (this.validateMove(stack))
		{
			this.selection.reverse();
			stack.pushStack(this.selection);
			if (this.sourceStack)
			{
				if (this.sourceStack==this.waste)
				{
					this.scorePoints(45);
				}
				if ((this.isFoundationStack(this.sourceStack)) && (!this.isFoundationStack(stack)))
				{
					this.scorePoints(-75);
				}
				if ((!this.isFoundationStack(this.sourceStack)) && (this.isFoundationStack(stack)))
				{
					this.scorePoints(60);
				}
				if (this.isVerticalStack(this.sourceStack) && (this.sourceStack.stackPointer>=0))
				{
					if (this.sourceStack.entries[this.sourceStack.stackPointer].front.style.display=='none')
					{
						this.sourceStack.showTopCard();
						this.scorePoints(25);
					}
				}
			}
			this.clearSelection();
			if (this.hasWon())
			{
				this.win();
			}
		}
		else
		{
			this.restoreSelection();
		}
	},
	validateMove: function(stack)
	{
//		return true;
		var topCard;
		if ((!stack) || (stack==this.deck) || (stack==this.waste))
		{
			return false;
		}
		topCard=stack.peek();
		if (!topCard)
		{
			if (this.isFoundationStack(stack))
			{
				if (this.selection.entries[0].value==1)
				{
					return true;
				}
			}
			else
			{
				if (this.selection.entries[0].value==13)
				{
					return true;
				}
			}
			return false;
		}
		if (this.isFoundationStack(stack))
		{
			if (topCard.suite==this.selection.entries[0].suite)
			{
				if (topCard.value==(this.selection.entries[0].value-1))
				{
					return true;
				}
			}
			return false;
		}
		if (topCard.value==(this.selection.entries[0].value+1))
		{
			if (topCard.colour!=this.selection.entries[0].colour)
			{
				return true;
			}
			else
			{
				return false;
			}
		}
		return false;
	},
	onResize: function(event)
	{
		var width=parseInt(document.body.clientWidth);
		var xd=(width/2)/4;
		var x=xd-47;
/*
		this.verticalStacks[0].moveTo(x,200);
		x+=xd;
		this.verticalStacks[1].moveTo(x,200);
		x+=xd;
		this.verticalStacks[2].moveTo(x,200);
		x=(width/2-47);
		this.verticalStacks[3].moveTo(x,200);
		x+=xd;
		this.verticalStacks[4].moveTo(x,200);
		x+=xd;
		this.verticalStacks[5].moveTo(x,200);
		x+=xd;
		this.verticalStacks[6].moveTo(x,200);
*/		
	},
	hasWon: function()
	{
		var count=0;
		var loop;
		for (loop=0; loop<this.foundations.length; loop++)
		{
			count+=this.foundations[loop].entries.length;
		}
		if (count==52)
		{
			return true;
		}
		return false;
	},
	win: function()
	{
		$('give_up').style.display='none';
		var now=new Date();
		this.playedTime=now-this.startTime;
		setTimeout(this.winDisplay.bind(this),250);
	},
	winDisplay: function()
	{
				this.winButton.style.display='';
				$('score_information').style.display='';
				if (this.game_number>=0)
				{
					$('score_information').innerHTML="Game: <b>" + this.game_number + "</b> | Score: <b>" + this.score + "</b> | Time: <b>" + this.playedTime + "</b>";
				}
				else
				{
					$('score_information').innerHTML="Game: <b>4</b>FUN | Score: <b>" + this.score + "</b> | Time: <b>" + this.playedTime + "</b>";
					
				}
				setTimeout(this.hideAddressBar.bind(this),100);
		
	},
	hideAddressBar: function()
	{
		window.scrollTo(0,1);
	},
	hideOptionsBar: function()
	{
		window.scrollTo(0,50);
	},
	winButtonOnClick: function()
	{
		$('score_information').style.display='none';
		this.winButton.style.display='none';
//		alert("Well Done!\n\nScore: " + this.score + " Time: " + this.playedTime)
		if (this.game_number>=0)
		{
			$('game_score_time').value=this.playedTime;
			$('game_score_score').value=this.score;
			show_scored_game_save_score_options();
		}
	},
	applySettings: function(cardsToDraw, deck, showSelectButtons)
	{
		this.newGameDrawNumberOfCards=cardsToDraw;
		this.applyDeck(deck);
		if (showSelectButtons=="false")
		{
			showSelectButtons=false;
		}
		if (showSelectButtons=="true")
		{
			showSelectButtons=true;
		}
		this.showSelectButtonsOption=showSelectButtons;
		if (this.showSelectButtonsOption)
		{
			this.showSelectButtons();
		}
		else
		{
			this.hideSelectButtons();
		}
	},
	applyDeck: function(deck)
	{
		var loop;
		this.deck.setClass("back_"+deck);
		this.waste.setClass("back_"+deck);
		for (loop=0; loop<this.verticalStacks.length; loop++)
		{
			this.verticalStacks[loop].setClass("back_"+deck);
		}
		for (loop=0; loop<this.foundations.length; loop++)
		{
			this.foundations[loop].setClass("back_"+deck);
		}
	},
	signIn: function()
	{
		$('sign_in_option').style.display='none';
		$('sign_out_option').style.display='';
		this.loadForms();
		if ($('scored_game_sign_in_options'))
		{
			if ($('scored_game_sign_in_options').style.display=='')
			{
				scored_game();
			}
		}
	},
	signOut: function()
	{
		if (AjaxModalLoader)
		{
			AjaxModalLoader.show();
		}
		var updater=new Ajax.Updater('ajax_container','/user/sign_out',{asynchronous:true, evalScripts:true,method:"get", onFailure:this.signOutFailure.bind(this), onSuccess:this.signOutSuccess.bind(this)});
	},
	signOutSuccess: function()
	{
		if (AjaxModalLoader)
		{
			AjaxModalLoader.hide();
		}
		$('sign_in_option').style.display='';
		$('sign_out_option').style.display='none';
	},
	signOutFailure: function()
	{
		if (AjaxModalLoader)
		{
			AjaxModalLoader.hide();
		}
		if (confirm("Oops... something went wrong.\n\nTry again?"))
		{
			this.signOut();
		}
	},
	loadForms: function()
	{
		if (AjaxModalLoader)
		{
			AjaxModalLoader.show();
		}
		var updater=new Ajax.Updater('forms','/web_apps/solitaire/forms',{asynchronous:true, evalScripts:true,method:"get", onFailure:this.loadFormsFailure.bind(this), onSuccess:this.loadFormsSuccess.bind(this)});
	},
	loadFormsSuccess: function()
	{
		if (AjaxModalLoader)
		{
			AjaxModalLoader.hide();
		}
	},
	loadFormsFailure: function()
	{
		if (AjaxModalLoader)
		{
			AjaxModalLoader.hide();
		}
		if (confirm("Oops... something went wrong.\n\nTry again?"))
		{
			this.loadForms();
		}
	}
});
