var svg = d3.select("svg");

var rows = 60;
var cols = 90;
var marginBottom = 152;
var totalWidth = tributary.sw;
var totalHeight = tributary.sh - marginBottom;
var width = parseInt(totalWidth / cols);
var height = parseInt(totalHeight / rows);



function GameOflife(options) {
  
  this.rows = options.rows;
  this.cols = options.cols;
  
}

GameOflife.prototype.setInitialState = function(init) {

  this.data = []; 
  
  for(var i = 0; i < this.rows; i++) {
    for(var j = 0; j < this.cols; j++) {
      this.data.push({ x: j, y: i, live: 0 });
    }
  }
  
  for(i = 0; i < init.length; i++) {
    
    var pos = this.getPos(init[i][0], init[i][1]);
    this.data[pos].live = 1;
  }
  
};

GameOflife.prototype.getPos = function(x, y) {
  
  if ( x >= 0 && x < this.cols && y >= 0 && y < this.rows ) {
    return (y * this.cols) + x; 
  }
  return -1;
};

GameOflife.prototype.getCell = function(x, y) {
  
  var pos = this.getPos(x, y);
  
  if (pos >= 0 && pos < this.data.length ) {
    return this.data[pos];
  }
  
  return {};
};

GameOflife.prototype.getNeighbours = function(cell) {
  
  var x = cell.x;
  var y = cell.y;
  var cells = [];
  
  cells.push(this.getCell(x - 1, y - 1));
  cells.push(this.getCell(x - 1, y));
  cells.push(this.getCell(x - 1, y + 1));
  cells.push(this.getCell(x, y - 1));
  cells.push(this.getCell(x, y + 1));
  cells.push(this.getCell(x + 1, y - 1));
  cells.push(this.getCell(x + 1, y));
  cells.push(this.getCell(x + 1, y + 1));
  
  return cells; 
};

GameOflife.prototype.nextGeneration = function() {
  
  var newData = [];
  
  for(var i = 0; i < this.data.length; i++) {
    
    var cell = this.data[i];
    var live = 0;
    var livesCount = 0;
    var neighbours = this.getNeighbours(cell);
    
    for (var j = 0; j < neighbours.length; j++) {
      if (neighbours[j].live && neighbours[j].live == 1) {
        livesCount = livesCount + 1;
      }
    }
    
    //Rule 1; Any live cell with fewer than two live neighbours dies, as if
    //caused by under-population.
    if (livesCount < 2 && cell.live == 1) {
      //console.log('dies');
      live = 0;
    }
    
    //Rule 2: Any live cell with two or three live neighbours lives on to the
    //next generation.
    if ((livesCount == 2 || livesCount == 3) && cell.live == 1) {
      //console.log('keep living');
      live = 1;
    }
    
    //Rule 3; Any live cell with more than three live neighbours dies,
    //as if by overcrowding.
    if ((livesCount > 3) && cell.live == 1) {
      //console.log('dies');
      live = 0;
    }
    
    //Rule 4: Any dead cell with exactly three live neighbours becomes a live cell,
    //as if by reproduction.
    if (livesCount == 3 && cell.live === 0) {
      //console.log('born!');
      live = 1;
    }
    
    newData.push({x: cell.x, y: cell.y, live: live});                   
    
  }
  
  this.data = newData;
  
}

GameOflife.prototype.draw = function() {
  
  d3.selectAll("rect")
    .data(this.data)
    .attr('class', function(d) { return "live" + d.live; });
  
}

GameOflife.prototype.start = function() {
  
  this.nextGeneration();
  this.draw();
 
}

svg.attr("width", totalWidth).
	attr("height", totalHeight + marginBottom);

var gameOfLife = new GameOflife({ rows: rows, cols: cols});

var graph = svg.append("g").
  attr("width", totalWidth).
  attr("height", totalHeight);

var x = d3.scale.linear().domain([0, cols]).range([0, totalWidth]);
var y = d3.scale.linear().domain([0, rows]).range([0, totalHeight]);


function addButton(x, y, text, callback) {
  
  var button = svg.append('g')
	.classed('btn', true)
	.attr('transform', 'translate('+[x,y]+')');

	button.append('rect')
	.attr("width", 100)
    .attr("height", 50)
	.attr("x", 0)
    .attr("y", 0);

	button.append('text')
	.attr("x", 20)
    .attr("y", 30)
	.text(text)
	.on('click', callback);
  
}


var initialized = false;
function init() {
   
  var state = [];
  
  var maxInitailcells = parseInt(Math.random()*(rows*cols));
    
  for (var a = 0; a < maxInitailcells; a++) {
    
    var item = [
      parseInt(Math.random()*cols),
      parseInt(Math.random()*rows)
    ];
    
    state.push(item);
    
  }
  
  gameOfLife.setInitialState(state);
  
  if (!initialized) {
    var data = graph.selectAll("g.cell")
    .data(gameOfLife.data); 
    
    data.enter().append("rect")
    .classed('cell',true)
    .attr("width", width - 0.3)
    .attr("height", height - 0.3)
    .attr("x", function(d) { return x(d.x); })
    .attr("y", function(d) { return y(d.y); });
  }
      
  gameOfLife.draw();
  
  initialized = true;

}


var interval = null;
addButton(10, totalHeight + 20, 'Start >>', function(){
      interval = setInterval(function(){ gameOfLife.start(); }, 500);
});

addButton(123, totalHeight + 20, 'RESET', function(){
      clearInterval(interval);
      init();
});

addButton(250, totalHeight + 20, 'Stop', function(){
      clearInterval(interval);
});

init();