import java.text.NumberFormat;
import java.util.Scanner;

/**
 * A text based user interface that allows the user to
 * play a simplified version of the game of blackjack
 * (excluding splitting and doubling).
 */
public class BlackjackUI
{
    private Blackjack bj; 
    private Scanner fromKeyboard;
    private NumberFormat nf;

    /**
     * Constructs a blackjack game with $1,000 in player bankroll
     */
    public BlackjackUI()
    {
        bj = new Blackjack(1000);
        fromKeyboard = new Scanner(System.in);
        nf = NumberFormat.getCurrencyInstance();
    }

    /**
     * Plays a single hand of blackjack
     */
    public void playHand()
    {
        bj.placeInitialBetAndDealCards(getValidBet());
        printHands();

        playPlayersHand();
        bj.playDealersHand();
        printHands();

        displayResult();
        bj.resolveBetsAndReset();
    }

    /**
     * Plays blackjack hands until the user chooses to quit
     */
    public void playHandsUntilQuit()
    {
        System.out.println("Money: " + nf.format(bj.getPlayersMoney()));
        
        boolean playAgain = true;
        
        while(playAgain)
        {
            playHand();

            System.out.println("\nMoney: " + nf.format(bj.getPlayersMoney()));
            
            if(bj.getPlayersMoney() > 0)
            {
                System.out.print("Play again (y/n): ");
                playAgain = fromKeyboard.next().toLowerCase().startsWith("y");
            }
            else
                playAgain = false;
        }
    }

    /**
     * Allows the player to hit until it is no longer possible
     * to do so or until the player chooses to stand
     */
    private void playPlayersHand()
    {
        boolean canHitAgain = bj.canHit();
        
        while(canHitAgain)
        {
            System.out.print("Hit? (y/n): ");
            boolean hit = fromKeyboard.next().toLowerCase().startsWith("y");
            
            if(hit)
                bj.hit();
            else
                bj.stand();

            canHitAgain = bj.canHit() && hit;

            if(canHitAgain)
                printHands();
        }
    }

    /**
     * Displays the result of the hand (push,
     * player win, player blackjack or loss)
     */
    private void displayResult()
    {
        System.out.print("Result: ");
        
        if(bj.getResult() == 0)
            System.out.println("push");
        else if(bj.getResult() > 0)
        {
            if(bj.getResult() == 2)
                System.out.println("blackjack");
            else
                System.out.println("win");
        }
        else
            System.out.println("loss");
    }

    /**
     * Returns the numeric representation of input or -1 if input is not numeric
     * @param input the value to be converted to a number
     * @return numeric representation or -1
     */
    private double stringToNumber(String input)
    {
        try
        {
            return Double.parseDouble(input);
        }
        catch(NumberFormatException e)
        {
            return -1;
        }
    }

    /**
     * Returns a valid numerical bet obtained from the player
     * @return a valid numerical bet obtained from the player
     */
    private double getValidBet()
    {
        System.out.println();
        System.out.print("Bet: $");

        String input = fromKeyboard.next();
        double bet = stringToNumber(input);
        
        while(bet <= 0 || bet > bj.getPlayersMoney())
        {
            System.out.println("Invalid bet");
            System.out.print("Bet: $");

            input = fromKeyboard.next();
            bet = stringToNumber(input);
        }

        return bet;
    }

    /**
     * Displays the face up portion of the dealer's and player's hands
     */
    private void printHands()
    {
        System.out.println();
        System.out.println("Dealer: " + bj.getFaceUpDealersHand());
        System.out.println("Player: " + bj.getPlayersHand());
    }
}
