//
// Global state
//
var game_state = k_game_state_ready;

var card_image_map = new Array(
	'cards/card_1.gif',
	'cards/card_2.gif',
	'cards/card_3.gif',
	'cards/card_4.gif',
	'cards/card_5.gif',
	'cards/card_6.gif',
	'cards/card_7.gif',
	'cards/card_8.gif',
	'cards/card_9.gif',
	'cards/card_10.gif'
	);

var card_back_image = 'cards/card_back.gif';

var deck = null;

// hands[0] belongs to the dealer. The rest belong to the player.
var hands = null;
var current_hand = 0;

var player_purse = 25;
var initial_wager = null;

var game_finished = false;


//
// Constants
//

// Game states
var k_game_state_ready = 0;
var k_game_state_player = 1;
var k_game_state_dealer = 2;


// BJHand object

function BJHand_hand_value()
{
	var soft_aces_used = 0;
	var total = 0;

	// Total the cards, counting aces as 11 for now
	for(i = 0; i < this.cards.length; i++)
		{
		if(this.cards[i] == 1)
			{
			total += 11;
			soft_aces_used++;
			}
		else
			total += this.cards[i];
		}

	// Try to harden aces to get us back under 22. If the caller asked for the
	// hard value, harden all aces.
	while(total > 21 && soft_aces_used > 0)
		{
		total -= 10;
		soft_aces_used--;
		}

	return total;
}


function BJHand_blackjack()
{
	// No blackjacks after a split
	if(this.split)
		return false;

	return(this.hand_value() == 21 && this.cards.length == 2);
}


function BJHand_bust()
{
	return (this.hand_value() > 21);
}


function BJHand_can_double()
{
	if(this.cards.length > 2)
		return false;

	hard_value = this.hand_value();

	if(hard_value == 10 || hard_value == 11)
		return true;
	else
		return false;
}


function BJHand_can_split()
{
	if(this.cards.length != 2)
		return false;

	if(this.cards[0] == this.cards[1])
		return true;
	else
		return false;
}


function BJHand()
{
	this.cards = new Array();
	this.obscured = false;
	this.double_down = false;
	this.split = false;
	this.wager = initial_wager;
	this.profit = null;

	this.hand_value = BJHand_hand_value;
	this.blackjack = BJHand_blackjack;
	this.bust = BJHand_bust;
	this.can_double = BJHand_can_double;
	this.can_split = BJHand_can_split;
}



function bj_init_deck()
{
	deck = new Array();

	// Add four of each value, one through nine
	for(i = 1; i <= 9; i++)
		deck.push(i, i, i, i);

	// Add sixteen tens
	for(i = 0; i < 16; i++)
		deck.push(10);

	shuffle_array(deck);

	// Rig the deck (for testing)
	rig_string = document.getElementById('bj_rig_deck').value;
	rig_values = rig_string.split(/ +/);
	for(i = rig_values.length - 1; i >= 0; i--)
		{
		rig_value = rig_values[i];
		if(rig_value.match(/^\d+$/))
			{
			rig_value = rig_value - 0;
			if(rig_value > 0 && rig_value <= 10)
				deck.push(rig_value);
			}
		}
}


function bj_deal_card(hand_index)
{
	hands[hand_index].cards.push(deck.pop());
}


function bj_init_hands()
{
	hands = new Array(new BJHand(), new BJHand());
	hands[0].obscured = true;
}


function bj_split_hand(hand_no)
{
	new_hand = new BJHand();
	new_hand.split = true;
	hands[hand_no].split = true;

	hands.splice(hand_no + 1, 0, new_hand);
	hands[hand_no + 1].cards.push(hands[hand_no].cards.pop());
}


