package de.kimminich.kata.tcg;

import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.Mock;
import org.mockito.runners.MockitoJUnitRunner;

import static org.hamcrest.CoreMatchers.equalTo;
import static org.hamcrest.CoreMatchers.is;
import static org.hamcrest.MatcherAssert.assertThat;

@RunWith(MockitoJUnitRunner.class)
public class PlayerTest {

    Player player;

    @Mock
    CardPicker cardPicker;

    @Before
    public void setUp() {
        player = new Player(cardPicker);
    }

    @Test
    public void playerShouldHave30InitialHealth() {
        assertThat(player.getHealth(), is(equalTo(30)));
    }

    @Test
    public void playerShouldHaveZeroInitialMana() {
        assertThat(player.getMana(), is(equalTo(0)));
    }

    @Test
    public void cardDeckShouldContainInitialCards() {
        assertThat(player.getNumberOfCardsWithManaCost(0), is(equalTo(2)));
        assertThat(player.getNumberOfCardsWithManaCost(1), is(equalTo(2)));
        assertThat(player.getNumberOfCardsWithManaCost(2), is(equalTo(3)));
        assertThat(player.getNumberOfCardsWithManaCost(3), is(equalTo(4)));
        assertThat(player.getNumberOfCardsWithManaCost(4), is(equalTo(3)));
        assertThat(player.getNumberOfCardsWithManaCost(5), is(equalTo(2)));
        assertThat(player.getNumberOfCardsWithManaCost(6), is(equalTo(2)));
        assertThat(player.getNumberOfCardsWithManaCost(7), is(equalTo(1)));
        assertThat(player.getNumberOfCardsWithManaCost(8), is(equalTo(1)));
    }

    @Test
    public void playerStartsWithEmptyHand() {
        assertThat(player.getNumberOfHandCards(), is(equalTo(0)));
    }

    @Test
    public void drawingACardShouldPutOneCardFromDeckIntoHand() {
        // given
        player = aPlayer().withCardsInDeck(0).withNoCardsInHand();
        // when
        player.drawCard();
        // then
        assertThat(player.getNumberOfHandCards(), is(equalTo(1)));
        assertThat(player.getNumberOfDeckCards(), is(equalTo(0)));
    }

    @Test
    public void drawingACardShouldPutThatCardFromDeckIntoHand() {
        // given
        player = aPlayer().withCardsInDeck(1,1,2).withNoCardsInHand();
        // when
        int card = player.drawCard();
        // then
        assertThat(player.getNumberOfHandCardsWithManaCost(1), is(equalTo(1)));
        assertThat(player.getNumberOfCardsWithManaCost(1), is(equalTo(1)));
        assertThat(player.getNumberOfCardsWithManaCost(2), is(equalTo(1)));
    }

    private FakePlayer aPlayer() {
        return new FakePlayer();
    }

    private class FakePlayer extends Player {

        public FakePlayer() {
            super(PlayerTest.this.cardPicker);
            this.deck = new int[]{0, 0, 0, 0, 0, 0, 0, 0, 0};
            this.hand = new int[]{0, 0, 0, 0, 0, 0, 0, 0, 0};
        }

        public FakePlayer withCardsInDeck(int... manaCost) {
            for (int cost : manaCost) {
                deck[cost] = deck[cost] + 1;
            }
            return this;
        }

        public FakePlayer withNoCardsInDeck() {
            this.deck = new int[]{0, 0, 0, 0, 0, 0, 0, 0, 0};
            return this;
        }

        public FakePlayer withCardsInHand(int... manaCost) {
            for (int cost : manaCost) {
                hand[cost] = hand[cost] + 1;
            }
            return this;
        }

        public FakePlayer withNoCardsInHand() {
            this.hand = new int[]{0, 0, 0, 0, 0, 0, 0, 0, 0};
            return this;
        }

    }

}

@@ -125,20 +125,79 @@
 mockito.
+BDD
 Mock
+ito;%0Aimport org.mockito.Mock;%0Aimport org.mockito.Mockito
 ;%0Aimport
@@ -383,16 +383,93 @@
 ertThat;
+%0Aimport static org.mockito.BDDMockito.*;%0Aimport static org.mockito.Mockito.*;
 %0A%0A@RunWi
@@ -2317,32 +2317,96 @@
 oCardsInHand();%0A
+        given(cardPicker.draw(any(int%5B%5D.class))).willReturn(1);%0A
         // when%0A

test passes. no need any more to let Player.drawCard() return the card.