/*
JavaScript version of the hit television gameshow, "Deal or No Deal"

Copyright (c) 2007, James Auldridge
All rights reserved.
Code licensed under the BSD License:
  http://www.jaaulde.com/license.php

Version 0.9.3beta


Uses:
	* DED|Chain JavaScript Library (c) BSD License 2007
	* http://dedchain.dustindiaz.com/license.txt
	* Author: Dustin Diaz | http://www.dustindiaz.com
	* Website: http://dedchain.dustindiaz.com
	* V 0.2

	YAHOO     YAHOO.util.Dom     YAHOO.util.Even
	Copyright (c) 2007, Yahoo! Inc. All rights reserved.
	Code licensed under the BSD License:
	http://developer.yahoo.net/yui/license.txt
	version: 2.2.0
*/
var debug = function(text){if(typeof console != 'undefined'){console.log(text)}};

DED.extendChain('toggleInputEnable',function(){
	var method = function(el){
		if(el.disabled===true){
			el.removeAttribute('disabled');
		}
		else{
			el.disabled = true;
		}
	}
	YAHOO.util.Dom.batch(this.el,method);return this;
});

var DoND = {
	data : {
		gameVersion : '0.9.3&beta;',
		caseAmounts : [.01,1,5,10,25,50,75,100,200,300,400,500,750,1000,5000,10000,25000,50000,75000,100000,200000,300000,400000,500000,750000,1000000],
 		cases : [],
 		remainingValues : null,
 		bmc : null,
 		bmcOpened : false,
 		lastCaseClicked : null,
		playersCase : null,
		currentState : 0,
		currentRound : 1,
		maxRounds : 10,
		openNumCasesThisRound : 6,
		casesOpenedThisRound : 0,
		casesLeft : 0,
		bankOfferDiminisher : .25,
		latestBankOffer : 0,
		highestBankOffer : 0,
		highWinnings : 0,
		winnings : 0,
		init : function(){
			DoND.data.remainingValues = DoND.data.caseAmounts.copy();
			DoND.data.cookieJar = (typeof jimAuld  != 'undefined' && typeof jimAuld.utils != 'undefined' &&	typeof jimAuld.utils.cookies != 'undefined' && jimAuld.utils.cookies.test())
				? jimAuld.utils.cookies
				: false;
			DoND.data.highWinnings = DoND.data.cookieJar
				? DoND.data.cookieJar.get('DoND_highWinnings')
				: 0;
			DoND.data.highWinnings = DoND.data.highWinnings!=null
				? parseInt(DoND.data.highWinnings)
				: 0;
		}
	},
	display : {
		//displayRoot : 'body',
		displayRoot : '#DoND-display-root',
		action : null,
		yourCase : null,
		bankoffer : null,
		popInfo : null,
		infoText : null,
		popInfoIsOpen : false,
		popInfoClose : new YAHOO.util.CustomEvent('popInfoClosed'),
		resetFlashTimer : null,
		init : function(){
			DoND.display.popInfoClose.subscribe(DoND.controller.onpopInfoClose);
			if(DoND.data.cases.length>0){
				_$(DoND.display.displayRoot).setContent('<p id="head"><a href="" id="reset">reset</a> High Score: <span id="highscore">'+DoND.display.formatUSD(DoND.data.highWinnings)+'</span></p>'+
										'<div id="caseDiv"></div>'+
										'<div id="playarea">'+
										'	<table cellspacing="0" cellpadding="0" id="strikeAmts">'+
										'		<thead>'+
										'			<tr>'+
										'				<th colspan="2">Dollar Amounts</th>'+
										'			</tr>'+
										'		</thead>'+
										'		<tbody>'+
										'		</tbody>'+
										'	</table>'+
										'	<div id="interface">'+
										'		<p class="label">Action required:</p>'+
										'		<p id="action">Please select your case to start the game</p>'+
										'		<p class="label">Your Case:</p>'+
										'		<p id="yourCase"></p>'+
										'		<p class="label">Bank Offer:</p>'+
										'		<p id="bankoffer"></p>'+
										'		<p class="label"><strong>Deal or no Deal?</strong></p>'+
										'		<p id="offerbuttons">'+
										'			<input type="button" id="deal" value="Deal!" disabled="true" />'+
										'			<input type="button" id="noDeal" value="No Deal!" disabled="true" />'+
										'		</p>'+
										'	</div>'+
										'	<ul id="bankofferHistory">'+
										'		<li><strong>Previous Bank Offers:</strong></li>'+
										'	</ul>'+
										'</div>'+
										'<p class="foot">'+
										'	<em>JavaScript <strong>Deal or No Deal</strong></em> v'+DoND.data.gameVersion+'<br />'+
										'	&copy; 2007 <a href="http://www.auldridges.com" title="Blessed Beyond Reason">Jim Auldridge</a><br />'+
										'	<a href="http://www.nbc.com/Deal_or_No_Deal/" title="Deal or No Deal on NBC">Based on the hit television game show</a>'+
										'</p>'+
										'<div id="popInfo" class="hidden">'+
										'	<p id="closePopInfoButton">Ok<br /><em>(or press Enter)</em></p>'+
										'	<p id="infoText"></p>'+
										'</div>');
				_$('#reset').on('click', function(){DoND.controller.reset()});
				_$('#deal').on('click',function(){DoND.controller.deal()});
				_$('#noDeal').on('click',function(){DoND.controller.noDeal()});
				_$(document).on('keydown',function(el,e){e = !e ? window.event : e;if(DoND.display.popInfoIsOpen===true && e.keyCode == 13 || e.which == 13){DoND.display.closePopInfo();}});
				_$('#closePopInfoButton').on('click',function(el,e){if(DoND.display.popInfoIsOpen===true){DoND.display.closePopInfo();}});
				var caseDivDCObj = _$('#caseDiv');
				for(var i=1;i<DoND.data.cases.length;i++){
					curCase = DoND.data.cases[i];
					caseDivDCObj.create('span',{id: 'case'+curCase.id},function(el){
						this.append(el);
						_$(el)
							.setContent(curCase.id)
							.on('click',function(el,e){
								DoND.controller.selectCase(el)
							})
							.addClass('notClicked');
					});
				}
				numCases = DoND.data.caseAmounts.length;
				var breakNum=Math.floor(numCases/2);
				var strikeAmtsBody = _$('#strikeAmts tbody');
				for(i=0;i<breakNum;i++){
					strikeAmtsBody.create('tr',{},function(el){
						this.append(el);
						_$(el)
							.create('td',{id:'sa'+i},function(el){
								this.append(el);
								_$(el).setContent(DoND.display.formatUSD(DoND.data.caseAmounts[i]));
							})
							.create('td',{id:'sa'+(i+breakNum)},function(el){
								this.append(el);
								_$(el).setContent(DoND.display.formatUSD(DoND.data.caseAmounts[i+breakNum]));
							});
					});
				}
			}
			else{
				throw 'DoND display object tried to build display with invalid list of cases.';
			}
		},
		formatUSD : function(num,hideZeroCents) {
			var sign,cents,dollars,numCommas,i,cPos;
			hideZeroCents = typeof hideZeroCents == 'undefined'?true:false;
			num = num.toString().replace(/[^0-9.-]/g,'');
			num = isNaN(num)?'0':num;
			sign = num==(num=Math.abs(num))?'':'-';
			num = num.toFixed(2);
			cents = Math.round((num*100)%100);
			cents = cents<10?'0'+cents:cents;
			cents = (hideZeroCents===true && cents=='00')?'':'.'+cents
			dollars = Math.floor(num).toString();
			numCommas = Math.floor(dollars.length/3);
			numCommas = dollars.length%3==0?numCommas-1:numCommas;
			for(i=0;i<numCommas;i++){
				cPos = dollars.indexOf(',');
				if(cPos===-1){cPos=dollars.length;}
				dollars = dollars.substring(0,cPos-3)+','+dollars.substring(cPos-3,dollars.length);
			}
			return sign+'$'+dollars+cents;
		},
		markPlayersCase : function(el){
			_$(el).replaceClass('notClicked','playersCase').setContent('');
			_$('#yourCase').addClass('caseSelected').setContent(DoND.data.playersCase.id);
			DoND.display.setAction('Choose '+DoND.data.openNumCasesThisRound+' cases to eliminate.');
		},
		markOutOfPlayCase : function(el){
			_$(el).replaceClass('notClicked','outOfPlay');
		},
		strikeAmount : function(id){
			_$('#sa'+id).addClass('struck');
		},
		openPopInfo : function(text){
			_$('#infoText').setContent(text);
			_$('#popInfo').replaceClass('hidden','revealed');
			DoND.display.popInfoIsOpen=true;
		},
		closePopInfo : function(){
			_$('#popInfo').replaceClass('revealed','hidden');
			_$('#infoText').setContent('');
			DoND.display.popInfoIsOpen=false;
			DoND.display.popInfoClose.fire();
		},
		showBankOffer : function(){
			DoND.display.setAction('The bank has made an offer.<br /><em>Deal or No Deal?</em>');
			_$('#bankoffer').setContent(DoND.display.formatUSD(DoND.data.latestBankOffer));
			_$('#offerbuttons input').toggleInputEnable();
		},
		removeBankOffer : function(){
			_$('#bankoffer').setContent('');
			_$('#offerbuttons input').toggleInputEnable();
			_$('#bankofferHistory').create('li',{},function(el){
				this.append(el);
				_$(el).setContent(DoND.display.formatUSD(DoND.data.latestBankOffer));
			});
		},
		setAction : function(text){
			_$('#action').setContent(text);
		},
		flashReset : function(){
			_$('#reset')
				.on('mouseover',function(){clearTimeout(DoND.display.resetFlashTimer)})
				.setCSS({
					fontWeight: 'bold',
					color: '#f00'
				});
			DoND.display.resetFlashCycler()
		},
		resetFlashCycler : function(){
			_$('#reset').toggle();
			DoND.display.resetFlashTimer = setTimeout('DoND.display.resetFlashCycler()',400);
		}
	},
	controller : {
		onpopInfoClose : function(){if(DoND.data.currentState == 3){DoND.controller.gameFlow();}},
		buildCases : function(){
			var values = DoND.data.caseAmounts.copy();
			var numCases = values.length;
			var ranNumber,ranValue;
			for(var i=numCases;i>=1;i--){
				ranNumber=Math.floor(Math.random()*i);
				ranValue = values[ranNumber];
				if(ranValue==1000000){DoND.data.bmc=i;}
				valueIndex = DoND.data.caseAmounts.indexOf(ranValue);
				values.splice(ranNumber,1);
				DoND.data.cases[i] = new DoND.controller.briefcase(i,ranValue,valueIndex);
				DoND.data.casesLeft++;
			}
		},
 		briefcase : function(id,value,valueIndex){
			this.id = id;
			this.value = value;
			this.valueIndex = valueIndex;
			this.inPlay = true;
			this.caseDisplayElement = false;
			DoND.controller.briefcase.prototype.choose = function(el){
				if(DoND.display.popInfoIsOpen === false && DoND.data.currentState!==10){
					if(this.inPlay){
	  					this.inPlay = false;
						this.caseDisplayElement = el;
						DoND.data.lastCaseClicked = this;
						DoND.data.casesLeft--;
						if(this.value==1000000){
							DoND.data.bmcOpened=true;
						}
						DoND.controller.gameFlow();
					}
				}
			}
		},
		gameFlow : function(){
			switch (DoND.data.currentState){
				case 0:
					DoND.data.currentState=1;
					DoND.data.playersCase = DoND.data.lastCaseClicked;
					DoND.display.markPlayersCase(DoND.data.lastCaseClicked.caseDisplayElement);
				break;

				case 1:
					DoND.data.casesOpenedThisRound++;
					DoND.data.remainingValues.splice(DoND.data.remainingValues.indexOf(DoND.data.lastCaseClicked.value),1);
					DoND.display.strikeAmount(DoND.data.lastCaseClicked.valueIndex);
					DoND.display.markOutOfPlayCase(DoND.data.lastCaseClicked.caseDisplayElement);
					DoND.display.setAction('Choose '+(DoND.data.openNumCasesThisRound-DoND.data.casesOpenedThisRound)+' more case(s) to eliminate.');
					DoND.display.openPopInfo('Case '+DoND.data.lastCaseClicked.id+' contained<br />'+DoND.display.formatUSD(DoND.data.lastCaseClicked.value));
					if(DoND.data.casesOpenedThisRound==DoND.data.openNumCasesThisRound){
						DoND.data.currentRound++;
						DoND.data.casesOpenedThisRound = 0;
						DoND.data.openNumCasesThisRound = DoND.data.openNumCasesThisRound>1?DoND.data.openNumCasesThisRound-1:DoND.data.openNumCasesThisRound;
						if(DoND.data.currentRound<=DoND.data.maxRounds){
							DoND.data.currentState = 10;
							DoND.controller.makeBankOffer();
						}
						else{
							DoND.data.currentState = 3;
							DoND.data.winnings = DoND.data.playersCase.value;
							var compString = DoND.data.playersCase.value > DoND.data.highestBankOffer
												? 'You came out ahead of all bank offers!'
												: "At least one bank offer was higher than your case's value--you should have quit while you were ahead!";
							DoND.display.openPopInfo("Your case held<br /><strong>"+DoND.display.formatUSD(DoND.data.playersCase.value)+"</strong><br /><br />"+compString);
						}
					}
				break;

				case 3:
					DoND.data.currentState = 10;
					DoND.display.setAction('Game over.  Reset to play again.');
					DoND.display.flashReset();
					var summaryString = 'Your winnings this game:<br /><strong>'+DoND.display.formatUSD(DoND.data.winnings)+'</strong><br /><br />';
					if(DoND.data.winnings > DoND.data.highWinnings){
						summaryString += '<strong>This is a new high score for you!</strong>';
						_$('#highscore').setContent(DoND.display.formatUSD(DoND.data.winnings));
						if(DoND.data.cookieJar!==false){
							DoND.data.cookieJar.set('DoND_highWinnings',DoND.data.winnings,8760);
						}
					}
					else{
						if(DoND.data.highWinnings>0){
							summaryString += 'Your high score:<br /><strong>'+DoND.display.formatUSD(DoND.data.highWinnings)+'</strong>';
						}
					}
					DoND.display.openPopInfo(summaryString);
				break;

				case 10:
				break;
			}
		},
		selectCase : function(el){
			elId = parseInt(el.getAttribute('id').match(/[0-9]+$/));
			DoND.data.cases[elId].choose(el);
		},
		caseMeanCalc : function(){
			var sum,qty=DoND.data.remainingValues.length;
			if(qty>0){
				sum = DoND.data.remainingValues.sum();
				var mean = (sum/qty).toFixed(2);
				return mean;
			}
			else{
				throw 'DoND controller object called method caseMeanCalc with no values left--proceding would cause divide by zero.';
			}
		},
		makeBankOffer : function(){
			var multiplier,rounder;
			DoND.data.latestBankOffer = DoND.controller.caseMeanCalc();
			multiplier = (DoND.data.bankOfferDiminisher*DoND.data.currentRound).toFixed(2);
			multiplier = multiplier>1 ? 1 : multiplier;
			DoND.data.latestBankOffer = multiplier<1 ? Math.round(DoND.data.latestBankOffer*multiplier) : DoND.data.latestBankOffer;
			if(DoND.data.latestBankOffer >= 0 && DoND.data.latestBankOffer <=99){
				rounder = 10;
			}
			else if(DoND.data.latestBankOffer >= 100 && DoND.data.latestBankOffer <=9999){
				rounder = 100;
			}
			else{
				rounder = 1000;
			}
			DoND.data.latestBankOffer = (Math.round(DoND.data.latestBankOffer/rounder))*rounder;
			DoND.data.latestBankOffer = DoND.data.latestBankOffer<.5 ? .5 : DoND.data.latestBankOffer;
			DoND.data.highestBankOffer = DoND.data.latestBankOffer>DoND.data.highestBankOffer ? DoND.data.latestBankOffer : DoND.data.highestBankOffer;
			DoND.display.showBankOffer();
		},
		deal : function(){
			var goodDealInfo,compString,millionDollarCaseReveal;
			DoND.display.removeBankOffer();
			DoND.data.currentState = 3;
			DoND.data.winnings = DoND.data.latestBankOffer;
			goodDealInfo = DoND.data.latestBankOffer > DoND.data.playersCase.value ? 'You made a good deal!' : 'You could have done better...';
			compString = DoND.data.winnings < DoND.data.highestBankOffer ? '<br /><br />There were earlier bank offers for more...you should have quit while you were ahead.' : '';
			millionDollarCaseReveal = DoND.data.bmcOpened ? '' : '<br /><br />By the way, the $1,000,000 was in case '+DoND.data.bmc;
			DoND.display.openPopInfo("You've taken the deal for<br /><strong>"+DoND.display.formatUSD(DoND.data.latestBankOffer)+"</strong><br /><br />Your case held<br /><strong>"+DoND.display.formatUSD(DoND.data.playersCase.value)+"</strong><br /><br />"+goodDealInfo+compString+millionDollarCaseReveal);
		},
		noDeal : function(){
			DoND.display.removeBankOffer();
			DoND.display.setAction('Choose '+DoND.data.openNumCasesThisRound+' more case(s) to eliminate.');
			DoND.data.currentState = 1;
		},
		reset : function(){
			window.location = window.location.href;
		},
		init : function(){
			DoND.controller.buildCases();
		}
	},
	setup : function(){
		DoND.data.init();
		DoND.controller.init();
		DoND.display.init();
	},
	init : function(){
		if(!Array.prototype.copy){Array.prototype.copy = function(){return this.concat();}}
		if(!Array.prototype.indexOf){Array.prototype.indexOf = function(value,start){var sPos,i,returnVal=-1;sPos = start || 0;for(i=sPos;i<this.length;i++){if(this[i]===value){returnVal = i;break;}}return returnVal;};}
		if(!Array.prototype.sum){Array.prototype.sum = function(){var i,points,prec=0,sum=0;for(i=0;i<this.length;i++){if(!isNaN(this[i])){points = this[i].toString().split('.');points = points[1]?points.length:0;prec = points>prec?points:prec;sum += parseFloat(this[i]);}}return sum.toFixed(prec);};}
		_$(window).on('load',function(){DoND.setup();});
		_$(window).on('unload',function(){DoND.display.displayRoot.innerHTML = '';DoND = null;});
	}()
}