function bj_play_dealer()
{
	game_state = k_game_state_ready;
	
	// If any player hand is not a bust, play the dealer
	for(hand_i = 1; hand_i < hands.length; hand_i++)
		{
		if(!hands[hand_i].bust())
			game_state = k_game_state_dealer;
		}

	// If the player got a blackjack, we don't need to play the dealer, but
	// we do need to reveal the dealer's hand.
	if(game_state == k_game_state_dealer && hands[1].blackjack())
		{
		hands[0].obscured = false;
		game_state = k_game_state_ready;
		}

	// If we still think the dealer needs to play, have at it.
	if(game_state == k_game_state_dealer)
		bj_play_dealer_cards_slowly();
	else
		bj_end_hand();
}


function bj_play_dealer_cards_slowly()
{
	if(hands[0].obscured)
		hands[0].obscured = false;
	else if(hands[0].hand_value() < 17)
		bj_deal_card(0);

	if(hands[0].hand_value() < 17)
		setTimeout("bj_play_dealer_cards_slowly()", 1000);
	else
		{
		// We're done with this hand.
		game_state = k_game_state_ready;
		bj_end_hand();
		}

	bj_update_ui();
}


function bj_update_game_state()
{
	while(game_state == k_game_state_player && hands[current_hand].hand_value() >= 21)
		{
		bj_next_hand();
		}

	if(game_state == k_game_state_dealer)
		{
		bj_play_dealer();
		}

	bj_update_ui();
}


function bj_next_hand()
{
	current_hand++;

	if(current_hand >= hands.length)
		{
		current_hand = 0;
		game_state = k_game_state_dealer;
		}
	else
		{
		// Deal the next hand up to two cards (in case it came from a split)
		while(hands[current_hand].cards.length < 2)
			bj_deal_card(current_hand);
		}
}


function bj_update_ui()
{
	bj_update_display_2();
	bj_update_button_state();
}


function bj_update_button_state()
{
	buttons_to_show = {bj_deal: false, bj_hit: false, bj_stand: false, bj_double: false, bj_split: false};


	if(game_state == k_game_state_ready)
		{
		buttons_to_show.bj_deal = true;
		}
	else if(game_state == k_game_state_player)
		{
		buttons_to_show.bj_hit = true;
		buttons_to_show.bj_stand = true;
		buttons_to_show.bj_double = hands[current_hand].can_double();
		buttons_to_show.bj_split = hands[current_hand].can_split();
		}

	for(button_name in buttons_to_show)
		{
		button_obj = document.getElementById(button_name);
		
		if(buttons_to_show[button_name])
			button_obj.disabled = false;
//			button_obj.style.display = 'inline';
		else
			button_obj.disabled = true;
//			button_obj.style.display = 'none';
		}
}


function bj_make_text_element(tag_name, tag_content)
{
	text_obj = document.createTextNode(tag_content);
	new_element = document.createElement(tag_name);
	new_element.appendChild(text_obj);

	return new_element;
}


