import static org.junit.jupiter.api.Assertions.*;
import org.junit.jupiter.api.Test;

public class BlackjackHandTester
{
    public void testConstant()
    {
        assertEquals(21, BlackjackHand.MAX_HAND_VALUE);
    }
    
    @Test
    public void testGetNumericalValueTwoBlackjackCardsNoAces()
    {
        // 6 5
        BlackjackHand hand =
                new BlackjackHand(new BlackjackCard(6, "S"), new BlackjackCard(5, "C"));
        assertEquals(11, hand.getNumericalValue());

        // 6 K
        hand = new BlackjackHand(
                new BlackjackCard(6, "C"),
                new BlackjackCard(BlackjackCard.KING_VALUE, "S"));
        assertEquals(16, hand.getNumericalValue());

        // Q K
        hand = new BlackjackHand(
                new BlackjackCard(BlackjackCard.QUEEN_VALUE, "D"),
                new BlackjackCard(BlackjackCard.KING_VALUE, "D"));
        assertEquals(20, hand.getNumericalValue());
    }

    @Test
    public void testGetNumericalValueTwoBlackjackCardsWithAce()
    {
        // Q A
        BlackjackHand hand = new BlackjackHand(
                new BlackjackCard(BlackjackCard.QUEEN_VALUE, "C"),
                new BlackjackCard(BlackjackCard.ACE_VALUE, "C"));
        assertEquals(21, hand.getNumericalValue());

        // A 9
        hand = new BlackjackHand(
                new BlackjackCard(BlackjackCard.ACE_VALUE, "H"),
                new BlackjackCard(9, "C"));
        assertEquals(20, hand.getNumericalValue());

        // 3 A
        hand = new BlackjackHand(
                new BlackjackCard(3, "C"),
                new BlackjackCard(BlackjackCard.ACE_VALUE, "C"));
        assertEquals(14, hand.getNumericalValue());

        // A A
        hand = new BlackjackHand(
                new BlackjackCard(BlackjackCard.ACE_VALUE, "C"),
                new BlackjackCard(BlackjackCard.ACE_VALUE, "C"));
        assertEquals(12, hand.getNumericalValue());
    }

    @Test
    public void testGetNumericalValueMultipleBlackjackCardsNoAces()
    {
        // 10 3 Q (23)
        BlackjackHand hand = new BlackjackHand(
                new BlackjackCard(10, "D"),
                new BlackjackCard(3, "H"));
        hand.addCard(new BlackjackCard(BlackjackCard.QUEEN_VALUE, "H"));
        assertEquals(23, hand.getNumericalValue());

        // 6 5 10 (21)
        hand = new BlackjackHand(
                new BlackjackCard(6, "S"), new BlackjackCard(5, "D"));
        hand.addCard(new BlackjackCard(10, "H"));
        assertEquals(21, hand.getNumericalValue());

        // 7 4 4 3 (18)
        hand = new BlackjackHand(new BlackjackCard(7, "S"), new BlackjackCard(4, "C"));
        hand.addCard(new BlackjackCard(4, "D"));
        hand.addCard(new BlackjackCard(3, "S"));
        assertEquals(18, hand.getNumericalValue());
    }

    @Test
    public void testGetNumericalValueMultipleBlackjackCardsWithAces()
    {
        // 7 A (18)
        BlackjackHand hand = new BlackjackHand(
                new BlackjackCard(7, "H"), new BlackjackCard(BlackjackCard.ACE_VALUE, "D"));
        assertEquals(18, hand.getNumericalValue());

        // 7 A 4 (12)
        hand.addCard(new BlackjackCard(4, "S"));
        assertEquals(12, hand.getNumericalValue());

        // 7 A 4 A (13)
        hand.addCard(new BlackjackCard(BlackjackCard.ACE_VALUE, "C"));
        assertEquals(13, hand.getNumericalValue());

        // A 2 A (14)
        hand = new BlackjackHand(
                new BlackjackCard(BlackjackCard.ACE_VALUE, "S"),
                new BlackjackCard(2, "C"));
        hand.addCard(new BlackjackCard(BlackjackCard.ACE_VALUE, "D"));
        assertEquals(14, hand.getNumericalValue());

        // A 4 A A (17)
        hand = new BlackjackHand(
                new BlackjackCard(BlackjackCard.ACE_VALUE, "S"),
                new BlackjackCard(4, "C"));
        hand.addCard(new BlackjackCard(BlackjackCard.ACE_VALUE, "D"));
        hand.addCard(new BlackjackCard(BlackjackCard.ACE_VALUE, "H"));
        assertEquals(17, hand.getNumericalValue());

        // A A 10 (12)
        hand = new BlackjackHand(
                new BlackjackCard(BlackjackCard.ACE_VALUE, "S"),
                new BlackjackCard(BlackjackCard.ACE_VALUE, "C"));
        hand.addCard(new BlackjackCard(10, "D"));
        assertEquals(12, hand.getNumericalValue());
    }

