package pl.edu.pw.mini.jk.sg.game.graph.advanceable;

import java.util.Optional;

import com.google.common.base.Preconditions;
import com.google.common.cache.Cache;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableSet;

import pl.edu.pw.mini.jk.sg.game.common.State;
import pl.edu.pw.mini.jk.sg.game.graph.moves.single.DesiredConfigurationMove;

public class AdvanceableGraphGameState implements State<AttackerAdvaceableGraphState, AdvanceableDefenderGraphState> {
	private final AttackerAdvaceableGraphState attackerAdvaceableGraphState;
	private final AdvanceableDefenderGraphState advanceableDefenderGraphState;
	private final ImmutableList<Boolean> activeAttackers;

	public AdvanceableGraphGameState(int timeStep, ImmutableList<Integer> defenderPositions, ImmutableList<Integer> attackerPositions,
			ImmutableList<ImmutableSet<Integer>> possibleDestinationFromVertex, ImmutableList<Boolean> activeAttackers,
			Optional<Cache<Object, ImmutableList<DesiredConfigurationMove>>> moveCache) {
		Preconditions.checkNotNull(moveCache);
		if (moveCache.isPresent()) {
			attackerAdvaceableGraphState = new AttackerAdvaceableGraphState(
											timeStep,attackerPositions,
					possibleDestinationFromVertex, moveCache.get());
			advanceableDefenderGraphState = new AdvanceableDefenderGraphState(
					defenderPositions,
					possibleDestinationFromVertex, timeStep, moveCache.get());
		} else {
		    attackerAdvaceableGraphState = new AttackerAdvaceableGraphState(timeStep,
					attackerPositions,
					possibleDestinationFromVertex);
			advanceableDefenderGraphState = new AdvanceableDefenderGraphState(
					defenderPositions,
					possibleDestinationFromVertex, timeStep);
		}
		this.activeAttackers = activeAttackers;
	}

	@Override
	public AdvanceableDefenderGraphState getDefenderVisibleState() {
		return advanceableDefenderGraphState;
	}

	@Override
	public AttackerAdvaceableGraphState getAttackerVisibleState() {
		return attackerAdvaceableGraphState;
	}

	public ImmutableList<Boolean> getActiveAttackers() {
		return activeAttackers;
	}

	@Override
	public int hashCode() {
		final int prime = 31;
		int result = 1;
		result = prime * result + ((activeAttackers == null) ? 0 : activeAttackers.hashCode());
		result = prime * result
				+ ((advanceableDefenderGraphState == null) ? 0 : advanceableDefenderGraphState.hashCode());
		result = prime * result
				+ ((attackerAdvaceableGraphState == null) ? 0 : attackerAdvaceableGraphState.hashCode());
		return result;
	}

	@Override
	public boolean equals(Object obj) {
		if (this == obj)
			return true;
		if (obj == null)
			return false;
		if (getClass() != obj.getClass())
			return false;
		AdvanceableGraphGameState other = (AdvanceableGraphGameState) obj;
		if (activeAttackers == null) {
			if (other.activeAttackers != null)
				return false;
		} else if (!activeAttackers.equals(other.activeAttackers))
			return false;
		if (advanceableDefenderGraphState == null) {
			if (other.advanceableDefenderGraphState != null)
				return false;
		} else if (!advanceableDefenderGraphState.equals(other.advanceableDefenderGraphState))
			return false;
		if (attackerAdvaceableGraphState == null) {
			if (other.attackerAdvaceableGraphState != null)
				return false;
		} else if (!attackerAdvaceableGraphState.equals(other.attackerAdvaceableGraphState))
			return false;
		return true;
	}
}
