//
//  Deck.swift
//  CasinoKit
//
//  A deck of playing cards with shuffle and draw functionality.
//

import Foundation

/// A deck of playing cards that can be shuffled and dealt from.
public struct Deck: Sendable {
    /// The cards remaining in the deck.
    public private(set) var cards: [Card]
    
    /// The number of standard 52-card decks used to create this deck.
    public let deckCount: Int
    
    /// The number of cards remaining in the deck.
    public var cardsRemaining: Int {
        cards.count
    }
    
    /// Whether the deck is empty.
    public var isEmpty: Bool {
        cards.isEmpty
    }
    
    /// Creates a new deck with the specified number of standard 52-card decks.
    /// - Parameter deckCount: The number of decks to combine (default: 1).
    public init(deckCount: Int = 1) {
        self.deckCount = deckCount
        self.cards = Self.createCards(deckCount: deckCount)
    }
    
    /// Creates cards for the specified number of decks.
    private static func createCards(deckCount: Int) -> [Card] {
        var cards: [Card] = []
        for _ in 0..<deckCount {
            for suit in Suit.allCases {
                for rank in Rank.allCases {
                    cards.append(Card(suit: suit, rank: rank))
                }
            }
        }
        return cards
    }
    
    /// Shuffles the deck using Fisher-Yates algorithm.
    public mutating func shuffle() {
        cards.shuffle()
    }
    
    /// Draws a card from the top of the deck.
    /// - Returns: The drawn card, or nil if the deck is empty.
    public mutating func draw() -> Card? {
        guard !cards.isEmpty else { return nil }
        return cards.removeFirst()
    }
    
    /// Draws multiple cards from the deck.
    /// - Parameter count: The number of cards to draw.
    /// - Returns: An array of drawn cards (may be fewer than requested if deck runs low).
    public mutating func draw(_ count: Int) -> [Card] {
        var drawn: [Card] = []
        for _ in 0..<count {
            if let card = draw() {
                drawn.append(card)
            }
        }
        return drawn
    }
    
    /// Resets the deck to its original state with all cards.
    public mutating func reset() {
        cards = Self.createCards(deckCount: deckCount)
    }
    
    /// Resets and shuffles the deck.
    public mutating func resetAndShuffle() {
        reset()
        shuffle()
    }
}