function bj_update_display_2()
{
	card_table = document.getElementById('bj_card_table').tBodies[0];

	// Remove all rows
	while(card_table.hasChildNodes())
		card_table.removeChild(card_table.childNodes[0]);

	dealer_hand = hands[0];
	dealer_value = dealer_hand.hand_value();

	
	// Find the largest hand. This will determine the width of the table.
	cards_max = 0;

	for(hand_i = 0; hand_i < hands.length; hand_i++)
		{
		if(hands[hand_i].cards.length > cards_max)
			cards_max = hands[hand_i].cards.length;
		}
	
	// Add the header row
	tr_obj = document.createElement('tr');
	
	th_obj = bj_make_text_element('th', 'Player');
	th_obj.style.borderBottom = 'solid thin';
	tr_obj.appendChild(th_obj);
	
	th_obj = bj_make_text_element('th', 'Cards');
	th_obj.colSpan = cards_max;
	th_obj.style.borderBottom = 'solid thin';
	tr_obj.appendChild(th_obj);
	
	th_obj = bj_make_text_element('th', 'Message');
	th_obj.style.borderBottom = 'solid thin';
	tr_obj.appendChild(th_obj);
	
	th_obj = bj_make_text_element('th', game_finished ? 'Payout' : 'Bet');
	th_obj.style.borderBottom = 'solid thin';
	tr_obj.appendChild(th_obj);
	
	card_table.appendChild(tr_obj);
	
	// Add a row for each hand
	for(hand_i = 0; hand_i < hands.length; hand_i++)
		{
		hand = hands[hand_i];
		hand_value = hand.hand_value();

		if(hand_i == 0)
			player_name = 'Dealer:';
		else
			player_name = 'You:';

		tr_obj = document.createElement('tr');

		// Add the header
		th_obj = bj_make_text_element('th', player_name);
		th_obj.align = 'right';
		th_obj.style.paddingRight = '5px';
		if(hand_i == current_hand && !game_finished)
			{
			th_obj.style.backgroundColor = '#CCC';
			}

		tr_obj.appendChild(th_obj);

		// Add the cards
		obfuscate = document.getElementById('bj_obfuscate').checked;
		for(card_i = 0; card_i < hand.cards.length; card_i++)
			{
			card_num = hand.cards[card_i];
			
			if(obfuscate)
				{
				img_obj = document.createElement('img');
				if(hand.obscured && card_i > 0)
					img_obj.src = card_back_image;
				else
					img_obj.src = card_image_map[card_num - 1];
				td_obj = document.createElement('td');
				td_obj.appendChild(img_obj);
				}
			else
				{
				if(hand.obscured && card_i > 0)
					card_num = 'X';
				else
					{
					if(card_num == 1)
						card_num = 'A';
					}

				td_obj = bj_make_text_element('td', card_num);
				}

			tr_obj.appendChild(td_obj);
			}
			
		// Add empty table cells to line up with hands having more cards
		for(card_i = hand.cards.length; card_i < cards_max; card_i++)
			{
			td_obj = document.createElement('td');
			tr_obj.appendChild(td_obj);
			}
		
		hand_messages = new Array();
		
		// Add a message
		if(!hand.obscured)
			{
			hand_message = '';
			if(hand.blackjack())
				hand_messages.push('Blackjack');
			else if(hand_value == 21 && hand_i > 0)
				hand_messages.push('21');
			else if(hand_value > 21)
				hand_messages.push('Bust');
			}
		
		// Append win/lose messages if we're done
		if(game_finished && hand_i > 0)
			{
			if(hand.bust())
				;
			else if(hand.blackjack())
				;
			else if(dealer_hand.bust())
				;
//			else if(dealer_hand.blackjack())
//				;
			else if(hand_value > dealer_value)
				hand_messages.push('You win');
			else if(hand_value < dealer_value)
				hand_messages.push('Dealer wins');
			else if(hand_value == dealer_value)
				hand_messages.push('Push');
			else
				hand_messages.push('Uh oh');	// Really shouldn't get here
			}

		td_obj = document.createElement('td');
		
		if(hand_messages.length > 0)
			td_obj.appendChild(document.createTextNode(hand_messages[0]));
		
		for(i = 1; i < hand_messages.length; i++)
			{
			td_obj.appendChild(document.createElement('br'));
			td_obj.appendChild(document.createTextNode(hand_messages[i]));
			}
		
		td_obj.align = 'center';
		td_obj.style.color = 'blue';
		td_obj.style.whiteSpace = 'nowrap';

		tr_obj.appendChild(td_obj);


		// Append Bet/Profit
		if(hand_i > 0)
			{
			if(game_finished)
				{
				pl_text = '';
				if(hand.profit < 0)
					pl_text += '-';
				else if(hand.profit > 0)
					pl_text += '+';
				pl_text += '$' + Math.abs(hand.profit);
	
				td_obj = bj_make_text_element('td', pl_text);
				if(hand.profit < 0)
					td_obj.style.color = 'red';
				else
					td_obj.style.color = 'green';
				}
			else
				{
				td_obj = bj_make_text_element('td', '$' + hand.wager);
				}
			}
		else
			td_obj = document.createElement('td');

		td_obj.align = 'center';
		tr_obj.appendChild(td_obj);


		card_table.appendChild(tr_obj);
		}

	purse_cell = document.getElementById('bj_purse');
	purse_cell.childNodes[0].data = 'Purse: $' + player_purse;
}


