package net.jacobandreas.cellular;

import java.util.*;

public class CAModel {

    int[][] cells;
    int counter;
    ArrayList<CARule> rules;

    private static final int EMPTY = 0;

    public CAModel(int rows, int cols) {

        cells = new int[rows][cols];
        counter = 0;
        rules = new ArrayList<CARule>();

        clear();

    }

    public void nextGeneration() {

        int[][] newCells = new int[getRows()][getColumns()];

        for(int r = 0; r < getRows(); r++) {
            for(int c = 0; c < getColumns(); c++) {

                int eval = evaluate(r, c);

                if(eval == CARule.KILL) {
                    newCells[r][c] = 0;
                } else if(eval == CARule.GROW) {
                    newCells[r][c] = cells[r][c] + 1;
                } else {
                    newCells[r][c] = cells[r][c];
                }

            }
        }

        cells = newCells;

    }

    private int evaluate(int row, int column) {

        int eval = CARule.IGNORE;

        for(CARule r : rules) {
            eval = r.evaluate(this, row, column);
            if(eval != CARule.IGNORE) {
                break;
            }
        }
        return eval;
    }

    public void clear() {
        for(int r = 0; r < getRows(); r++) {
            for(int c = 0; c < getColumns(); c++) {
                cells[r][c] = EMPTY;
            }
        }
    }

    public int getRows() {
        return cells.length;
    }

    public int getColumns() {
        return cells[0].length;
    }

    public int getValue(int r, int c) {
        if(r < 0 || r >= cells.length || c < 0 || c >= cells[0].length) {
            return 0;
        } else {
            return cells[r][c];
        }
    }

    public void setValue(int r, int c, int val) {
        cells[r][c] = val;
    }

    public void addRule(CARule r) {
        rules.add(r);
    }

    public void seed(int r0, int c0, int[][] seed) {
        //clear();
        for(int i = 0; i < seed.length; i++) {
            for(int j = 0; j < seed[0].length; j++) {
               setValue(r0 + i, c0 + j, seed[i][j]);
            }
        }
    } 

}

