
/*****************************************************************************
 *
 *  Define the ComputerPlayer Object and Functions
 *
 *****************************************************************************/
function Hand()
{
    this.blue = new Array();
    this.red = new Array();
    this.yellow = new Array();
    this.pink = new Array();
    this.brown = new Array();
    this.green = new Array();
    this.gray = new Array();

    this.wild = new Array();
    this.plus2 = new Array();

    this.hand = new Array();
}

Hand.prototype.getWild = function()
{
    return this.wild;
}

Hand.prototype.getPlus2 = function()
{
    return this.plus2;
}

Hand.prototype.getCards = function()
{
    return this.toList();
}


Hand.prototype.getColorIndex = function(theColor)
{
    for (var i=0; i<this.hand.length; i++)
    {
        if ((this.hand[i] != null) &&
            (this.hand[i].length > 0) &&
            (this.hand[i][0].getColor() == theColor))
        {
            return i;
        }
    }

    assert(false, "Could not locate color " + theColor + " in my hand");
    return -1;
}

Hand.prototype.toList = function()
{
    var list = new Array();
    for (var i=0; i< this.hand.length; i++)
    {
        if (this.hand[i].length > 0)
        {
            for (var j=0; j<this.hand[i].length; j++)
            {
                list.push(this.hand[i][j]);
            }
        }
    }

    for (var i=0; i<this.wild.length; i++)
    {
        list.push(this.wild[i]);
    }

    for (var i=0; i<this.plus2.length; i++)
    {
        list.push(this.plus2[i]);
    }

    return list;
}


Hand.prototype.addRow = function(theRow)
{
    if ((theRow == null) || (theRow.length <= 1))
    {
        return;
    }

    for (var i=1; i<theRow.length; i++)
    {
        this.addCard(theRow[i]);
    }
}

Hand.prototype.scoreRow = function(theRow, theCard)
{
    var prevScore = this.clone().getScore();
    var newHand = this.clone();
    newHand.addRow(theRow);
    if (theCard != null)
    {
        newHand.addCard(theCard);
    }
    return { before: prevScore, after: newHand.getScore(), colorCount: newHand.getColorCount() };
}

Hand.prototype.scoreCard = function(theCard)
{
    var prevScore = this.clone().getScore();
    var newHand = this.clone();
    newHand.addCard(theCard);
    return { before: prevScore, after: newHand.getScore(), colorCount: newHand.getColorCount() };
}



Hand.prototype.addCard = function(theCard)
{
    if (theCard.getColor() == 'wild')
    {
        this.wild.push(theCard);
    }
    else if (theCard.getColor() == 'plus2')
    {
        this.plus2.push(theCard);
    }
    else
    {
        var colorArray = this[theCard.getColor()];

        colorArray.push(theCard);

        // The first card of that color triggers the array to be added to
        // my hand. This approach lets the color order be determined by the
        // cards that arrive in my hand rather than a fixed order (e.g. blue is
        // always 2nd from the left)
        if (colorArray.length == 1)
        {
            this.hand.push(colorArray);
        }
    }
}

Hand.prototype.getColorCount = function(theColor)
{
    var cnt = 0;
    if ((theColor == null) || (theColor == 'blue')) { cnt += (this.blue.length > 0) ? 1 : 0; }
    if ((theColor == null) || (theColor == 'red')) { cnt += (this.red.length > 0) ? 1 : 0; }
    if ((theColor == null) || (theColor == 'yellow')) { cnt += (this.yellow.length > 0) ? 1 : 0; }
    if ((theColor == null) || (theColor == 'gray')) { cnt += (this.gray.length > 0) ? 1 : 0; }
    if ((theColor == null) || (theColor == 'pink')) { cnt += (this.pink.length > 0) ? 1 : 0; }
    if ((theColor == null) || (theColor == 'brown')) { cnt += (this.brown.length > 0) ? 1 : 0; }
    if ((theColor == null) || (theColor == 'green')) { cnt += (this.green.length > 0) ? 1 : 0; }
    return cnt;
}

Hand.prototype.getColorCountWithRow = function(theRow)
{
    var cnt = this.getColorCount();

    for (var i=1; i<theRow.length; i++)
    {
        var color = theRow[i].getColor();
        if (this.getColorCount(theRow[i].getColor()) == 0)
        {
            cnt++;
        }
    }

    return cnt;
}


Hand.prototype.isColorMatch = function(theCard)
{
    return this[theCard.getColor()].length > 0;
}

Hand.prototype.clone = function()
{
    var newHand = new Hand();

    newHand.blue = this.blue.slice();
    newHand.red = this.red.slice();
    newHand.yellow = this.yellow.slice();
    newHand.gray= this.gray.slice();
    newHand.pink = this.pink.slice();
    newHand.brown = this.brown.slice();
    newHand.green = this.green.slice();

    for (var i=0; i<this.hand.length; i++)
    {
        var colorArray = this.hand[i];
        newHand.hand.push(newHand[colorArray[0].getColor()]);
    }

    newHand.wild = this.wild.slice();
    newHand.plus2 = this.plus2.slice();

    return newHand;
}

Hand.prototype.getScore = function()
{
    // put the jokers on the colors with the largest amounts less than 6
    // to maximize points.
    for (var i=0; i<this.wild.length; i++)
    {
        var wildLocation = this.findWildLocation();

        if (wildLocation.largest != -1)
        {
            this.hand[wildLocation.largest].push(this.wild[i]);
        }
        else if (wildLocation.firstAt6 != -1)
        {
            // assign wild (arbitrarily) to first color at 6 or above
            this.hand[wildLocation.firstAt6].push(this.wild[i]);
        }

    }

    // nuke the wilds since assigned to hand
    this.wild = new Array();

    // with wilds assigned, then find the three largest colors
    var copy = this.hand.slice();
    copy.sort(this.sortHand);

    var positivePoints = 0;
    var negativePoints = 0;
    for (var i=0; (i<3 && i<copy.length); i++)
    {
        positivePoints += this.calculatePoints(copy[i]);
    }

    positivePoints += (2 * this.plus2.length);


    if (copy.length > 3)
    {
        for (var i=3; i<copy.length; i++)
        {
            negativePoints += this.calculatePoints(copy[i]);
        }
    }

    return (positivePoints - negativePoints);
}

Hand.prototype.findWildLocation = function()
{
    // find largest less than 6
    var largest = -1;
    var firstAt6 = -1;
    for (var i=0; i<this.hand.length; i++)
    {
        if ((this.hand[i] != null) && (this.hand[i].length < 6))
        {
            if ((largest == -1) ||
                (this.hand[largest].length < this.hand[i].length))
            {
                largest = i;
            }
        }
        else if (this.hand[i].length >= 6)
        {
            firstAt6 = i;
        }
    }

    return { largest: largest, firstAt6: firstAt6 };
}



Hand.prototype.calculatePoints = function(color)
{
    var cnt = 0;

    if (color != null)
    {
        switch (color.length)
        {
            case 0: cnt += 0; break;
            case 1: cnt += 1; break;
            case 2: cnt += 3; break;
            case 3: cnt += 6; break;
            case 4: cnt += 10; break;
            case 5: cnt += 15; break;
            case 6:
            default :
                    cnt += 21;
        }
    }

    return cnt;
}

Hand.prototype.sortHand = function(color1, color2)
{
    if (color1 == null)
    {
        return 1;
    }

    if (color2 == null)
    {
        return -1;
    }

    return color2.length - color1.length;
}


