var initiated = false;
var gameStarted = false;
var gameStop = false;
var gameStep = 1000;
var round = 0;
var _rows = 15, _columns = 30;
var margin = 1;
var intervalID;
var mapArrayA;
var mapArrayB;
var mapArray;
var currentArray;

//initiate the game
function GameofLife_initiate(id,rows,columns,size)
{
    $(id).html('');
    if(rows)
        _rows = rows
    if(columns)
        _columns = columns;
    if(!size)
        size = 15;
    
    mapArrayA = new Array(_rows);
    mapArrayB = new Array(_rows);
    mapArray = new Array(_rows);
    
    $(id).width(_columns*(size+margin));
    $(id).height(_rows*(size+margin));
    
    for(i=0;i<_rows;i++)
    {
        mapArray[i] = new Array(_columns);
        mapArrayA[i] = new Array(_columns);
        mapArrayB[i] = new Array(_columns);
        
        for(j=0;j<_columns;j++)
        {
            $(id).append('<div id="'+i+"_"+j+'" class="golCell" style="width:'+size+'px;height:'+size+'px"></div>');
            mapArrayA[i][j] = 0;
            mapArrayB[i][j] = 0;
            mapArray[i][j] = 0;
        }
    }
    initiated = true;
}

//start the game
function GameofLife_start()
{
    if(initiated)
    {
        GameofLife_setmaparray();
        intervalID = setInterval("GameofLife_run()",gameStep);
    }
    else
    {
        alert("The game is not initiated.");
    }
}

//stop the game
function GameofLife_stop()
{
    clearInterval(intervalID);
}
function GameofLife_resetstep()
{
    if(initiated)
    {
        intervalID = setInterval("GameofLife_run()",gameStep);
    }
}
//turn map tiles in to 1s and 0s and put them into an array for easy access
function GameofLife_setmaparray()
{   
    currentArray = 'A';
    for(i=0;i<_rows;i++)
    {
        mapArrayA[i] = new Array(_columns);
        for(j=0;j<_columns;j++)
        {
            if($("#"+i+"_"+j).hasClass("selectedCell"))
            {
                mapArrayA[i][j] = 1;
            }
            else
            {
                mapArrayA[i][j] = 0;
            }
        }
    }
}

//set round number
function GameofLife_setround(number)
{
    $('#roundCount').html(number);
}

//clear map and arrays
function GameofLife_clear()
{
    for(i=0;i<_rows;i++)
    {
        for(j=0;j<_columns;j++)
        {
            $("#"+i+"_"+j).removeClass("selectedCell");
            mapArrayA[i][j] = 0;
            mapArrayB[i][j] = 0;
            mapArray[i][j] = 0;
        }
    }
    round = 0;
    GameofLife_setround(round);
}

//get next map array, set it and update round number
function GameofLife_run()
{
    //alert(mapArrayA+'\n'+mapArrayB);
    GameofLife_getNextMap();
    GameofLife_setNextMap();
    round++;
    GameofLife_setround(round);
}

//get next map array
function GameofLife_getNextMap()
{
    var row,column;
    var neighbors;
    var mapSquare;

    for(i=0;i<_rows;i++)
    {
        for(j=0;j<_columns;j++)
        {            
            neighbors = GameofLife_getliveneighbors(i,j);
            
            mapSquare = $("#"+i+"_"+j);
            switch(neighbors)
            {
                case 0:
                case 1:
                    mapArray[i][j] = 0;
                    break;
                case 2:
                    if(mapSquare.hasClass("selectedCell"))
                    {
                        mapArray[i][j] = 1;
                    }
                    else
                    {
                        mapArray[i][j] = 0;
                    }
                    break;
                case 3:
                    mapArray[i][j] = 1;
                    break;
                case 4:
                case 5:
                case 6:
                case 7:
                case 8:
                    mapArray[i][j] = 0;
                    break;
                default:
                    break;
            }
        }
    }
    mapArrayB = mapArray;
}

//set next map array
function GameofLife_setNextMap()
{
    mapArray = mapArrayB;
   
    for(i=0;i<_rows;i++)
    {
        for(j=0;j<_columns;j++)
        {
            mapSquare = $("#"+i+"_"+j);
            if(mapArray[i][j] == 1)
            {
                mapSquare.addClass("selectedCell");
                mapArrayA[i][j] = 1;
            }
            else
            {
                mapSquare.removeClass("selectedCell");
                mapArrayA[i][j] = 0;
            }
        }
    }
}

//calculate number of neighbor of a given tile
function GameofLife_getliveneighbors(row,column)
{
    var count = 0;
    var mapItem;
    row = parseInt(row);
    column = parseInt(column);
    
    //upper left neighbor
    if(row>0 && column>0)
        if(mapArrayA[(row-1)][(column-1)])
            count++;
    
    //upper mid neighbor
    if(row>0)
        if(mapArrayA[(row-1)][column])
            count++;
        
    //upper right neighbor
    if(row>0 && column<_columns-1)
        if(mapArrayA[(row-1)][(column+1)])
            count++;
            
    //left neighbor
    if(column>0)
        if(mapArrayA[row][(column-1)])
            count++;
    
    //right neighbor
    if(column<_columns-1)
        if(mapArrayA[row][(column+1)])
            count++;
            
    //lower left neighbor
    if(row<_rows-1 && column>0)
        if(mapArrayA[(row+1)][(column-1)])
            count++;
            
    //lower mid neighbor
    if(row<_rows-1)
        if(mapArrayA[(row+1)][column])
            count++;
            
    //lower right neighbor
    if(row<_rows-1 && column<_columns-1)
        if(mapArrayA[(row+1)][(column+1)])
            count++;
            
    return count;
}

