/**
* cardEngine
*
* written by Florian Sax 20080523 <flosax(at)users.sourceforge.net>
* Copyright (C) 2006 Florian Sax
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
* 
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
* GNU General Public License for more details.
* 
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
* 
* 
* You can also find the GPL at the following internet adress: <http://www.gnu.org/copyleft/gpl.html>
*
* @version: = 20080523
*/

if( !window.JSAX){
	alert( "cardEngine requires the JSAX to run.");
}

require( "event", "OutPut");

/**
* JSAX.drag
*
* written by Florian Sax 20080523 <flosax(at)users.sourceforge.net>
* Copyright (C) 2008 Florian Sax
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
* 
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
* GNU General Public License for more details.
* 
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
* 
* 
* You can also find the GPL at the following internet adress: <http://www.gnu.org/copyleft/gpl.html>
*
* @version: = 20080523
* this version is not nicely integrated in the JSAX.
* requires an optimization of the window.mouseX/Y evaluation
*/
JSAX.drag = {
	/**
	* the following 4 functions are for window movement & resize
	*/
	elems: [],
	"begin": function( targetElem, onDragEnd, e){
		if( onDragEnd){
			targetElem.onDragEnd = onDragEnd;
		}
		JSAX.drag.elems.push( targetElem);

		JSAX.drag.mMove( e);
		JSAX.drag.lastX = window.mouseX;
		JSAX.drag.lastY = window.mouseY;

		document.onmousemove = JSAX.drag["do"];
		document.onmouseup   = JSAX.drag["end"];
		document.onselectstart = function( e){ return JSAX.Event.preventAction( e); };
		document.ondragstart = function( e){ return JSAX.Event.preventAction( e); };
//		JSAX.drag["do"]( e);

//		return JSAX.Event.preventAction();
	},
	
	"do": function( e){	
//		alert( elem.parentNode.innerHTML);
		JSAX.drag.mMove( e);

		var difX	= 0;
		var difY	= 0;
		if( window.mouseX && JSAX.drag.lastX){
			var difX	= window.mouseX -JSAX.drag.lastX;
			var difY	= window.mouseY -JSAX.drag.lastY;
		}
		
		var minimumX	= 0;//80+parseInt( frm.left);
		var minimumY	= 0;//50+parseInt( frm.top);
		minimumX = -1280;
		minimumY = -1024;
		
		
		for( var i = 0; i < JSAX.drag.elems.length; i++){
			var elem = JSAX.drag.elems[i];
			var newX	= elem.offsetLeft +difX;
			var newY	= elem.offsetTop +difY;
			if( newX < minimumX){
				newX = minimumX;
			}
			if(newY < minimumY){
				newY = minimumY;
			}
		
			elem.style.position = "absolute";
			elem.style.left	= newX+"px";
			elem.style.top	= newY+"px";
			elem.style.zIndex = "999";
		}

		JSAX.drag.lastX	= window.mouseX;
		JSAX.drag.lastY	= window.mouseY;
		
		
//		return JSAX.Event.preventAction( e);
	},
	
	"end": function( e){
		var e = JSAX.Event.solv( e);
		JSAX.drag.mMove( e);

		document.onmousemove = null;
		document.onmouseup   = null;
		document.onselectstart = null;
		document.ondragstart = null;

		for( var i = 0; i < JSAX.drag.elems.length; i++){
		var elem = JSAX.drag.elems[i];
		// execute onDragEnd
		if( typeof( elem.onDragEnd) == "function"){
			elem.onDragEnd( e);
		}
		// reset elem data
		elem.style.position = "";
		elem.style.left	= "";
		elem.style.top	= "";
		elem.style.zIndex = "";
		elem.onDragEnd = null;
		}
		JSAX.drag.elems = [];
//		return JSAX.Event.preventAction( e);
	},
	mMove: function( e){
		var ev = JSAX.Event.solv( e);
		if( !ev)return;
		window.mouseX = ev.clientX +document.body.scrollLeft;
		window.mouseY = ev.clientY +document.body.scrollTop;
	}

};

window.elemsByClass = function( elem, cn){
	if(!elem.getElementsByTagName){
		var elem = document;
	}
	var allElems = elem.getElementsByTagName("*");
	var elems = new Array;
	for( var i = 0; i < allElems.length; i++){
		if( isClassMember(allElems[i], cn)){
			elems.push(allElems[i]);
		}
	}
	return elems;
};

