package pl.edu.pw.mini.jk.sg.mixeduct.attackerresponse;

import java.util.List;

import com.google.common.collect.ImmutableList;
import org.apache.commons.math3.random.RandomGenerator;

import pl.edu.pw.mini.jk.sg.game.common.DefenderMove;
import pl.edu.pw.mini.jk.sg.game.common.TwoPlayerPayoffInfo;
import pl.edu.pw.mini.jk.sg.uct.PayoffInfo;
import pl.edu.pw.mini.jk.sg.game.common.SecurityGame;
import pl.edu.pw.mini.jk.sg.game.common.advanceable.AdvanceableAttackerState;
import pl.edu.pw.mini.jk.sg.game.DefenderAttackerGame;
import pl.edu.pw.mini.jk.sg.uct.SinglePlayerGame;


public class ClonableDefenderGameView<AM, DM extends DefenderMove, AS extends AdvanceableAttackerState<AM>, G extends DefenderAttackerGame<AM, DM, AS, ?, ?> & pl.edu.pw.mini.jk.sg.game.common.Cloneable<G>  & SecurityGame> implements pl.edu.pw.mini.jk.sg.game.common.Cloneable<ClonableDefenderGameView<AM,DM,AS,G>>, SinglePlayerGame<AM, AS> {
    private final G game;
    private final ImmutableList<DM> defenderStrategy;
    private int moveNum;
    
    public ClonableDefenderGameView(G game, int moveNum, ImmutableList<DM> defenderStrategy) {
		super();
		this.game = game;
		this.defenderStrategy = defenderStrategy;
		this.moveNum = moveNum;
	}

	public G getGame() {
		return game;
	}
	
	@Override
	public AS getCurrentState() {
		return game.getCurrentState().getAttackerVisibleState();
	}

	@Override
	public List<AM> possibleMoves() {
		return game.possibleAttackerMoves();
	}

    @Override
    public AM randomMove(RandomGenerator rng) {
	return game.randomAttackerMove(rng);
    }

	@Override
	public PayoffInfo makeMove(AM move) {
		game.playDefenderMove(defenderStrategy.get(moveNum));
		game.playAttackerMove(move);
		moveNum++;
		final TwoPlayerPayoffInfo pi = game.finishRound();
		return new PayoffInfo(pi.attackerPayoff(), pi.catchAccidentsCount(), pi.attackAccidentsCount());
	}

	@Override
	public int getTimeStep() {
	    assert(game.getTimeStep() == game.getCurrentState().getDefenderVisibleState().getTimeStep());
	    return game.getTimeStep();
	}

	@Override
	public ClonableDefenderGameView<AM, DM, AS, G> typedClone() {
	    final G clone = game.typedClone();
	    return new ClonableDefenderGameView<>(clone, moveNum, defenderStrategy);
	}

    public double getDefenderPayoff() {
	return game.getDefenderResult();
    }

    public double getAttackerPayoff() {
	return game.getAttackerResult();
    }

}