/*
function bj_update_display_1()
{
	card_table = document.getElementById('bj_card_table').tBodies[0];

	// Remove all rows
	while(card_table.hasChildNodes())
		card_table.removeChild(card_table.childNodes[0]);

	dealer_hand = hands[0];
	dealer_value = dealer_hand.hand_value();

	// Add a row for each hand
	for(hand_i = 0; hand_i < hands.length; hand_i++)
		{
		hand = hands[hand_i];
		hand_value = hand.hand_value();

		if(hand_i == 0)
			player_name = 'Dealer:';
		else
			player_name = 'You:';

		tr_obj = document.createElement('tr');

		// Add the header
		th_obj = bj_make_text_element('th', player_name);
		th_obj.align = 'right';
		if(hand_i == current_hand && !game_finished)
			{
			th_obj.style.backgroundColor = '#CCC';
			}

		tr_obj.appendChild(th_obj);

		// Add the cards
		obfuscate = document.getElementById('bj_obfuscate').checked;
		for(card_i = 0; card_i < hand.cards.length; card_i++)
			{
			card_num = hand.cards[card_i];
			
			if(obfuscate)
				{
				img_obj = document.createElement('img');
				if(hand.obscured && card_i > 0)
					img_obj.src = card_back_image;
				else
					img_obj.src = card_image_map[card_num - 1];
				td_obj = document.createElement('td');
				td_obj.appendChild(img_obj);
				}
			else
				{
				if(hand.obscured && card_i > 0)
					card_num = 'X';
				else
					{
					if(card_num == 1)
						card_num = 'A';
					}

				td_obj = bj_make_text_element('td', card_num);
				}

			tr_obj.appendChild(td_obj);
			}
		
		// Mark doubles
		if(hand.double_down)
			{
			td_obj = bj_make_text_element('td', 'double');
			td_obj.style.color = 'blue';
			tr_obj.appendChild(td_obj);
			}
		
		// Add a message
		if(!hand.obscured)
			{
			hand_message = '';
			if(hand.blackjack())
				hand_message = 'Blackjack';
			else if(hand_value == 21 && hand_i > 0)
				hand_message = '21';
			else if(hand_value > 21)
				hand_message = 'Bust';
		
			td_obj = bj_make_text_element('td', hand_message);
			td_obj.style.color = 'blue';
			tr_obj.appendChild(td_obj);
			}
		
		// Append win/lose messages if we're done
		if(game_finished && hand_i > 0)
			{
			final_message = '';

			if(hand.bust())
				final_messsage = '';
			else if(hand.blackjack())
				final_message = '';
			else if(dealer_hand.bust())
				final_message = '';
//			else if(dealer_hand.blackjack())
//				final_message = '';
			else if(hand_value > dealer_value)
				final_message = 'You win';
			else if(hand_value < dealer_value)
				final_message = 'Dealer wins';
			else if(hand_value == dealer_value)
				final_message = 'Push';
			else
				final_message = 'Uh oh';	// Really shouldn't get here

			td_obj = bj_make_text_element('td', final_message);
			td_obj.style.color = 'blue';
			tr_obj.appendChild(td_obj);
			
			// Append P&L
			pl_text = '';
			if(hand.profit < 0)
				pl_text += '-';
			else if(hand.profit > 0)
				pl_text += '+';
			pl_text += '$' + Math.abs(hand.profit);

			td_obj = bj_make_text_element('td', pl_text);
			if(hand.profit < 0)
				td_obj.style.color = 'red';
			else
				td_obj.style.color = 'green';
			tr_obj.appendChild(td_obj);
			}

		card_table.appendChild(tr_obj);
		}

	purse_cell = document.getElementById('bj_purse');
	purse_cell.childNodes[0].data = 'Purse: $' + player_purse;
}
*/


