from random import randint

class Card:
  def __init__(self, cardRank, cardSuit, cardPointVal):
    self.rank = cardRank
    self.suit = cardSuit
    self.pointVal = cardPointVal

  def getSuit(self):
    return self.suit

  def getRank(self):
    return self.rank

  def getPointVal(self):
    return self.pointVal

class Deck:
  def __init__(self, suits, ranks, values):
    self.cards = []
    self.suits = suits
    self.ranks = ranks
    self.values = values

    for rank, value in zip(self.ranks, self.values):
      for suit in suits:
        self.cards.append(Card(rank, suit, value))

  def getCards(self):
    return self.cards

  def getCard(self, index):
    return self.cards[index]

  def setCard(self, index, myCard):
    self.cards[index] = myCard

mySuits = ['hearts', 'diamonds', 'clubs', 'spades']
myRanks = ['ace', '2', '3', '4', '5', '6', '7', '8', '9', '10', 'jack', 'queen', 'king']
myPointVals = [1,2,3,4,5,6,7,8,9,10,10,10,10]
myDeck = Deck(mySuits, myRanks, myPointVals)

def randomShuffle():
  shufflenum = int(input("How many times would you like to shuffle the deck?\n"))
  for i in range(shufflenum):
    for i in range(len(myDeck.cards)-1, 0, -1):
      j = randint(0, i)
      temp = myDeck.cards[i]
      myDeck.cards[i] = myDeck.cards[j]
      myDeck.cards[j] = temp

player = []
dealer = []
cardspassed = 0
endcondition = False

def dealtoplayer():
  global cardspassed
  player.append(myDeck.cards[cardspassed])
  cardspassed += 1

def dealtodealer():
  global cardspassed
  dealer.append(myDeck.cards[cardspassed])
  cardspassed += 1

def dealcards():
  dealtoplayer()
  dealtodealer()

def calculate_score(hand):
  score = 0
  ace_count = 0
  for card in hand:
    score += card.getPointVal()
    if card.getRank() == 'ace':
      ace_count += 1

  while ace_count > 0 and score + 10 <= 21:
    score += 10
    ace_count -= 1
  return score

def checkscore():
  global playerscore
  global dealerscore
  playerscore = calculate_score(player)
  dealerscore = calculate_score(dealer)

  print(f'\nPlayer, your score is {playerscore}')
  print(f'Dealer, your score is {dealerscore}')

def checkcards():
  print("\nPlayer, your cards are:\n-------------------------")
  for card in player:
    print(f'{card.getRank()} of {card.getSuit()}')

  print("\nDealer, your cards are:\n-------------------------")
  for card in dealer:
    print(f'{card.getRank()} of {card.getSuit()}')

def getchoice():
  global dealerout
  global playerout
  dealerout = False
  playerout = False
  while not dealerout and not playerout:
    hitorstay = input("\nPlayer, would you like to hit or stay? [Hit/Stay]").lower()
    while hitorstay != 'hit' and hitorstay != 'stay':
      print("Invalid input, please try again.")
      hitorstay = input("\nPlayer, would you like to hit or stay? [Hit/Stay]").lower()
    if hitorstay == 'hit':
      hit()
      checkcards()
      checkscore()
      if playerscore >= 21 or dealerscore >= 21:
        break
    elif hitorstay == 'stay':
      stay()
      checkcards()
      checkscore()
      break

def hit():
  print("\nPlayer hits!")
  dealtoplayer()
  if dealerscore <= 16:
    dealtodealer()
    print("Dealer hits!")
  else:
    print("Dealer stays!")

def stay():
  print("\nPlayer stays!")
  if dealerscore <= 16:
    dealtodealer()
    print("Dealer hits!")
  else:
    print("Dealer stays!")

