
function Player( name )
{
    this.name = name;
    this.score = 0;
    this.creator = false;
    this.tr = null;
    this.isActive = true; // set to false if you leave the game (or lag out)
}


Player.ClearAll = function()
{
    whoAmI = null;
    currentPlayer = null;
    
    otherPlayerChatMenu = null;

    Player._playersByName = {};
    Player._players = [];
    
    while (userList.rows.length > 1)
        userList.deleteRow(1);

    while (talkWindow.rows[0].cells.length > 0)
        talkWindow.rows[0].deleteCell();
}
Player._playersByName = {};
Player._players = [];


Player.Exists = function( name )
{
    return (Player._playersByName[name]) ? true : false;
}

Player.Get = function( name )
{
    return Player._playersByName[name];
}

Player.Create = function( name )
{
    var p = Player._playersByName[name];
    if (p)
        debugger;

    p = new Player( name );
    p.inx = Player._players.length;
    Player._playersByName[name] = p;
    Player._players.push(p);
    return p;
}


Player.prototype.Init = function( isCreator )
{
    // First, add player to SCORE CARD
    this.tr = userList.insertRow();
    this.nameTD = this.tr.insertCell();
    this.nameTD.innerHTML = this.name;
    this.scoreTD = this.tr.insertCell();
    this.scoreTD.innerHTML = this.score;
    this.extraTD = this.tr.insertCell();

    // If creator, add a "Start Game" button to SCORE CARD
    if ( isCreator )
    {
        this.created = true;
        if (this === whoAmI)
        {
            this.b = AddNode( this.extraTD, "BUTTON" );
            this.b.innerHTML = "Start Game";
            this.b.onclick = function()
            {
                CallbackBus("startGame", function()
                {
                    Player.StartGame();
                });
            };
        }
    }

    // Then add ChatWindow
    if (this === whoAmI)
    {
        this.nameTD.innerHTML = "<B>"+this.name+"</B>";
    
        this.chatTD = talkWindow.rows[0].insertCell(0); // always first TD in row.
        this.chatTD.id = this.name+"ChatTD";

        AddNode(this.chatTD, "DIV").innerHTML = this.name;

        this.chatWindow = CreateChatWindow( this.chatTD );
        this.chatWindow.id = this.name+"ChatWindow";

        var bufferTD = talkWindow.rows[0].insertCell(1);
        bufferTD.innerHTML = "&nbsp;";
    }
    else
    {
        if (!otherPlayerChatMenu)
            otherPlayerChatMenu = new MenuTabs( [] );

        this.chatTD = talkWindow.rows[0].insertCell();
        this.chatTD.id = this.name+"ChatTD";

        this.chatWindow = CreateChatWindow( this.chatTD );
        this.chatWindow.id = this.name+"ChatWindow";

        this.tab = otherPlayerChatMenu.AddTab({ id: this.chatTD.id, title: this.name });
    }
}

    

var otherPlayerChatMenu;

var currentPlayer;
var whoAmI;

Player.StartGame = function()
{
    var p = Player.Creator();
    if (p === whoAmI)
    {
        p.b.disabled = true;
        p.b.innerHTML = "Game Begun";
    }
    else
        p.extraTD.innerHTML = "Game Has Begun!!!";

    CallbackBus("getScrabbleSet", function(txt)
    {
        var letters = txt.split(/\n/);

        // Init Scrabble Set
        InitScrabbleSet( letters );

        // Fill Tray
        replenishTray();

        p.BeginTurn();
    });
}

Player.Creator = function()
{
    return Player._players[0];
}

Player.prototype.BeginTurn = function()
{
    currentPlayer = this;

    this.tr.style.backgroundColor = "lightsteelblue";
    if (this === whoAmI)
    {
        if ( !InChatMode() )
        {
            trayCell.style.borderWidth = "2px";
            trayCell.style.borderStyle = "dashed";
        }
    }
}


Player.prototype.LoseNextTurn = function()
{
    this.lostNextTurn = true;
}

Player.ActivePlayers = function()
{
    var count = 0;
    for (var inx = 0; inx < Player._players.length; inx++)
        if ( Player._players[inx].isActive )
            count++;
    return count;
}
Player.HighScorer = function()
{
    var maxScore = 0;
    for (var inx = 0; inx < Player._players.length; inx++)
        maxScore = Math.max( maxScore, Player._players[inx].score );

    for (var inx = 0; inx < Player._players.length; inx++)
    {
        var p = Player._players[inx];
        if ( p.score == maxScore )
            return p;
    }

    throw "Ughhhh...";
}


Player.IsMyTurn = function()
{
    return whoAmI != null && currentPlayer === whoAmI;
}

