package kevin.lawrence.bowling;

import static org.hamcrest.Matchers.*;
import static org.hamcrest.MatcherAssert.*;

import java.util.Iterator;

import org.junit.Before;
import org.junit.Test;

public class GameTest {
  
  private Game game;

  @Before
  public void createGame() {
    game = new Game();
  }

  @Test
  public void shouldBeTenFramesWithTwoRollsInEach() {
    for(int frame = 0; frame < 10; frame++){
      game.bowl(0);
      game.bowl(0);
    }
    
    assertThat(game.isGameOver(), is(true));
  }

  @Test
  public void theGameShouldNotBeOverAfterNineAndHalfFrames() {
    for(int frame = 0; frame < 9; frame++){
      game.bowl(0);
      game.bowl(0);
    }
    
    game.bowl(0);
 
    assertThat(game.isGameOver(), is(false));
  }

  @Test(expected=IllegalArgumentException.class) 
  public void shouldThrowAnExceptionIfMoreThanTenPins() {
    game.bowl(11);
  }

  @Test(expected=IllegalArgumentException.class) 
  public void shouldThrowAnExceptionIfLessThanZeroPins() {
    game.bowl(-1);
  }

  @Test
  public void shouldBeNoScoreUntilBallIsBowled() {
    Frame frame = game.iterator().next();
    
    assertThat(frame.getFirstBall(), is(""));
    assertThat(frame.getSecondBall(), is(""));
  }

  @Test
  public void firstBallShouldBeAddedToTheFirstFrame() {
    game.bowl(3);
    
    Frame frame = game.iterator().next();
    assertThat(frame.getFirstBall(), is("3"));
  }

  @Test
  public void thirdBallShouldBeAddedToTheSecondFrame() {
    game.bowl(1);
    game.bowl(2);
    game.bowl(3);
    game.bowl(4);
    
    Iterator<Frame> frames = game.iterator();
    
    Frame frameOne = frames.next();
    assertThat(frameOne.getFirstBall(), is("1"));
    assertThat(frameOne.getSecondBall(), is("2"));

    Frame frameTwo = frames.next();
    assertThat(frameTwo.getFirstBall(), is("3"));
    assertThat(frameTwo.getSecondBall(), is("4"));
  }

  @Test
  public void thereShouldBeTenFrames() {
    int counter = 0;
    for (Iterator<Frame> frames = game.iterator(); frames.hasNext();) {
      frames.next();
      counter++;
    }
    assertThat(counter, is(10));
  }

  @Test
  public void frameScoreShouldAccumulate() {
    game.bowl(1);
    game.bowl(2);
    game.bowl(3);
    game.bowl(4);
    
    Iterator<Frame> frames = game.iterator();
    
    Frame frameOne = frames.next();
    assertThat(frameOne.getScore(), is("3"));

    Frame frameTwo = frames.next();
    assertThat(frameTwo.getScore(), is("10"));
  }

  @Test
  public void gameShouldShowCurrentScoreAfterEachBall() {
    game.bowl(9);
    assertThat(game.getScore(), is(9));
  }

  @Test
  public void aStrikeFrameHasOnlyOneBall() {
    game.bowl(10);
    game.bowl(2);
    game.bowl(3);
    
    Iterator<Frame> frames = game.iterator();
    
    Frame frameOne = frames.next();
    assertThat(frameOne.getFirstBall(), is("X"));

    Frame frameTwo = frames.next();
    assertThat(frameTwo.getFirstBall(), is("2"));
    assertThat(frameTwo.getSecondBall(), is("3"));
  }

}

