# Load required libraries
pacman::p_load(pacman, dplyr, grid, gridExtra, png)

# Create the full deck of cards based on the number of decks
suits <- c("Hearts", "Diamonds", "Clubs", "Spades")
values <- c(2:10, "J", "Q", "K", "A")

# Shuffle function to create a deck with multiple packs
shuffle_deck <- function(num_decks = 1) {
  deck <- expand.grid(Value = values, Suit = suits, stringsAsFactors = FALSE)
  full_deck <- do.call(rbind, replicate(num_decks, deck, simplify = FALSE))  # Replicate the deck based on num_decks
  full_deck <- full_deck[sample(nrow(full_deck)), ]  # Shuffle the deck
  full_deck$Value <- as.character(full_deck$Value)  # Ensure 'Value' column is treated as characters
  return(full_deck)
}

# Blackjack card values
blackjack_values <- c("2" = 2, "3" = 3, "4" = 4, "5" = 5, "6" = 6, "7" = 7, "8" = 8, "9" = 9, "10" = 10, 
                      "J" = 10, "Q" = 10, "K" = 10, "A" = 11)  # Ace can also be 1, handle separately

# Function to get the blackjack value of a card
get_blackjack_value <- function(card) {
  return(blackjack_values[as.character(card)])
}

# Function to calculate the value of a hand in Blackjack
calculate_hand_value <- function(cards) {
  values <- sapply(cards$Value, get_blackjack_value)  # Get the numeric values of the cards
  total_value <- sum(values)  # Sum up the values
  
  # Adjust for Aces (Ace can be 1 or 11)
  num_aces <- sum(cards$Value == "A")
  while (total_value > 21 && num_aces > 0) {
    total_value <- total_value - 10  # Treat an Ace as 1 instead of 11
    num_aces <- num_aces - 1
  }
  
  return(total_value)
}

# Function to display card images
display_card_image <- function(value, suit, face_down = FALSE) {
  if (face_down) {
    file_name <- "back_of_card.png"  # Path to the back of the card image
  } else {
    file_name <- paste0(tolower(value), "_of_", tolower(suit), ".png")
  }
  
  # Load the image from the file path
  img_path <- file.path("cards", file_name)
  
  if (file.exists(img_path)) {
    img <- readPNG(img_path)
    return(rasterGrob(img))
  } else {
    cat("Card image not found:", img_path, "\n")
    return(NULL)
  }
}

# Function to display the cards in two rows (with dealer's face-down card option)
display_blackjack_table <- function(dealer_cards, player_cards, reveal_dealer = FALSE) {
  dealer_images <- lapply(1:nrow(dealer_cards), function(i) {
    face_down <- ifelse(i == 2 && !reveal_dealer, TRUE, FALSE)  # Dealer's second card face down if not reveal_dealer
    display_card_image(dealer_cards$Value[i], dealer_cards$Suit[i], face_down = face_down)
  })
  
  player_images <- lapply(1:nrow(player_cards), function(i) {
    display_card_image(player_cards$Value[i], player_cards$Suit[i])
  })
  
  # Arrange dealer and player cards in rows
  grid.arrange(gridExtra::arrangeGrob(grobs = dealer_images, ncol = nrow(dealer_cards)),
               gridExtra::arrangeGrob(grobs = player_images, ncol = nrow(player_cards)),
               nrow = 2)
}

# Main game function for Blackjack with deck selection and replay option
play_blackjack <- function(deck = NULL, num_decks = NULL) {
  # If no deck is provided (first game or reshuffle), ask how many decks to use
  if (is.null(deck) || nrow(deck) < 10) {  # Check if deck needs reshuffling
    if (is.null(num_decks)) {
      num_decks <- as.integer(readline(prompt = "How many decks do you want to play with? (Typical casino uses 6 or 8): "))
      if (is.na(num_decks) || num_decks < 1) {
        cat("Invalid input. Using 1 deck.\n")
        num_decks <- 1
      }
    }
    
    deck <- shuffle_deck(num_decks)  # Shuffle new deck with selected number of decks
  } else {
    cat("Continuing with the current deck...\n")
  }
  
  # Deal two cards to both player and dealer
  player_cards <- deck[1:2, ]
  dealer_cards <- deck[3:4, ]
  deck <- deck[-(1:4), ]  # Remove the dealt cards from the deck
  
  # Display the initial deal with dealer's second card face down
  cat("Initial cards dealt:\n")
  display_blackjack_table(dealer_cards, player_cards, reveal_dealer = FALSE)  # Face down for dealer's second card
  
  # Player's turn
  player_hand_value <- calculate_hand_value(player_cards)
  while (player_hand_value < 21) {
    cat("Your hand value is:", player_hand_value, "\n")
    action <- readline(prompt = "Do you want to hit or stand? (h/s): ")
    
    if (tolower(action) == "h") {
      new_card <- deck[1, ]
      deck <- deck[-1, ]  # Remove the new card from the deck
      player_cards <- rbind(player_cards, new_card)
      display_blackjack_table(dealer_cards, player_cards, reveal_dealer = FALSE)  # Still face down
      player_hand_value <- calculate_hand_value(player_cards)
    } else if (tolower(action) == "s") {
      break
    } else {
      cat("Invalid input. Please enter 'h' for hit or 's' for stand.\n")
    }
  }
  
  if (player_hand_value > 21) {
    cat("Bust! Your hand value is:", player_hand_value, ". You lose.\n")
    replay_game(deck, num_decks)  # Pass the current deck and num_decks to the replay function
    return()
  }
  
  # Dealer's turn: reveal face-down card and follow rules
  cat("\nDealer's turn:\n")
  display_blackjack_table(dealer_cards, player_cards, reveal_dealer = TRUE)  # Reveal dealer's second card
  dealer_hand_value <- calculate_hand_value(dealer_cards)
  
  # Dealer hits until hand value is 17 or higher OR until the hand value is at least as high as the player's hand (without busting)
  while (dealer_hand_value < 17 || (dealer_hand_value < player_hand_value && dealer_hand_value <= 21)) {
    cat("Dealer's hand value is:", dealer_hand_value, "\n")
    new_card <- deck[1, ]
    deck <- deck[-1, ]
    dealer_cards <- rbind(dealer_cards, new_card)
    display_blackjack_table(dealer_cards, player_cards, reveal_dealer = TRUE)
    dealer_hand_value <- calculate_hand_value(dealer_cards)
  }
  
  # Determine the outcome without printing the bust message twice
  if (dealer_hand_value > 21) {
    cat("Dealer busts! Dealer's hand value is:", dealer_hand_value, ". You win!\n")
  } else {
    cat("Dealer stands with a hand value of:", dealer_hand_value, "\n")
    
    # Determine the final outcome after the dealer stands
    if (dealer_hand_value > player_hand_value) {
      cat("Dealer wins with a hand value of:", dealer_hand_value, "\n")
    } else if (dealer_hand_value < player_hand_value) {
      cat("You win with a hand value of:", player_hand_value, "\n")
    } else {
      cat("It's a tie! Both have a hand value of:", player_hand_value, "\n")
    }
  }
  
  # Ask if the player wants to play again
  replay_game(deck, num_decks)
}

# Function to ask if the player wants to play again, without shuffling if they continue
replay_game <- function(deck, num_decks) {
  play_again <- readline(prompt = "Do you want to play again? (y/n): ")
  
  if (tolower(play_again) == "y") {
    play_blackjack(deck, num_decks)  # Continue with the same deck and number of decks
  } else {
    cat("Thanks for playing!\n")
  }
}

# Start the game with no deck passed initially (fresh start)
play_blackjack()