/**
 * Copyright (c) http://www.php-etc.com
 * Anyone is allowed to use, copy, distribute and/or modify the source code in this file, as long as this copyright notice is retained.
 */

/**
 * Represents a 'card' object
 *
 * @param int cardNumericValue - a number between 0 and 51 (for 52 different cards)
 */
function Card (cardNumericValue)
{
    // Some constants to define all cards
    var SUIT = ["d", "c", "h", "s"];
    var NUMBERS = ["a", "2", "3", "4", "5", "6", "7", "8", "9", "t" , "j", "q", "k"];

	/**
	 * Card numeric value mapping:
	 * 0 - 12 = Ace of Diamonds to King of Diamonds
	 * 13 - 25 = Ace of Clubs to King of Clubs
	 * 26 - 38 = Ace of Hearts to King of Hearts
	 * 39 - 51 = Ace of Spades to King of Spades
	 */
    this.number = NUMBERS[(cardNumericValue % 13)];
    this.suit = SUIT[(Math.floor(cardNumericValue / 13))];
    this.toString = function ()
    {
        return this.number + this.suit;
    }

	// Get the image object for this card
    this.getImage = function ()
    {
        var img = document.createElement("IMG");
        img.setAttribute("src", "/images/cards/"+this.toString()+".gif");
        img.setAttribute("alt", this.toString());
        return img;
    }
}

// Represents one blackjack player (either a 'dealer' or a 'player')
function Player ()
{
    this.cards = new Array();
    this.isBusted = false;
    this.isBlackjack = false;
    this.minCount = 0;
    this.maxCount = 0;

    this.cardDisplayArea = null;
    this.numberDisplayArea = null;

	// Add a new card to the player's hand
    this.addCard = function (newCard)
    {
        this.cards[this.cards.length] = newCard;

        var cardImg = newCard.getImage();
        this.cardDisplayArea.appendChild(cardImg);

        this.countCard();
        this.numberDisplayArea.firstChild.data = (this.minCount == this.maxCount) ? this.minCount : this.minCount + " / " + this.maxCount;
    }

	// Get the highest count of the current hand (e.g.: if there is an Ace it would be counted as 11 instead of 1)
    this.getBestCount = function ()
    {
        return (this.maxCount <= 21) ? this.maxCount : this.minCount;
    }

	// Find the count of the current hand
    this.countCard = function ()
    {
        var foundAce = false;
        this.minCount = 0;
        this.maxCount = 0;
        for (var i=0; i<this.cards.length; i++)
        {
            var num = this.cards[i].number;
            switch (num)
            {
                case "t": // fall-thru
                case "j": // fall-thru
                case "q": // fall-thru
                case "k":
                    num = 10;
                    break;
                case "a":
                    num = 1;
                    break;
                default:
                    break;
            }
            this.minCount += parseInt(num);
            this.maxCount += parseInt(num);
            if (num == 1 && !foundAce)
            {
                this.maxCount += 10;
                foundAce = true;
            }
        }
        // Blackjack!
        if (this.maxCount == 21 && this.cards.length == 2)
        {
            this.isBlackjack = true;
        }
        // Busted
        else if (this.minCount > 21)
        {
            this.isBusted = true;
        }
        else if (this.maxCount > 21)
        {
            this.maxCount = this.minCount;
        }
    }
}


// Main logic of the game
function Blackjack ()
{
	// Deal a new game
    this.deal = function ()
    {
		// Player
        this.player = new Player();
        this.player.cardDisplayArea = document.getElementById("tblP");
        this.player.numberDisplayArea = document.getElementById("sumP");

		// Dealer
        this.dealer = new Player();
        this.dealer.cardDisplayArea = document.getElementById("tblD");
        this.dealer.numberDisplayArea = document.getElementById("sumD");

		// Clear the table from previous game
        while (document.getElementById('tblD').firstChild)
            document.getElementById('tblD').removeChild(document.getElementById('tblD').firstChild);
        document.getElementById('sumD').firstChild.data = 0;
        while (document.getElementById('tblP').firstChild)
            document.getElementById('tblP').removeChild(document.getElementById('tblP').firstChild);
        document.getElementById('sumP').firstChild.data = 0;

		// 2 cards for player, 1 card for dealer
        this.playerHit();
        this.dealerHit();
        this.playerHit();
    }

	// Player wants to hit another card
    this.playerHit = function ()
    {
        var newCard = this.drawCard();
        this.player.addCard(newCard);

        if (this.player.isBlackjack)
        {
            this.playerWin();
        }
        else if (this.player.isBusted)
        {
            this.playerLose();
        }
    }

	// Dealer hits another card
    this.dealerHit = function ()
    {
        var newCard = this.drawCard();
        this.dealer.addCard(newCard);
    }

	// Player stands
    this.stand = function ()
    {
        if (this.dealer.isBlackjack)
        {
            this.playerLose();
        }
        else if (this.dealer.isBusted)
        {
            this.playerWin();
        }
        else if (this.dealer.getBestCount() < 17)
        {
            var newCard = this.drawCard();
            this.dealer.addCard(newCard);
            setTimeout("game.stand()", 250);
        }
        else if (this.dealer.getBestCount() < this.player.getBestCount())
        {
            this.playerWin();
        }
        else if (this.dealer.getBestCount() > this.player.getBestCount())
        {
            this.playerLose();
        }
        else
        {
            this.push();
        }
    }

	// Gets a random card
    this.drawCard = function ()
    {
        do
        {
            var card = new Card(Math.floor(Math.random()*52));
        } while (this.cardIsDrawn(card));
        return card;
    }

	// Check if a card is already displayed on the table
    this.cardIsDrawn = function (card)
    {
        var allDrawnCards = this.player.cards.concat(this.dealer.cards);
        for (var i=0; i<allDrawnCards; i++)
        {
            if (allDrawnCards[i].toString() == card.toString())
            {
                return true;
            }
        }
        return false;
    }

	// Handles 'player lose' event
    this.playerLose = function ()
    {
        alert("You lose!");
        this.deal();
    }

	// Handles 'player win' event
    this.playerWin = function ()
    {
        alert("You win!");
        this.deal();
    }

	// Handles 'push' event
    this.push = function ()
    {
        alert("Push!");
        this.deal();
    }
}


var game;
function init ()
{
    game = new Blackjack();
    game.deal();
}
window.onload = init;
