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

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

# Shuffle function
shuffle_deck <- function() {
  deck <- expand.grid(Value = values, Suit = suits, stringsAsFactors = FALSE)
  deck <- deck[sample(nrow(deck)), ]  # Shuffle the deck
  deck$Value <- as.character(deck$Value)  # Ensure 'Value' column is treated as characters
  return(deck)
}

# Mapping numerical values to card ranks for comparison
card_values <- c("2" = 2, "3" = 3, "4" = 4, "5" = 5, "6" = 6, "7" = 7, "8" = 8, "9" = 9, "10" = 10, 
                 "J" = 11, "Q" = 12, "K" = 13, "A" = 14)

# Function to get the numeric value of a card
get_card_value <- function(card) {
  return(card_values[as.character(card)])
}

# Function to display card images
display_card_image <- function(value, suit) {
  # Construct the file name from the value and suit
  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 calculate the odds of the next card being higher, lower, or the same
calculate_probabilities <- function(deck, prev_card_value) {
  remaining_higher <- sum(sapply(deck$Value, function(x) get_card_value(x) > prev_card_value))
  remaining_lower <- sum(sapply(deck$Value, function(x) get_card_value(x) < prev_card_value))
  remaining_same <- sum(sapply(deck$Value, function(x) get_card_value(x) == prev_card_value))
  total_remaining <- remaining_higher + remaining_lower + remaining_same
  
  prob_higher <- remaining_higher / total_remaining
  prob_lower <- remaining_lower / total_remaining
  prob_same <- remaining_same / total_remaining
  
  return(list(higher = prob_higher, lower = prob_lower, same = prob_same))
}

# Function to display cards in a grid layout
display_cards_grid <- function(cards) {
  # Collect card images as grobs
  card_images <- lapply(1:nrow(cards), function(i) {
    display_card_image(cards$Value[i], cards$Suit[i])
  })
  
  # Remove NULL images
  card_images <- card_images[!sapply(card_images, is.null)]
  
  # Arrange the images in a grid layout
  grid.arrange(grobs = card_images, ncol = 5)
}

# Function to play the game with probabilities
play_game <- function(deck = NULL, replaced_card = NULL) {
  deck <- shuffle_deck()
  row1 <- deck[1:10, ]
  dealt_cards <- row1
  
  print("Cards dealt (face down):")
  print(dealt_cards)
  
  cat("\nYou have the option to replace the first card before turning it over.\n")
  replace_first <- readline(prompt = "Do you want to replace the first card with the next one (11th in pack)? (y/n): ")
  
  if (tolower(replace_first) == "y") {
    cat("\nReplacing the first card with the 11th card...\n")
    first_card <- deck[11, ]
    replaced_card <- dealt_cards[1, ]
    deck <- deck[-11, ]
    
    # Update dealt_cards with the replaced first card
    dealt_cards[1, ] <- first_card
  } else {
    first_card <- dealt_cards[1, ]
  }
  
  cat("\nFirst card turned over:", paste(first_card$Value, "of", first_card$Suit), "\n")
  
  # Display the first card
  display_cards_grid(dealt_cards[1, , drop = FALSE])
  
  deck <- deck[-1, ]
  prev_card <- first_card
  prev_value <- get_card_value(prev_card$Value)
  
  for (i in 2:nrow(dealt_cards)) {
    current_card <- dealt_cards[i, ]
    probs <- calculate_probabilities(deck, prev_value)
    
    cat(sprintf("Probability of next card being higher: %.2f%%\n", probs$higher * 100))
    cat(sprintf("Probability of next card being lower: %.2f%%\n", probs$lower * 100))
    cat(sprintf("Probability of next card being the same: %.2f%%\n", probs$same * 100))
    
    prediction <- readline(prompt = paste("Will the next card be higher or lower than", 
                                          paste(prev_card$Value, "of", prev_card$Suit), "? (h/l): "))
    
    current_value <- get_card_value(current_card$Value)
    
    if (is.na(current_value) || is.na(prev_value)) {
      cat("Error: Invalid card values. Please check the card value mappings.\n")
      break
    }
    
    cat("Next card:", paste(current_card$Value, "of", current_card$Suit), "\n")
    
    # Display all cards revealed so far, updating after each new card
    display_cards_grid(dealt_cards[1:i, ])
    
    if (current_value == prev_value) {
      cat("Same value card! Game over.\n")
      break
    }
    
    if ((prediction == "h" && current_value > prev_value) ||
        (prediction == "l" && current_value < prev_value)) {
      cat("Correct!\n")
    } else {
      cat("Incorrect! Game over.\n")
      break
    }
    
    prev_card <- current_card
    prev_value <- current_value
    deck <- deck[-1, ]
    
    if (i == nrow(dealt_cards)) {
      cat("Congratulations! You predicted all the cards correctly and won the game!\n")
    }
  }
  
  play_again <- readline(prompt = "Do you want to play again? (y/n): ")
  
  if (tolower(play_again) == "y") {
    play_game()
  } else {
    cat("Thank you for playing!\n")
  }
}

# Start the game
play_game()
## [1] "Cards dealt (face down):"
##    Value     Suit
## 51     K   Spades
## 49     J   Spades
## 39     A    Clubs
## 19     7 Diamonds
## 12     K   Hearts
## 2      3   Hearts
## 23     J Diamonds
## 26     A Diamonds
## 1      2   Hearts
## 25     K Diamonds
## 
## You have the option to replace the first card before turning it over.
## Do you want to replace the first card with the next one (11th in pack)? (y/n): 
## 
## First card turned over: K of Spades

## Probability of next card being higher: 7.84%
## Probability of next card being lower: 86.27%
## Probability of next card being the same: 5.88%
## Will the next card be higher or lower than K of Spades ? (h/l): 
## Next card: J of Spades

## Incorrect! Game over.
## Do you want to play again? (y/n): 
## Thank you for playing!