    @Test
    public void testIsBlackjack()
    {
        // blackjack with A 10
        BlackjackHand hand = new BlackjackHand(
                new BlackjackCard(BlackjackCard.ACE_VALUE, "H"),
                new BlackjackCard(10, "D"));
        assertEquals(true, hand.isBlackjack());

        // bj with 10 A
        hand = new BlackjackHand(
                new BlackjackCard(10, "C"),
                new BlackjackCard(BlackjackCard.ACE_VALUE, "S"));
        assertEquals(true, hand.isBlackjack());

        // bj with Q A
        hand = new BlackjackHand(
                new BlackjackCard(BlackjackCard.QUEEN_VALUE, "C"),
                new BlackjackCard(BlackjackCard.ACE_VALUE, "S"));
        assertEquals(true, hand.isBlackjack());

        // bj with A J
        hand = new BlackjackHand(
                new BlackjackCard(BlackjackCard.ACE_VALUE, "D"),
                new BlackjackCard(BlackjackCard.JACK_VALUE, "H"));
        assertEquals(true, hand.isBlackjack());

        // 2 cards not blackjack (under 21)
        hand = new BlackjackHand(new BlackjackCard(9, "D"), new BlackjackCard(7, "H"));
        assertEquals(false, hand.isBlackjack());

        // 3 cards not blackjack (21)
        hand = new BlackjackHand(new BlackjackCard(9, "D"), new BlackjackCard(7, "H"));
        hand.addCard(new BlackjackCard(5, "C"));
        assertEquals(false, hand.isBlackjack());

        // 3 cards not blackjack (under 21)
        hand = new BlackjackHand(new BlackjackCard(9, "D"), new BlackjackCard(7, "H"));
        hand.addCard(new BlackjackCard(4, "C"));
        assertEquals(false, hand.isBlackjack());

        // 3 cards not blackjack (over 21)
        hand = new BlackjackHand(new BlackjackCard(9, "D"), new BlackjackCard(7, "H"));
        hand.addCard(new BlackjackCard(6, "C"));
        assertEquals(false, hand.isBlackjack());
    }
    
    @Test
    public void testIsBust()
    {
        BlackjackHand hand = new BlackjackHand(
                new BlackjackCard(10, "S"), new BlackjackCard(8, "H"));
        
        assertTrue( ! hand.isBust() );
        
        hand.addCard(new BlackjackCard(2, "C"));
        assertTrue( ! hand.isBust() );
        
        
        hand = new BlackjackHand(
                new BlackjackCard(BlackjackCard.JACK_VALUE, "S"),
                new BlackjackCard(BlackjackCard.ACE_VALUE, "H"));
        
        assertTrue( ! hand.isBust() );
        
        
        hand = new BlackjackHand(
                new BlackjackCard(10, "S"), new BlackjackCard(6, "H"));
        
        assertTrue( ! hand.isBust() );
        
        hand.addCard(new BlackjackCard(6, "C"));
        assertTrue(hand.isBust());
        
        
        hand = new BlackjackHand(
                new BlackjackCard(10, "S"), new BlackjackCard(4, "H"));
        
        hand.addCard(new BlackjackCard(BlackjackCard.ACE_VALUE, "H"));
        assertTrue( ! hand.isBust() );
        
        hand.addCard(new BlackjackCard(BlackjackCard.ACE_VALUE, "S"));
        assertTrue( ! hand.isBust() );
        
        hand.addCard(new BlackjackCard(6, "S"));
        assertTrue(hand.isBust());
    }

    @Test
    public void testToString()
    {
        // JS AH (21)
        BlackjackHand hand = new BlackjackHand(
                new BlackjackCard(BlackjackCard.JACK_VALUE, "S"),
                new BlackjackCard(BlackjackCard.ACE_VALUE, "H"));
        assertEquals("JS AH (21)", hand.toString());

        // 10C 9S (19)
        hand = new BlackjackHand(new BlackjackCard(10, "C"), new BlackjackCard(9, "S"));
        assertEquals("10C 9S (19)", hand.toString());

        // 7H 4D 3H (14)
        hand = new BlackjackHand(new BlackjackCard(7, "H"), new BlackjackCard(4, "D"));
        hand.addCard(new BlackjackCard(3, "H"));
        assertEquals("7H 4D 3H (14)", hand.toString());
    }
    
    @Test
    public void testCanAddCard()
    {
        BlackjackHand hand = new BlackjackHand(
                new BlackjackCard(5, "S"), new BlackjackCard(8, "D"));
        
        assertTrue(hand.canAddCard());
        
        hand.addCard(new BlackjackCard(7, "H"));
        assertTrue(hand.canAddCard());
        
        hand.addCard(new BlackjackCard(4, "S"));
        assertTrue(! hand.canAddCard() );
    }
}