window.sol = {
	start : function(){},
	deal : function(){},
	updateStatus : function(){}
};
window.cardEngine = {
	version : 20080523,

	games : [],
	game : function(){},

	decks : [],

	loadDeckFile : function( file, area){
		if( !area){
			var area = document.getElementById( "cardEngine_stack");
			if( !area){
				area = document.createElement( "div");
				area.id = "cardEngine_stack";
				document.body.appendChild( area);
			}
		}
		if( typeof( area.add) != "function"){
			area.innerHTML = "Loading deck file...";
		}
		if( cardEngine.decks[file]){
			cardEngine.loadDeck( cardEngine.decks[file]);
		}else{
			cardEngine.decks[file] = read( file);
			cardEngine.loadDeck( cardEngine.decks[file], area);
//			read( file, "cardEngine.decks['"+file+"'] = ...; cardEngine.loadDeck( cardEngine.decks['"+file+"']);");
		}
	},
	num_cards : 0,
	loadDeck : function( deck, area){
		if( !area){
			var area = byId( "cardEngine_stack");
			if( !area){
				area = document.createElement( "div");
				area.id = "cardEngine_stack";
				document.body.appendChild( area);
			}
		}
		if( typeof( area.add) != "function"){
			area.innerHTML = "";
//			area.innerHTML = "<style type=text/css>"+deck+"</style>";
			cardEngine.activateStack( area);
		}
		var rows = deck.split( "\n");
		for( var i = 0; i < rows.length; i++){
			// get name from css line [.br 	{}]
			var name = rows[i].split( ".")[1];
			if( !name)continue;
			name = name.split( " ")[0].split( "\t")[0];
			var card = document.createElement( "div");
			card.cardId = this.num_cards++;
			card.cardName = name;
			card.className = "cardEngine_card back";
			JSAX.object.attachTo( cardEngine.card, card);
			area.add( card, 1);
			if( typeof( area.add) != "function")return;
		}
		cardEngine.area = area;
		cardEngine.refreshStatus();
	},
	card : {
		onmousedown : function( e){
			var el = this;
			var els = [el];
			while( el.nextSibling){
				if( !this.stack.pattern( el.nextSibling, el)){
					return;
				}
				el = el.nextSibling;
				els.push( el);
			}
			var f = function( e){
				var target = cardEngine.dragNDropToStack( e);
				if( target)target.add( this);
//				alert( target.className);
			};
			for( var i = els.length-1; i >= 0; i--){
				if( f)JSAX.drag.begin( els[i], f, e);
//				f = null;
			}
			
		},
		onclick : function( e){ // the onclick function when the card is flippedq
			if( this.nextSibling)return false; // dont do anything with facedown cards that are not top of the stack
			cardEngine.log( "<br/>click on card back:"+this.stack.id.substr( 11)+":"+this.className.substr( 11));
//			this.className = this.className.replace( "_card back", "_card "+this.cardName);
			this.flip();
			this.onclick = this.onfrontclick;
			cardEngine.setActive( this);
		},
		onfrontclick : function( e){
			cardEngine.log( "<br/>click on card front:"+this.stack.id.substr( 11)+":"+this.className.substr( 11));
			var el = this;
			while( el.nextSibling){
				if( !this.stack.pattern( el.nextSibling, el)){
					return;
				}
				el = el.nextSibling;
			}
			if( this.stack && cardEngine.activeCard
			 && this.stack.add( cardEngine.activeCard)){ // add to stack
//				alert( stk.topCard().className);
				return JSAX.Event.preventAction( e);
			}
			// else set active
			cardEngine.setActive( this);
//			document.getElementById( "cardEngine_stack_1").add( this);
			return;
			JSAX.drag.begin( this);
		},
		num : function(){
			var s = this.cardName.substr( 1);
			if( s == "J")return 11;
			else if( s == "Q")return 12;
			else if( s == "K")return 13;
			else return parseInt( s);
		},
		color : function(){
			var s = this.cardName.substr( 0, 1);
			if( s == "C" || s == "S")return "r";
			else if( s == "D" || s == "H")return "b";
			else return false;
		},
		flip : function(){
			cardEngine.log( "<br/>Flip:"+this.stack.id.substr( 11)+":"+this.className.substr( 11));
			if( this.className.indexOf( " active") != -1){
				cardEngine.activeCard = null;
				document.getElementById( "cardEngine_hidden").appendChild( document.getElementById( "cardEngine_active"));
				cardEngine.log( " active");
			}
			if( this.className.indexOf( "cardEngine_card back") == 0){
				this.className = "cardEngine_card "+this.cardName;
				this.onclick = cardEngine.card.onfrontclick;
				cardEngine.log( " to front "+this.cardName);
			}else{
				this.className = "cardEngine_card back";
				this.onclick = cardEngine.card.onclick;
				cardEngine.log( " to back");
			}
		}
	},

	absoluteOffset : function( elem, which){
		if( !elem.tagName)return;
		var w = {"Top":"OK","Left":"OK"};
		if( w[which] != "OK"){
			return false;
		}
		w = "offset"+which;
		var v = elem[w];
		if( elem.offsetParent && elem.offsetParent.tagName != "BODY"){
			v += cardEngine.absoluteOffset( elem.offsetParent, which);
		}
		return v;
	},
	dragNDropToStack : function( e){
		var ev = JSAX.Event.solv( e);
		var els = document.body.getElementsByTagName( "div");
		var x = window.mouseX;
		var y = window.mouseY;
		var sks = [];
		for( var i = 0; i < els.length; i++){
			if( els[i].className == "cardEngine_stack"){
				var e = [ cardEngine.absoluteOffset( els[i], "Left"), cardEngine.absoluteOffset( els[i], "Top"), els[i].offsetWidth, els[i].offsetHeight];
			if( x >= e[0] && x <= e[0]+e[2] && y >= e[1] && y <= e[1]+e[3]){
					return els[i];
				}
				sks.push( [e,els[i]]);
			}
		}

		for( i = sks.length-1; i >= 0; i--){ // run again threw, with heiger tolerance
			e = sks[i][0];
			e[0] -= 5;
			e[1] -= 5;
			e[2] += 10;
			e[3] += 300; // add 300px to height tolerace
			if( x >= e[0] && x <= e[0]+e[2] && y >= e[1] && y <= e[1]+e[3]){
				return sks[i][1];
			}
		}
		return false;
	},



	activateStack : function( elem){
		var container = elem.getElementsByTagName( "div")[0];
		if( container && container.className == "cardEngine_stackContainer"){
			return;
		}
		var stack = elem;
		if( !stack || !stack.tagName){
			alert( "no valid stack element submitted"); return;
		}
		var container = document.createElement( "div");
		container.className = "cardEngine_stackContainer";
		stack.appendChild( container);
//		stack.obj = cardEngine.stack
		JSAX.object.attachTo( cardEngine.stack, stack);
//		cardEngine.stacks[cardEngine.stacks.length -1] = stack;
	},
//	stacks : [],
	stack : {
		cards : function(){
			var cs = [];
			var divs = this.getElementsByTagName( "div")[0].getElementsByTagName( "div");
			return divs;
			for( var i = 0; i < divs.length; i++){
				if( divs[i].className && divs[i].className.indexOf( "cardEngine_card") == 0){
					cs.push( divs[i]);
				}
			}
			return cs;
		},
		onclick : function( e){
			cardEngine.log( "<br/>click on stack:"+this.id.substr( 11));
			if( this.topCard())cardEngine.log( " with top card:"+this.topCard().className.substr( 11));
			if( cardEngine.activeCard)this.add( cardEngine.activeCard);
//			alert( cardEngine.activeCard.className);
		},
		add : function( card, force){
			var cs = this.cards().length;
//			alert( cs+" "+this.id);
			var tc = this.topCard();
			if( tc.cardId == card.cardId
			 || ( !force && !this.pattern( card, tc))){
				return false;
			}
			var lastStack = card.stack;
			if( card.stack && tc.stack)cardEngine.log( "<br/>Move:"+card.stack.id.substr( 11)+":"+card.className.substr( 11)+" to:"+tc.stack.id.substr( 11)+":"+tc.className.substr( 11));


			var cards = [];
			var stk = card.stack;
			if( stk){
//				var ml = stk.cards().length;
				var c = card;
				while( c && c.cardName){
					cards.push( c);
					c = c.nextSibling;
				}
			}else cards = [card];
//			alert( cards.length);
			for( var i = 0; i < cards.length; i++){
				card = cards[i];
				if( card.stack)card.stack.remove( card);
				card.stack = this;
				this.getElementsByTagName( "div")[0].appendChild( card);
			}

/*			// arrange the heights of this and the last stack
			if( lastStack){
				card = lastStack.topCard();
				lastStack.getElementsByTagName( "div")[0].style.height = parseInt( card.offsetTop)+parseInt( card.offsetHeight)+"px";
			}
			card = this.topCard();
			this.getElementsByTagName( "div")[0].style.height = parseInt( card.offsetTop)+parseInt( card.offsetHeight)+"px";
*/
			if( !force && stk){
				var tc = stk.topCard();
				if( tc && stk.id != "cardEngine_stack"){
					cardEngine.setActive( tc);
//					tc.onclick();
				}
//				cardEngine.setActive( stk.topCard());
			}
			if( !force){
				cardEngine.lastMove = [lastStack, card];
				sol.updateStatus();
			}
			return true;

//			card.onmousedown = function( e){};

//			card.style.position = "absolute"
//			card.style.top = ((this.cards().length -1) *20)+"px"
//			card.style.zIndex = this.cards().length;
		},
		shuffle : function( count){
			if( !count)count = 1024;
			var cards = this.cards().length;
			var container =  this.getElementsByTagName( "div")[0];
			for( var i = 0; i < count; i++){
				var card = Math.floor( Math.random() *(cards));
//				if( card==51)alert( container.getElementsByTagName( "div")[card]);
//				container.removeChild( this.getElementsByTagName( "div")[card]);
				container.appendChild( container.getElementsByTagName( "div")[card]);
			}
			
		},
		remove : function( card){
			return;
			var cs = [];
			for( var i = 0; i < this.cards.length; i++){
				if( this.cards[i] != card){
					cs.push( this.cards[i]);
				}
			}
			this.cards = cs;
		},
		topCard : function(){
			var divs = this.getElementsByTagName( "div");
//			return divs[divs.length-1];

			var m = "cardEngine_card";
			for( var i = divs.length -1; i > 0; i--){
				var n = divs[i].className;
				if( n.substr( 0, m.length) == m){
					return divs[i];
				}
			}
			return false;

			var cs = this.cards();
			if( !cs.length)return false;
			return cs[cs.length -1];

			var card = this.cards[0];
			for( var i = 0; i < this.cards.length; i++){
				if( this.cards[i].style.zIndex == 999)continue;
				if( this.cards[i].style.zIndex > card.style.zIndex){
					card = this.cards[i];
				}
			}
			return card;
		},
		pattern : function( newCard, card){

			var n_c = newCard.className;
			var n_n = cardEngine.parseNum( n_c);
			n_c = n_c.split( " ")[1];
			n_c = n_c.substr( 0, 1);

			if( !card)var card = this.topCard();
			var t_c = card;
			if( !t_c){ // no card in stack
				if( n_n == 13){
					return true;
				}else{
					return false;
				}
			}
			t_c = t_c.className;
			var t_n = cardEngine.parseNum( t_c);
			t_c = t_c.split( " ")[1];
			t_c = t_c.substr( 0, 1);

			if( t_n == n_n +1){
				n_c = "HCDS".indexOf( n_c) %2;
				t_c = "HCDS".indexOf( t_c) %2;
				if( n_c != t_c){
					return true;
				}
			}
			return false;
//			alert( t_c+" "+n_c+" "+t_n+" "+n_n);
		}
	},

	unDo : function(){
		if( this.lastMove){
			this.lastMove[0].add( this.lastMove[1], 1);
			sol.updateStatus();
			this.setActive( this.lastMove[1]);
			this.lastMove = false;
		}
	},
	setActive : function( elem){

		cardEngine.log( "<br/>setActive:"+elem.stack.id.substr( 11)+":"+elem.className.substr( 11));

		if( elem.className == "cardEngine_card back"){
//			elem.className = "cardEngine_card "+elem.cardName;
			elem.flip(); // autoflip&click
			cardEngine.log( " - flipped to:"+elem.className.substr( 11));
//			return; // dont autoflip&click
//			return elem.onclick();
		}
		if( cardEngine.activeCard){
//			alert( this.activeCard.className+"\n"+elem.className);
//			JSAX.Opacity.set( 100, cardEngine.activeCard);
			cardEngine.activeCard.className = cardEngine.activeCard.className.replace( " active", "");
		}
		var activ = document.getElementById( "cardEngine_active");
		elem.appendChild( activ);
//		JSAX.Opacity.set( 80, elem);
		cardEngine.activeCard = elem;
		cardEngine.activeCard.className += " active";
		return;
	},

	undo : function( steps){
		cardEngine.refreshStatus();
	},
	parseNum : function( s){
		var s = s.split( " ")[1];
		s = s.substr( 1);
		if( s == "J")return 11;
		else if( s == "Q")return 12;
		else if( s == "K")return 13;
		else return parseInt( s);
	},

	coordinatesBetween : function( c1, c2){
		var fx = parseInt( c1.split( "x")[0]);
		var fy = parseInt( c1.split( "x")[1]);
		var tx = parseInt( c2.split( "x")[0]);
		var ty = parseInt( c2.split( "x")[1]);
		var cb =
			( fx -( fx -tx) /2)+
			"x"+
			( fy -( fy -ty) /2);
		return cb;
	},

	refreshStatus: function(){
		document.getElementById( "cardEngine_status").innerHTML = "OK";
	},
	"LOG" : "",
	"log" : function( txt){
		this.LOG += "\n"+txt;
	}
};


