package predatorprey;

import fr.cemagref.simaqualife.extensions.spatial2D.Grid2D;
import fr.cemagref.simaqualife.extensions.spatial2D.Grid2D.NeighborsType;
import fr.cemagref.simaqualife.kernel.AquaNismsGroup;
import fr.cemagref.simaqualife.kernel.util.TransientParameters.InitTransientParameters;
import fr.cemagref.simaqualife.pilot.Pilot;
import predatorprey.predators.Predator;
import predatorprey.preys.Prey;
import umontreal.iro.lecuyer.probdist.UniformDist;
import umontreal.iro.lecuyer.randvar.UniformGen;

public class Grid extends Grid2D<Cell, Individual> {

    public Grid(int gridWidth, int gridHeight, NeighborsType neighborsType) {
        super(gridWidth, gridHeight, neighborsType);
        // TODO Auto-generated constructor stub
    }

    /**
     * <code>preyCarryingCapacity</code> number of preys that a cell can support
     */
    private int preyCarryingCapacity;
    private double habitatValue0 = .25;
    private double habitatValue1 = .5;
    private double habitatValue2 = 1;

    transient private UniformGen uniformGen;
    transient private double[] habitatValues;

    @InitTransientParameters
    public void initTransientParameters(Pilot pilot) {

        this.pos = neighborsType.getPos();

        habitatValues = new double[3];
        habitatValues[0] = habitatValue0;
        habitatValues[1] = habitatValue1;
        habitatValues[2] = habitatValue2;

        UniformGen uniformGen = new UniformGen(pilot.getRandomStream(), new UniformDist(0, habitatValues.length - 1));

        grid = new Cell[gridWidth * gridHeight];
        for (int i = 0; i < grid.length; i++) {
            double hab = habitatValues[(int) Math.round(uniformGen.nextDouble())];
            grid[i] = new Cell(i, hab, preyCarryingCapacity);
        }
    }

    @Override
    public void addAquaNism(Individual ind, AquaNismsGroup group) {
        super.addAquaNism(ind, group);
        if (ind instanceof Prey) {
            ind.getPosition().addPrey((Prey) ind);
        } else {
            ind.getPosition().addPredator((Predator) ind);
        }
    }

    @Override
    public void moveAquaNism(Individual ind, AquaNismsGroup group, Cell dest) {
        super.moveAquaNism(ind, group, dest);
        this.removeAquaNism(ind, group);
        if (ind instanceof Prey) {
            dest.addPrey((Prey) ind);
        } else {
            dest.addPredator((Predator) ind);
        }
    }

    @Override
    public void removeAquaNism(Individual ind, AquaNismsGroup group) {
        super.removeAquaNism(ind, group);
        if (ind instanceof Prey) {
            ind.getPosition().removePrey((Prey) ind);
        } else {
            ind.getPosition().removePredator((Predator) ind);
        }
    }

}