// Weewar Profiler
// Version 0.4
// Updated 2009-04-20, by spadequack
//
// Original script by faman. http://userscripts.org/scripts/show/24555 
//
// Based on Weewar Spy by Pluto:
//   http://userscripts.org/scripts/show/13619
//
// v0.2: Reworked logic to call all APIs and populate table from GM_xmlhttpRequest 
//       calls instead of using a timer.   Also added map thumbnails and the
//       ability to work with test server profiles.
//
// v0.3: Updated to work with changes to Map page HTML.  Also added online
//       status indicator for current player.
//
// v0.4: Updated to work with new API changes.

// ==UserScript==
// @name Weewar Profiler
// @description Adds a table of information about a player's current games to his/her user profile page
// @namespace userscripts.org
// @include http://*weewar.com/user/*
// ==/UserScript==

var http_requests = new Array();

function loadXMLHttpRequest() {
  http_request = false;
  if (window.XMLHttpRequest) { // Mozilla, Safari,...
	 http_request = new XMLHttpRequest();
  } else if (window.ActiveXObject) { // IE
	 try {
		http_request = new ActiveXObject("Msxml2.XMLHTTP");
	 } catch (e) {
		try {
		   http_request = new ActiveXObject("Microsoft.XMLHTTP");
		} catch (e) {}
	 }
  }
  if (!http_request) {
	 alert('Cannot create XMLHTTP instance');
	 return false;
  }
  var index = http_requests.length;
  http_requests[index] = http_request;
  return index;
}

// ============================================================================
// Global Variables
// ============================================================================
//   Lists
var gameNums = new Array();       // List of the game numbers
var gameLinks = new Array();      // List of links to games
var gameTags = new Array();       // List of tags for games in table
var gameRows = new Array();       // List of table row elements
var mapNums = new Array();        // List of map numbers for each game
var currentPlayers = new Array(); // List of current player for each game

var username;

// ============================================================================
// Main Program
// ============================================================================
// parse the player name from the window URL (works from any profile tab)
var URL = window.location.href;

// Check to see if profile is from test server, if so use test server apis
var weewarURL = "http://weewar.com";
xpath = new RegExp("http://test.weewar.com");
if ( URL.match(xpath) )
{
    weewarURL = "http://test.weewar.com";
}


// ----------------------------
//   Initialize the table
// ----------------------------


var secondNode;
var currentTableElement;
function doAll() {

secondNode = document.getElementById('openGames');

if ( secondNode )
{

    // Create a new element that will contain a table of all current games
    // re-using the 'openGames' style from the game list page
    var currentGameList = document.createElement('div');
    currentGameList.setAttribute('id', 'openGames');
    secondNode.parentNode.replaceChild(currentGameList, secondNode);

    // Add javascript to show map preview on mouseover
    var mouseoverJavascript = document.createElement('script');
    currentGameList.appendChild(mouseoverJavascript);
    mouseoverJavascript.setAttribute('type', 'text/javascript');
    mouseoverJavascript.innerHTML = '<!--\n' + 
        'var currentPreview=null;\n' +
        'var currentPreviewTimeout=null;\n' +
        'function countdownPreview( id )\n' +
        '{\n' +
        '    //alert( "Showing "+id );\n' +
        '    if( currentPreviewTimeout==null )\n' +
        '    {\n' +
        '        currentPreview=$(id);\n' +
        '        //currentPreviewTimeout = setTimeout( "showPreview()", 1000 );\n' +
        '        Element.show( currentPreview );\n' +
        '    }\n' +
        '}\n' +
        'function showPreview(  )\n' +
        '{\n' +
        '    //alert( "Showing "+ele );\n' +
        '    if( currentPreview!=null )\n' +
        '    {\n' +
        '        Element.show( currentPreview );\n' +
        '    }\n' +
        '}\n' +
        'function hidePreview()\n' +
        '{\n' +
        '    if( currentPreview!=null )\n' +
        '    {\n' +
        '        //alert( "hiding" );\n' +
        '        Element.hide( currentPreview );\n' +
        '        window.clearTimeout( currentPreviewTimeout );\n' +
        '        currentPreview = null;\n' +
        '        currentPreviewTimeout=null;\n' +
        '    }\n' +
        '} \n' +
        '//-->';

    // This is the title of the table
    var currentGameTitle = '<td id="currentGameTitle" colspan="5" ' +
        'style="background-color: #FFFFBB; ' +
        'text-align: center; color: #666;">' +
        '<font style="font-weight: bold; font-size: large">' +
        'Current Games</font></td>';

    // Table of current games is created in HTML and will be inserted into
    // the currentGameList div element once complete
    var tableHtml = 
        '<table id="currentGameTable" cellpadding="0" cellspacing="0">\n' +
        '  <thead>\n' +
        '    <tr>\n' + currentGameTitle + '\n    </tr>\n' +
        '    <tr>\n' +
	'      <th>Select</th>\n' +
	'      <th>ID</th>\n'+
        '      <th>Name</th>\n' +
        '      <th>Map</th>\n' +
        '      <th>Current Player</th>\n' +
        '    </tr>\n' +
        '  </thead>\n' +
        '</table>';

    // Rows for the table have been created.  Insert into currentGameList table
    currentGameList.innerHTML = tableHtml;

    // Get a reference to the table element so rows can be added
    var tableElements = currentGameList.getElementsByTagName('table');
    for ( var i = 0; i < tableElements.length; i++ )
    {
        // find the td element that we inserted with an id of 'currentGameTitle'
        if ( tableElements[i].getAttribute('id') == 'currentGameTable');
        {
            currentTableElement  = tableElements[i];
        }
    }
}
}