//returns xy coordinate from id string
function getIdArrayFromString(str)
{
    return str.split('_');
}

//plot a map based on a given string
function GameofLife_setmap(map)
{
    initiated = false;
    GameofLife_stop();
    GameofLife_clear();

    GameofLife_setmapbyarray(map);
    GameofLife_setmaparray();
    
    initiated = true;
    gameStarted = false;
    $('#gameStop').attr('disabled','true');
    $('#gameStart').removeAttr('disabled');
}

//plot a map based on a given string
function GameofLife_setmapbyarray(arrayString)
{
    arrayString = $.trim(arrayString);
    
    if(arrayString == '')
        alert("No save");
        
    var rowArray = arrayString.split(';');
    var columnArray;
    var leftIndex = 0;
    var topIndex = 0;
    
    var row = rowArray.length;
    topIndex = Math.ceil(_rows/2) - Math.ceil(row/2);
    
    for(i=0;i<rowArray.length;i++)
    {
        columnArray = rowArray[i].split(',');
        columns = columnArray.length;
        leftIndex = Math.ceil(_columns/2) - Math.ceil(columns/2);
        
        for(j=0;j<columns;j++)
        {
            if(columnArray[j] == '1')
            {
                $('#'+topIndex+'_'+leftIndex).addClass("selectedCell");
            }
            leftIndex++;
        }
        topIndex++;
    }
}
function GameofLife_saveoriginal()
{
    $('#saveBar').val(GameofLife_maptostring())
}
function GameofLife_maptostring()
{
    var leftIndex = 1000;
    var topIndex = 1000;
    var rightIndex = -1;
    var bottomIndex = -1;
    var mapstring = '';
    
    for(i=0;i<_rows;i++)
    {
        for(j=0;j<_columns;j++)
        {
            if($("#"+i+"_"+j).hasClass("selectedCell"))
            {
                if(i<topIndex)
                    topIndex = i;
                if(i>bottomIndex)
                    bottomIndex = i;
                if(j<leftIndex)
                    leftIndex = j;
                if(j>rightIndex)
                    rightIndex = j;
            }
        }
    }
    
    for(i=topIndex;i<=bottomIndex;i++)
    {
        for(j=leftIndex;j<=rightIndex;j++)
        {
            if($("#"+i+"_"+j).hasClass("selectedCell"))
            {
                mapstring += '1,';
            }
            else
            {
                mapstring += '0,';
            }
        }
        mapstring = mapstring.substr(0,mapstring.length-1)
        mapstring += ';'
    }
    mapstring = mapstring.substr(0,mapstring.length-1)
    return mapstring;
}
function GameofLife_restoreoriginal(mapstring)
{
    GameofLife_clear();
    GameofLife_setmapbyarray(mapstring);
}
$(document).ready(function(){
    $('.golCell').live('click',function(){
        if($(this).hasClass("selectedCell"))
        {
            $(this).removeClass("selectedCell");
        }
        else
        {
            $(this).addClass("selectedCell");
        }
    });
    $('#gameStart').live('click',function(){
        GameofLife_start();
        gameStarted = true;
        $(this).attr('disabled','true');
        $('#gameStop').removeAttr('disabled');
    });
    $('#gameStop').live('click',function(){
        GameofLife_stop();
        $(this).attr('disabled','true');
        $('#gameStart').removeAttr('disabled');
    });
    $('#gameSave').live('click',function(){
        GameofLife_saveoriginal();
    });
    $('#gameRestore').live('click',function(){
        GameofLife_restoreoriginal($('#saveBar').val())
        $('#gameStart').removeAttr('disabled');
    });
    $('#preSetMaps').live('change',function(){
        var val = $(this).val();
        
        GameofLife_setmap(val);
    });
    $('#step').live('change',function(){
        gameStep = $(this).val();
        
        if(gameStep < 50 || gameStep > 2000)
            gameStep = 1000;
        
        GameofLife_stop();
        GameofLife_resetstep();
    });
    $('#size').live('change',function(){
        gridSize = $(this).val();
        
        GameofLife_stop();
        GameofLife_clear();
        
        switch(gridSize)
        {
            case '10x15':
                GameofLife_initiate("#GameofLife",10,15,30);
                break;
            case '15x30':
                GameofLife_initiate("#GameofLife",15,30,20);
                break;
            case '30x60':
                GameofLife_initiate("#GameofLife",30,60,10);
                break;
            default:
                GameofLife_initiate("#GameofLife",15,30,20);
                break;
        }
    });
    
});