package kevin.lawrence.bowling;

public class Frame {
  public static final int PINS_IN_FRAME = 10;
  
  private Integer[] balls = new Integer[3];
  private int ballCount;
  private Frame previousFrame;
  private boolean lastFrame;

  public Frame(Frame previousFrame, boolean lastFrame) {
    this.previousFrame = previousFrame;
    this.lastFrame = lastFrame;
  }

  public String getFirstBall() {
    if(isStrike()){
      return "X";
    }
    return formatBall(balls[0]);
  }

  public String getSecondBall() {
    if(isStrike() && ! lastFrame){
      return "";
    }
    if(isSpare()){
      return "/";
    }
    return formatBall(balls[1]);
  }

  public String getThirdBall() {
    return formatBall(balls[2]);
  }

  private String formatBall(Integer ball) {
    if (ball == null) {
      return "";
    }
    else if(ball == 0){
      return "-";
    }
    else {
      return ball.toString();
    }
  }

  public void addBall(int pins) {
    if(pins > PINS_IN_FRAME || pins < 0) {
      throw new IllegalArgumentException("Invalid pin count - " + pins);
    }
    
    if(! isStrike()){
      if(ballCount == 1 && balls[0] + pins > PINS_IN_FRAME) {
        throw new IllegalArgumentException("Total pin count invalid");
      }
    }
    
    balls[ballCount++] = new Integer(pins);
  }

  public boolean needsMoreBalls() {
    return (isStrike() || isSpare()) && ballCount < 3
        || ballCount < 2;
  }

  public String getScore() {
    return needsMoreBalls() 
         ? "" 
         : Integer.toString(getCumulativeScore());
  }

  public int getCumulativeScore() {
    int cumulativeScore = 0;
    
    for(Integer ball : balls) {
      if(ball != null){
        cumulativeScore += ball;
      }
    }
    
    if(previousFrame != null){
      cumulativeScore += previousFrame.getCumulativeScore();
    }

    return cumulativeScore; 
  }

  public boolean isStrike() {
    return ballCount > 0 && balls[0] == 10;
  }

  public boolean isComplete() {
    return ballCount == 2 || isStrike();
  }

  public boolean isSpare() {
    return ballCount >= 2 
        && balls[0] + balls[1] == PINS_IN_FRAME
        && !isStrike();
  }
  
}