//--------------------------------
//  Call APIs and populate table
//--------------------------------
// Everything is run from within this GM_xmlhttpRequest call.  This is done 
// because the call is asynchronous and we need to make sure we have all of the
// data loaded before creating the table

function getHq(formObj) {
	doAll();
	username = formObj.childNodes[1].value;
	var params = "?method=user&username=" + username;
	var httpReqIndex = loadXMLHttpRequest();
  	http_requests[httpReqIndex].onreadystatechange = function() { return loadHq(httpReqIndex); };
  	http_requests[httpReqIndex].open('GET', "callweewarapi.php" + params, true);
  	http_requests[httpReqIndex].send(null);
}

function loadHq(httpReqIndex) {
	if (http_requests[httpReqIndex].readyState==4) {
	
	// gotta trim starting newline
	//alert(http_request.responseText.substring(1));
        var parser = new DOMParser();
        var dom = parser.parseFromString(http_requests[httpReqIndex].responseText.substring(1),"application/xml");
        //grab the game element that lists all the game numbers
        var theirGames = dom.getElementsByTagName('game');  

	

        //loop through the game element to fill up the gameNums array
        for (var i = 0; i < theirGames.length; i++)
        {
            // Store the game number and game link
            gameNums[i] = theirGames[i].textContent;
            gameLinks[i] = weewarURL + '/game/' + gameNums[i]; 

            // Determine if row is even or odd
            var trClass = 'even';
            if ( (i % 2) == 0 )
            {
                trClass = 'odd';
            }

            // Create a row and add to the table
            var gameRowElement = document.createElement('tr');
            gameRowElement.setAttribute('class', trClass);
            currentTableElement.appendChild(gameRowElement);
            gameRows[i] = gameRowElement;

            // Load the info for this game
            genGameRow(gameNums[i], i);	   
        }
    }
}

// ============================================================================
//  Functions
// ============================================================================

// Populates the row in the game table.
// Get the map number from the game api and then access the map web page to 
// load the map info
function genGameRow(gameNum, listNum)
{
	var params = "?method=game&gameId=" + gameNum;
	var httpReqIndex = loadXMLHttpRequest();
  	http_requests[httpReqIndex].onreadystatechange = function() { return loadGameRow(httpReqIndex, gameNum, listNum); 
};
  	http_requests[httpReqIndex].open('GET', "callweewarapi.php" + params, true);
  	http_requests[httpReqIndex].send(null);
}