def checkendcondition():
  global playerscore
  global dealerscore
  if playerscore == dealerscore:
    print("\nBOTH PLAYER AND DEALER HAVE THE SAME SCORE! IT'S A TIE!")
  elif playerscore > 21:
    checkace()
    if playerace:
      print("\nPlayer was going to bust, but then was saved because they had an ace!")
      playerscore -= 10
      print(f'\nPlayer, your score is {playerscore}')
      print(f'\nDealer, your score is {dealerscore}')
      if playerscore > dealerscore:
        print("\nPLAYER HAS A HIGHER SCORE THAN DEALER. PLAYER WINS! DEALER LOSES!")
      elif playerscore < dealerscore:
        print("\nDEALER HAS A HIGHER SCORE THAN PLAYER. DEALER WINS! PLAYER LOSES!")
      else:
        print("\nBOTH PLAYER AND DEALER HAVE THE SAME SCORE! IT'S A TIE!")
    else:
      print("\nPLAYER BUSTED! PLAYER LOSES! DEALER WINS!")
  elif dealerscore > 21:
    checkace()
    if dealerace:
      print("\nDealer was going to bust, but then was saved because they had an ace!")
      dealerscore -= 10
      print(f'\nPlayer, your score is {playerscore}')
      print(f'\nDealer, your score is {dealerscore}')
      if playerscore > dealerscore:
        print("\nPLAYER HAS A HIGHER SCORE THAN DEALER. PLAYER WINS! DEALER LOSES!")
      elif playerscore < dealerscore:
        print("\nDEALER HAS A HIGHER SCORE THAN PLAYER. DEALER WINS! PLAYER LOSES!")
      else:
        print("\nBOTH PLAYER AND DEALER HAVE THE SAME SCORE! IT'S A TIE!")
    else:
      print("\nDEALER BUSTED! DEALER LOSES! PLAYER WINS!")
  elif playerscore == 21 and dealerscore != 21:
    print("\nPLAYER BLACKJACK! PLAYER WINS! DEALER LOSES!")
  elif dealerscore == 21 and playerscore != 21:
    print("\nDEALER BLACKJACK! DEALER WINS! PLAYER LOSES!")
  elif playerscore == 21 and dealerscore == 21:
    print("\nIT'S A TIE! BOTH PLAYERS HAVE BLACKJACK!")
  elif playerscore > dealerscore:
    print("\nPLAYER HAS A HIGHER SCORE THAN DEALER. PLAYER WINS!")
  elif playerscore < dealerscore:
    print("\nDEALER HAS A HIGHER SCORE THAN PLAYER. DEALER WINS!")

def blackjack():
  randomShuffle()

  print("\nWelcome to Blackjack!")
  for i in range(2):
    dealcards()
  print("The cards have been dealt!")

  checkcards()
  checkscore()

  if playerscore == 21 and dealerscore != 21:
    print("\nPLAYER BLACKJACK (NATURAL)! PLAYER WINS! DEALER LOSES!")
    return
  elif dealerscore == 21 and playerscore != 21:
    print("\nDEALER BLACKJACK (NATURAL)! DEALER WINS! PLAYER LOSES!")
    return
  elif playerscore == 21 and dealerscore == 21:
    print("\nIT'S A TIE! BOTH PLAYER AND DEALER HAVE BLACKJACK (NATURAL)!")
    return

  getchoice()
  checkendcondition()

blackjack()

Welcome to Blackjack!
The cards have been dealt!

Player, your cards are:
-------------------------
ace of spades
9 of spades

Dealer, your cards are:
-------------------------
king of diamonds
2 of spades

Player, your score is 20
Dealer, your score is 12
Invalid input, please try again.

Player hits!
Dealer hits!

Player, your cards are:
-------------------------
ace of spades
9 of spades
queen of clubs

Dealer, your cards are:
-------------------------
king of diamonds
2 of spades
queen of diamonds

Player, your score is 20
Dealer, your score is 22

DEALER BUSTED! DEALER LOSES! PLAYER WINS!