package edu.wright.hendrix11.conway.logic;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * @author Joe Hendrix
 */
public class Grid {
    private List<Cell> aliveCells = new ArrayList<>();

    public void addLivingCell(Cell cell) {
        assert cell.isAlive();
        aliveCells.add(cell);
    }

    public void removeDeadCell(Cell cell) {
        assert !cell.isAlive();
        aliveCells.remove(cell);
    }

    public void tick() {
        List<Cell> toggleTheseCells = new ArrayList<>();

        checkLivingCells(toggleTheseCells);

        toggleCells(toggleTheseCells);
    }
    
    private void toggleCells(List<Cell> toggleTheseCells) {
        for(Cell cell : toggleTheseCells) {
            cell.toggle();

            if(cell.isAlive()) {
                aliveCells.add(cell);
            } else {
                assert !cell.isAlive();
                aliveCells.remove(cell);
            }
        }
    }
    
    private void checkAdjacentDeadCells(List<Cell> toggleTheseCells) {
        Set<Cell> newbornCells = new HashSet<>();
        
        for(Cell cell : aliveCells) {
            checkDeadCell(cell.getNorthernCell(), newbornCells);
            checkDeadCell(cell.getSouthernCell(), newbornCells);
            checkDeadCell(cell.getEasternCell(), newbornCells);
            checkDeadCell(cell.getWesthernCell(), newbornCells);
            
            checkDeadCell(cell.getNorthEasternCell(), newbornCells);
            checkDeadCell(cell.getNorthWesternCell(), newbornCells);
            checkDeadCell(cell.getSouthEasternCell(), newbornCells);
            checkDeadCell(cell.getSouthWesternCell(), newbornCells);
        }
        
        toggleTheseCells.addAll(newbornCells);
    }
    
    private void checkDeadCell(Cell deadCell, Set<Cell> newbornCells) {
        if(deadCell != null && deadCell.isAlive()) {
            return;   
        }
        
        assert deadCell == null || !deadCell.isAlive();
        
        if(deadCell == null) {
            // Todo: handle this case
            return;
        }
        
        int numberOfLivingNeighbors = deadCell.getNumberLivingNeighbors();
        
        assert numberOfLivingNeighbors >= 0 && numberOfLivingNeighbors <= 8;
        
        if(numberOfLivingNeighbors == 3) {
            newbornCells.add(cell.getNorthernCell());
        }
    }
    
    private void checkLivingCell(Cell livingCell, List<Cell> toggleTheseCells) {
        assert livingCell.isAlive();
        
        int numberOfLivingNeighbors = livingCell.getNumberLivingNeighbors();
        
        assert numberOfLivingNeighbors >= 0 && numberOfLivingNeighbors <= 8;
        
        if(numberOfLivingNeighbors < 2 || numberOfLivingNeighbors > 3) {
            toggleTheseCells.add(livingCell);
        }
    }
    
    private void checkLivingCells(List<Cell> toggleTheseCells) {
        for(Cell cell : aliveCells) {
            checkLivingCell(cell, toggleTheseCells);
        }
    }

}

@@ -86,19 +86,19 @@
 til.Hash
-Map
+Set
 ;%0Aimport
@@ -135,11 +135,11 @@
 til.
-Map
+Set
 ;%0A%0A/
@@ -1173,190 +1173,121 @@
     
-checkDeadCell(cell.getNorthernCell(), newbornCells);%0A            checkDeadCell(cell.getSouthernCell(), newbornCells);%0A            checkDeadCell(cell.getEasternCell(), newbornCells);%0A
+for(Cell neighbor : cell.getNeighbors()) %7B%0A                if(neighbor != null && !neighbor.isAlive()) %7B%0A        
     
@@ -1316,19 +1316,19 @@
 cell.get
-Wes
+Nor
 thernCel
@@ -1363,692 +1363,297 @@
     
-%0A            checkDeadCell(cell.getNorthEasternCell(), newbornCells);%0A            checkDeadCell(cell.getNorthWesternCell(), newbornCells);%0A            checkDeadCell(cell.getSouthEasternCell(), newbornCells);%0A            checkDeadCell(cell.getSouthWesternCell(), newbornCells);%0A        %7D%0A        %0A        toggleTheseCells.addAll(newbornCells);%0A    %7D%0A    %0A    private void checkDeadCell(Cell deadCell, Set%3CCell%3E newbornCells) %7B%0A        if(deadCell != null && deadCell.isAlive()) %7B%0A            return;   %0A        %7D%0A        %0A        assert deadCell == null %7C%7C !deadCell.isAlive();%0A        %0A        if(deadCell == null) %7B%0A            // Todo: handle this case%0A            return;%0A        %7D
+    %7D else if(neighbor == null) %7B%0A                    // Todo: this case%0A                %7D%0A            %7D%0A        %7D%0A        %0A        toggleTheseCells.addAll(newbornCells);%0A    %7D%0A    %0A    private void checkDeadCell(Cell deadCell, Set%3CCell%3E newbornCells) %7B%0A        assert !deadCell.isAlive();
 %0A   

Update Grid.java