function loadGameRow(httpReqIndex, gameNum, listNum) {
	if (http_requests[httpReqIndex].readyState==4) {
            // Create columns for this row
	    var selectCol = document.createElement('td');
	    var gameNumCol = document.createElement('td');
            var gameNameCol = document.createElement('td');
            var mapNameCol = document.createElement('td');
            var playerCol = document.createElement('td');
            gameRows[listNum].appendChild(selectCol);
 	    gameRows[listNum].appendChild(gameNumCol);
            gameRows[listNum].appendChild(gameNameCol);
            gameRows[listNum].appendChild(mapNameCol);
            gameRows[listNum].appendChild(playerCol);

            // Parse HTML response
            var parser = new DOMParser();
            var dom = parser.parseFromString(http_requests[httpReqIndex].responseText.substring(1),"application/xml");

            // ------------------------------
            // First Column: Game Name + Link
            // ------------------------------
    
            // pull out the game name and update column
            var gameName = gameNum;
            if(dom.getElementsByTagName('name')[0])
            {
                gameName = dom.getElementsByTagName('name')[0].textContent; 
            }

            // assemble the link to the game with gamename and mapname on the link
            gameTags[listNum] = '<a href="' + weewarURL + '/game/' + gameNum + 
                '">' + gameName + '</a>';

	    gameNumCol.innerHTML =  '<a href="' + weewarURL + '/game/' + gameNum +
                '">' + gameNum + '</a>';
            gameNameCol.innerHTML = gameTags[listNum];

	    // select col
	    selectCol.innerHTML = '<input type="radio" name="gameSelect" value="' + gameNum + 
		'" onchange="updateSelectedGame(' + listNum + ');" />'

            // ------------------------------
            // Second Column: Map Name + Link
            // ------------------------------
    
            // Pull out the map number, use it to load map info page
            var mapNum;
            if(dom.getElementsByTagName('map')[0])
            {
                mapNum = dom.getElementsByTagName('map')[0].textContent;
                mapNums[listNum] = mapNum;

                // Load the map name and link
                getMapLinks(mapNum, listNum, mapNameCol);
            }
            
            // ------------------------------------------
            // Third Column: Current Player / Game Status
            // ------------------------------------------

            // find out if game is finished
            var gameState = (dom.getElementsByTagName('state'))[0].textContent;
    
            // find out who's turn it is
            var players = dom.getElementsByTagName('player');
            var winner;
            var drawers = new Array();
            var numDraw = 0;
            for (var i = 0; i < players.length; i++)
            {
                if ( gameState == "running" && players[i].getAttribute('current') )
                {
                    currentPlayers[listNum] = players[i].textContent;
                }
                else if ( gameState == "finished" && 
                          players[i].getAttribute('result') == 'victory' )
                {
                    winner = players[i].textContent;
                }
                else if ( gameState == "finished" && 
                          players[i].getAttribute('result') == 'draw' )
                {
                    drawers[numDraw++] = players[i].textContent;
                }
            }

            // Display the current player or the winner if the game is over.
            var currentPlayerCol = '';
            if ( winner )
            {
                // If user lost display the winner's name in red.  If user won 
                // display their name in green
                if ( winner == username )
                {
                    currentPlayerCol = '<font style="color: #006400;">' + 
                        winner + ' was victorious</font>';
                }
                else
                {
                    currentPlayerCol = '<a style="color: #bc2224;" ' + 
                        'href="' + weewarURL + '/user/' + winner + '">' +
                        winner + ' was victorious</a>';
                }
            }
            else if ( numDraw > 0 )
            {
                var drawNames = drawers[0];
                for ( var i=1; i < numDraw; i++ )
                {
                    if ( (i+1) == numDraw )
                    {
                        drawNames = drawNames + " &amp; " + drawers[i];
                    }
                    else
                    {
                        drawNames = drawNames + ", " + drawers[i];
                    }
                }

                currentPlayerCol = '<font style="color: #d4a017;">' +
                    drawNames + ' ended the game in peace.';
            }
            // If the current player is the user display their name in green
            else if ( currentPlayers[listNum] == username )
            {
                currentPlayerCol = '<font style="color: #006400">' + 
                    currentPlayers[listNum] + '</font>';
	    }
            // Otherwise display a link to the current player
            else if ( currentPlayers[listNum] )
            {
                currentPlayerCol = '<a href="' + weewarURL + '/user/' + 
                    currentPlayers[listNum] + '">' + currentPlayers[listNum] + 
                    '</a>';

                // If the current player is online, show an indicator
               // showCurrentPlayerOnlineStatus(playerCol, currentPlayers[listNum]);
            }
	   
	    if (

            playerCol.innerHTML = currentPlayerCol;
	}
    }



// Gets map information (real name and thumbnail link) from map info page.
// Currently uses http map info page but if/when a SOAP API is made available can
// update to use that instead
function getMapLinks(mapNum, listNum, mapNameCol)
{
	var params = "?method=map&mapId=" + mapNum;
	var httpReqIndex = loadXMLHttpRequest();
  	http_requests[httpReqIndex].onreadystatechange = function() { return loadMapLink(httpReqIndex, mapNum, listNum, 
mapNameCol); };
  	http_requests[httpReqIndex].open('GET', "callweewarapi.php" + params, true);
  	http_requests[httpReqIndex].send(null);

}

function loadMapLink(httpReqIndex, mapNum, listNum, mapNameCol) {
	if (http_requests[httpReqIndex].readyState==4) {
            var responseText = http_requests[httpReqIndex].responseText.substring(1);

            var parser = new DOMParser();
            var dom = parser.parseFromString(responseText,"application/xml");

            // Parse out the map name
            var mapName = (dom.getElementsByTagName('name'))[0].textContent;
/*
            // Parse out the thumbnail image name
            var mapThumbnailImgLink = (dom.getElementsByTagName('thumbnail'))[0].textContent;

            // Add map preview to mouseover of mouse name
            mapNameCol.setAttribute("onMouseover", 
                "countdownPreview( 'preview_" + listNum + "' );");
            mapNameCol.setAttribute("onMouseOut", "hidePreview();");
*/
            // Finalize the map name element html
            var mapLink = weewarURL + '/map/' + mapNum;
            mapNameCol.innerHTML = '<a href="' + mapLink + '">' + 
                mapName +
/*                '<span style="display: block; position: relative; color: #666; ' +
	            'margin-top: 0.2em;">' +
                '<img id="preview_' + listNum + '" ' +
                'src="' + mapThumbnailImgLink + '" alt="' + mapName + '"' +
                'width="150" height="110" ' +
                'style="position: absolute; top: -60px; left: 40px; padding: 5px; ' +
                'background-color: #FFF; border: 1px solid #CCC; display: none" /></span>' +
*/                '</a>';
        }
    }



// Find out if current player is online, if so add an indicator
function showCurrentPlayerOnlineStatus(playerCol, playerNum)
{
/*
	// api no longer supports call by id
	makeRequest("?method=user&userid=" + playerNum, (loadOnlineStatus) (playerCol, playerNum));
*/
}
/*
function loadOnlineStatus(playerCol, playerNum) {
	if (http_request.readyState==4) {
            // Check to see if the player is online
            var xpath = new RegExp("<on>(.*)<\/on>");
            var onlineStatus = http_request.responseText.match(xpath)[1];

            if ( onlineStatus == "true" )
            {
                var onlineHtml = playerCol.innerHTML + '&nbsp;<font style="' +
                    'color: #9CC700; margin-left: 0.3em; ' +
                    'font-weight: normal;">on</font>&nbsp;';
                playerCol.innerHTML = onlineHtml;
            }
        }
    }
*/


var selectedGameId;

function updateSelectedGame(listNum) {
	selectedGameId = gameNums[listNum];
	document.getElementById('selectedGame').innerHTML = gameTags[listNum] + '<a href="' + weewarURL + '/game/' + 
		gameNums[listNum] + '"> (' + gameNums[listNum] + ')</a>';
}

function httpElizaPost(form, method) {
	var gameId = selectedGameId;
	var apiKey = form.apikey.value;
	var params = "method=" + method + "&gameId=" + gameId + "&username=" + username + "&apiKey=" + apiKey;
        var httpReqIndex = loadXMLHttpRequest();
	http_requests[httpReqIndex].onreadystatechange = function() { return updateElizaResp(httpReqIndex); };
        http_requests[httpReqIndex].open('POST', "callweewarelizaapi.php", true);
	http_requests[httpReqIndex].setRequestHeader("Content-type", "application/x-www-form-urlencoded");
	http_requests[httpReqIndex].setRequestHeader("Content-length", params.length);
	http_requests[httpReqIndex].setRequestHeader("Connection", "close");
        http_requests[httpReqIndex].send(params);
}


function updateElizaResp(httpReqIndex) {
	if (http_requests[httpReqIndex].readyState==4) {
            var responseText = http_requests[httpReqIndex].responseText.substring(1);
	    if (responseText.indexOf('This request requires HTTP authentication') != -1) {
		responseText = "Username and API key do not match.";
	    }
	    var elizaRespElt = document.getElementById('elizaResp');
	    replaceLastLiteral(responseText, elizaRespElt);
	}
}

function replaceLastLiteral(literalString, targetElement) {
    var textNode = document.createTextNode(literalString);
    targetElement.replaceChild(textNode, targetElement.lastChild);
    return textNode;
}

