package model;

import util.Position;
import util.TargetStrategy;

import java.lang.reflect.InvocationTargetException;
import java.util.*;


public class FFBoard implements Board<List<ModelElement>> {
  private final int columnCount;
  private final int rowCount;
  private final int initialFireCount;
  private final int initialFirefighterCount;
  private BoardData boardData;
  private FFUpdater FFUpdater ;
  private final Random randomGenerator = new Random();

  public FFBoard(int columnCount, int rowCount, int initialFireCount, int initialFirefighterCount) {
    boardData=new FFBoardData(columnCount,rowCount);
    FFUpdater=new FFUpdater();
    this.columnCount = columnCount;
    this.rowCount = rowCount;
    this.initialFireCount = initialFireCount;
    this.initialFirefighterCount = initialFirefighterCount;
    initializeElements();
  }

  public void initializeElements() {
    boardData.initialize();
    FFUpdater= new FFUpdater();
    for (int index = 0; index < initialFireCount; index++)
      boardData.addElement(new StandardFire(randomPosition()));
     for (int index = 0; index < initialFirefighterCount; index++)
       boardData.addElement(new StandardFireFighter(randomPosition()));
    for (int index = 0; index < 2; index++)
      boardData.addElement(new MotorizedFireFighter(randomPosition()));
    for (int index = 0; index < 10; index++)
      boardData.addElement(new Cloud(randomPosition()));
    for (int index = 0; index < 50; index++)
      boardData.addElement(new Road(randomPosition()));

  }

  private Position randomPosition() {
    return new Position(randomGenerator.nextInt(rowCount), randomGenerator.nextInt(columnCount));
  }

  @Override
  public List<ModelElement> getState(Position position) {
    List<ModelElement> result=new ArrayList<>();
    for (Element e:boardData.getCell(position).Content) {
      result.add(e.getType());
    }
    return result;
  }

  @Override
  public int rowCount() {
    return rowCount;
  }

  @Override
  public int columnCount() {
    return columnCount;
  }

  public List<Position> updateToNextGeneration() {

    List<Position> modifiedPositions = FFUpdater.updateAll(boardData);
    boardData.setStep(boardData.getStep()+1);
    return modifiedPositions;
  }
  @Override
  public int stepNumber() {
    return boardData.getStep();
  }
  @Override
  public void reset() {
    initializeElements();
  }
  @Override
  public void setState(List<ModelElement> state, Position position) {
    for (ModelElement modelElement: state) {
        boardData.addElement(modelElement.instanciate(position));
    }
  }
}