var cols = 70
var rows = 13
var cellSize = 4
var delay = 1000

var grids
var queues
var cells
var current

function cell(row, col) {
  // return $('cell_' + row + '_' + col)
  return cells[row][col]
}

function addCell(id, board_id) {
  var board = $(board_id)
  var cell = document.createElement('div')
  cell.id = id
  cell.addClassName('cell')
  cell.style.width = "" + cellSize - 2 + "px"
  cell.style.height = "" + cellSize - 2 + "px"
  board.appendChild(cell)
  
  return cell
}

function addCells() {
  var cell, board_id
  $('board1').style.width = "" + (cols * cellSize / 2) + "px"
  $('board1').style.height = "" + (rows * cellSize) + "px"
  $('board2').style.width = "" + (cols * cellSize / 2) + "px"
  $('board2').style.height = "" + (rows * cellSize) + "px"
  for (i = 0; i < rows; i++) {
    for (j = 0; j < cols; j++) {
      board_id = j < 35 ? 'board1' : 'board2'
      cell = addCell('cell_' + i + '_' + j, board_id)
      cell.row = i
      cell.col = j
      cell.live = false
      cell.addEventListener('click', clickCell, true)
      cells[i][j] = cell
    }
  }
}

function setCell(row, col, live) {
  var cell = cellAt(row, col)
  grids[1-current][row][col] = live
  // cell.live = live
  if (live) {
    cell.style.backgroundColor = 'black'
  } else {
    cell.style.backgroundColor = 'transparent'
  }
}

function clickCell(e) {
  // flipCell(this)
  var neighbors = liveNeighbors(this.row, this.col)
  alert("Live: " + current[this.row][this.col] + ", Neighbors: " + neighbors)
  alert("Lives: " + ((this.live && (neighbors == 2)) || (neighbors == 3))
  )
}

// Game of Life
function cellAt(row, col) {
  // alert("Cell at " + x + ", " + y)
  col = col < 0 ? cols + col : col % cols
  row = row < 0 ? rows + row : row % rows
  // alert("Translated to " + x + ", " + y)
  return cell(row, col)
}

function valueAt(row, col) {
  // alert("Cell at " + x + ", " + y)
  col = col < 0 ? cols + col : col % cols
  row = row < 0 ? rows + row : row % rows
  // alert("Translated to " + x + ", " + y)
  return grids[current][row][col]
}

// add work to the queue for a cell
var WORK_KILL = 0
var WORK_LIVE = 1
var WORK_READ = 2
function addWork(row, col, type) {
  if (type == WORK_READ) {
    // reads go on the next queue
    queues[1-current]
  }
}

function setup() {
  // init arrays
  grids = [[],[]]
  queues = [[], []]
  cells = []
  for (i = 0; i < rows; i++) {
    grids[0][i] = []
    grids[1][i] = []
    cells[i] = []
    for (j = 0; j < cols; j++) {
      grids[0][i][j] = false
      grids[1][i][j] = false
    }
  }
  current = 0
  // add cells to the page
  addCells()
  // init to two r-pentominos
  setCell(Math.floor(rows/2),     Math.floor(cols/4 - 1), true)
  setCell(Math.floor(rows/2),     Math.floor(cols/4), true)
  setCell(Math.floor(rows/2 - 1), Math.floor(cols/4), true)
  setCell(Math.floor(rows/2 - 1), Math.floor(cols/4 + 1), true)
  setCell(Math.floor(rows/2 - 2), Math.floor(cols/4), true)
  
  setCell(Math.floor(rows/2 - 1), Math.floor(3 * cols/4), true)
  setCell(Math.floor(rows/2),     Math.floor(3 * cols/4), true)
  setCell(Math.floor(rows/2),     Math.floor(3 * cols/4 - 1), true)
  setCell(Math.floor(rows/2 + 1), Math.floor(3 * cols/4 - 1), true)
  setCell(Math.floor(rows/2),     Math.floor(3 * cols/4 - 2), true)
  
  setTimeout('updateBoard()', delay)
}
function liveNeighbors(x, y) {
  var count = 0
  count += valueAt(x-1, y-1) ? 1 : 0
  count += valueAt(x, y-1) ? 1 : 0
  count += valueAt(x+1, y-1) ? 1 : 0
  count += valueAt(x-1, y) ? 1 : 0
  count += valueAt(x+1, y) ? 1 : 0
  count += valueAt(x-1, y+1) ? 1 : 0
  count += valueAt(x, y+1) ? 1 : 0
  count += valueAt(x+1, y+1) ? 1 : 0
  return count
}
function updateBoard() {
  var cell, neighbors, live
  current = 1 - current
  // loop through cells
  for (row = 0; row < rows; row++) {
    for (col = 0; col < cols; col++) {
      live = grids[current][row][col]
      neighbors = liveNeighbors(row, col)
      grids[1-current][row][col] = ((live && (neighbors == 2)) || (neighbors == 3))
    }
  }
  // update cells
  for (row = 0; row < rows; row++) {
    for (col = 0; col < cols; col++) {
      // cell = cellAt(row, col)
      if (grids[0][row][col] != grids[1][row][col])
      setCell(row, col, grids[1-current][row][col])
    }
  }
  setTimeout('updateBoard()', delay)
}