function bj_begin_hand()
{
	game_finished = false;

	wager_obj = document.getElementById('bj_wager');
	wager_obj.disabled = true;
	initial_wager = wager_obj.value - 0;
}


function bj_end_hand()
{
	game_finished = true;
	bj_settle_accounts();
	document.getElementById('bj_wager').disabled = false;
}


function bj_settle_accounts()
{
	dealer_value = hands[0].hand_value();

	for(hand_i = 1; hand_i < hands.length; hand_i++)
		{
		hand = hands[hand_i];
		hand_value = hand.hand_value();

		if(hand.bust())
			hand.profit = -hand.wager;
		else if(hand.blackjack() /* && !hands[0].blackjack() */)
			hand.profit = hand.wager * 2;
		else if(hands[0].bust())
			hand.profit = hand.wager;
//		else if(hands[0].blackjack() && !hands[1].blackjack())
//			hand.profit = -hand.wager;
		else if(hand_value >= dealer_value)
			hand.profit = hand.wager;
		else if(dealer_value > hand_value)
			hand.profit = -hand.wager;
		
		player_purse += hand.profit;
		}
}


function bj_validate_wager()
{
	wager_input = document.getElementById('bj_wager');
 	wager_value = wager_input.value;

	matches = wager_value.match(/(\d+)/)
	if(matches != null)
		wager_value = matches[1] - 0;
	else
		wager_value = 1;

	if(wager_value < 1)
		wager_value = 1;
	else if(wager_value > 5)
		wager_value = 5;

	wager_input.value = wager_value;
}


function bj_deal()
{
	game_state = k_game_state_player;
	bj_begin_hand();

	bj_init_deck();
	bj_init_hands();

	bj_deal_card(1);
	bj_deal_card(0);
	bj_deal_card(1);
	bj_deal_card(0);

	current_hand = 1;

	bj_update_game_state();
}


function bj_hit()
{
	bj_deal_card(current_hand);
	bj_update_game_state();
}


function bj_stand()
{
	bj_next_hand();
	bj_update_game_state();
}


function bj_double()
{
	hands[current_hand].double_down = true;
	hands[current_hand].wager *= 2;
	bj_deal_card(current_hand);
	bj_next_hand();
	bj_update_game_state();
}


function bj_split()
{
	bj_split_hand(current_hand);
	bj_deal_card(current_hand);
//	bj_deal_card(current_hand + 1);
	bj_update_game_state();
}


function bj_obfuscation_changed()
{
	bj_update_ui();
}


function bj_generate_solution()
{
	card_names = new Array('Ace', 'Two', 'Three', 'Four', 'Five', 'Six', 'Seven', 'Eight', 'Nine', 'Ten');

	solution_table = document.getElementById('bj_card_image_map').tBodies[0];
	
	while(solution_table.hasChildNodes())
		solution_table.removeChild(solution_table.childNodes[0]);

	for(row_num = 0; row_num <= 1; row_num++)
		{
		tr_obj = document.createElement('tr');
		
		for(i = 0 + (5 * row_num); i < 5 + (5 * row_num); i++)
			{
			td_obj = document.createElement('td');

			img_obj = document.createElement('img');
			img_obj.src = card_image_map[i];
			
			br_obj = document.createElement('br');
			
			text_obj = document.createTextNode(card_names[i]);
			
			td_obj.appendChild(img_obj);
			td_obj.appendChild(br_obj);
			td_obj.appendChild(text_obj);
			
			tr_obj.appendChild(td_obj);
			}

		solution_table.appendChild(tr_obj);
		}
}


// Initialize the puzzle. Shuffle the mapping of card values to images and
// generate the solution part of the page.
function bj_initialize()
{
	shuffle_array(card_image_map);
	bj_generate_solution();
}