Player.prototype.EndTurn = function()
{
    this.tr.style.backgroundColor = "white";
    if (this === whoAmI)
    {
        trayCell.style.borderWidth = "0px";
    }

    // 	The game ends when...
    
    // (1) one player plays every tile in his rack, and there are no tiles 
	//     remaining in the bag (regardless of the tiles in his opponent's rack) 
    if ( TrayTiles().Count == 0 && Bag.TilesRemaining() )
    {
        GameEnds("Bingo and no tiles left in bag.");
        return;
    }

	// (2) or; when six successive scoreless turns have occurred and at least one word is on the board.
	if ( scorelessTurnCount >= 6 )
	{
        GameEnds(Player.ActivePlayers()+" scoreless turns.");
        return;
	}
	
	// Gabe's rule: if everyone passes, game is over
	if ( passedTurnCount >= Player.ActivePlayers() )
	{
        GameEnds("Everyone passed.");
        return;
	}

    if (this === whoAmI)
        replenishTray();



    // Next Player's Turn
    var maxTries = Player._players.length;
    var tryCount = 0;
    var nextPlayer;
    do
    {
        do
        {
            if ( nextPlayer && nextPlayer.lostNextTurn )
            {
                nextPlayer.ShowMessage( "Lost turn." );
                nextPlayer.lostNextTurn = false;
                currentPlayer = nextPlayer;
            }

            var nextInx = currentPlayer.inx + 1;
            if ( nextInx == Player._players.length )
                nextInx = 0;
            nextPlayer = Player._players[nextInx];
        } while ( nextPlayer.lostNextTurn );
        
        tryCount++;
        if ( tryCount > maxTries )
        {
            alert("Looks like everyone left.  Including yourself!?  Game over.");
            return;
        }
    }
    while ( !nextPlayer.isActive );

    nextPlayer.BeginTurn();
}

Player.prototype.LeftGame = function( reasonTxt )
{
    this.isActive = false;
    this.tr.style.color = "gray";
    this.ShowMessage(reasonTxt);
}


Player.prototype.ShowMessage = function(msg)
{
    this.extraTD.innerHTML = msg;
}


Player.prototype.ScoreDetails = function( isBingo, words )
{
    var play = { user: this.name, isBingo:isBingo, words:words };

    play.totalScore = isBingo?50:0;
    for (var inx = 0; inx < words.length; inx++)
        play.totalScore += words[inx].WordScore;

    return play;
}
Player.prototype.SuccessfulPlay = function( play )
{
    this.score += play.totalScore;
    this.scoreTD.innerHTML = this.score;
    _plays.push( play );
}
    var _plays = [];


function GameEnds(msg)
{
    var popUp = new PopUp({
            width: 500, 
            height: 200, 
            backgroundColor: "#DEEEEF" 
        });
    popUp.SetTitle( "Game Over" );
    popUp.SetPosition( PagePosition.Absolute( 200, 200 ) );
    popUp.SetBody( 
"Winner is <B>"+Player.HighScorer().name+"</B>.  <div id='gameResultsDIV'>Checking all word plays...</div>"
        );
    popUp.Open();

    var request = "";
    for (var inx = 0; inx < _plays.length; inx++)
    {
        var play = _plays[inx];
        
        if ( inx > 0 )
            request+="\n";
        request+=inx; // play #
        request+="\t";
        request+=play.user;
        request+="\t";
        request+=play.isBingo?"Y":"N";
        for (var jnx = 0; jnx < play.words.length; jnx++)
        {
            var w = play.words[jnx];
            request+="\t";
            request+=w.WordText+"^"+w.WordHTML+"^"+w.WordScore;
        }
    }
    CallbackBusEx("recordGameEnd", request, function(rspTxt)
    {
        var gameResultsDIV = $("gameResultsDIV");
        gameResultsDIV.innerHTML = "";
        
        var badWords = rspTxt.split(/\n/);
        var badWordHash = {};
        for (var inx = 0; inx < badWords.length; inx++)
        {
            var badWord = badWords[inx];
            badWordHash[badWord.toUpperCase()] = true;
        }

        var t = AddNode( gameResultsDIV, "TABLE" );
        t.style.marginLeft = "25px";

        var tr = t.insertRow();
        tr.insertCell().innerHTML = "";
        tr.insertCell().innerHTML = "<B>Player</B>";
        tr.insertCell().innerHTML = "<B>Bingo?</B>";
        tr.insertCell().innerHTML = "<B>Score</B>";
        tr.insertCell().innerHTML = "<B>Word(s)</B>";

        for (var inx = 0; inx < _plays.length; inx++)
        {
            var play = _plays[inx];

            var tr = t.insertRow();
            
            tr.insertCell().innerHTML = (inx+1) + "";
            tr.insertCell().innerHTML = play.user;
            tr.insertCell().innerHTML = play.isBingo?"BINGO":"";
            tr.insertCell().innerHTML = play.totalScore+"";

            var subTable = AddNode( tr.insertCell(), "TABLE" );
            for (var jnx = 0; jnx < play.words.length; jnx++)
            {
                var w = play.words[jnx];

                var subTR = subTable.insertRow();
                
                subTR.insertCell().innerHTML = w.WordHTML;
                subTR.insertCell().innerHTML = w.WordScore+"";
                subTR.insertCell().innerHTML = badWordHash[w.WordText.toUpperCase()]?"bad word":"";
            }
            subTable.rows[0].cells[0].style.width = "110px";
            subTable.rows[0].cells[1].style.width = "20px";
        }

    });
}
