//
//  Shoe.swift
//  Baccarat
//
//  A shoe containing multiple decks of cards, used in baccarat.
//

import Foundation
import CasinoKit

/// Represents a shoe containing multiple decks of cards.
/// Standard baccarat uses 6-8 decks shuffled together.
struct Shoe {
    private var cards: [Card] = []
    
    /// The number of decks in this shoe.
    let deckCount: Int
    
    /// Number of cards remaining in the shoe.
    var cardsRemaining: Int {
        cards.count
    }
    
    /// Whether the shoe needs to be reshuffled (less than 20% remaining).
    var needsReshuffle: Bool {
        let totalCards = deckCount * 52
        return cards.count < totalCards / 5
    }
    
    /// Creates a new shoe with the specified number of decks.
    /// - Parameter deckCount: Number of decks to include (default: 8).
    init(deckCount: Int = 8) {
        self.deckCount = deckCount
        shuffle()
    }
    
    /// Shuffles all decks together to create a fresh shoe.
    mutating func shuffle() {
        cards = []
        
        for _ in 0..<deckCount {
            for suit in Suit.allCases {
                for rank in Rank.allCases {
                    cards.append(Card(suit: suit, rank: rank))
                }
            }
        }
        
        // Fisher-Yates shuffle for true randomness
        for i in stride(from: cards.count - 1, through: 1, by: -1) {
            let j = Int.random(in: 0...i)
            cards.swapAt(i, j)
        }
    }
    
    /// Deals a single card from the top of the shoe.
    /// - Returns: The dealt card, or nil if shoe is empty.
    mutating func deal() -> Card? {
        guard !cards.isEmpty else { return nil }
        return cards.removeFirst()
    }
    
    /// Burns (discards) a specified number of cards from the shoe.
    /// - Parameter count: Number of cards to burn.
    mutating func burn(_ count: Int) {
        for _ in 0..<min(count, cards.count) {
            _ = cards.removeFirst()
        }
    }
}

