1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
use std::result::Result;
use std::vec::Vec;

use super::*;

/// The `Deck` represents a deck of zero or more cards. Internally the
/// deck consists of an undealt and a dealt pile of cards. The undealt pile starts off empty and
/// receives cards as they are dealt from the undealt pile.
///
/// The deck may be reset to return it to its original state. A deck may be shuffled to randomize
/// its order.
///
/// A deck can contain more than one card with the same rank / suit combination.
///
/// A deck cannot have more cards added or removed to it once it is created.
///
#[derive(Clone)]
pub struct Deck {
    /// A deck contains zero or more cards
    cards: Vec<Card>,
    /// Dealt cards are cards which have been dealt in calls but are still members of the deck
    /// they remain dealt until the deck is reshuffled or reset.
    dealt_cards: Vec<Card>,
}

impl Cards for Deck {
    fn cards(&self) -> &[Card] {
        self.cards.as_slice()
    }

    fn mut_cards(&mut self) -> &mut [Card] {
        self.cards.as_mut_slice()
    }
}

impl Deck {
    /// Creates a new `Deck` containing the standard set of 52 cards
    pub fn new() -> Deck {
        Deck::from_cards(Card::all_cards())
    }

    /// Creates a new `Deck` containing the specified cards
    pub fn from_cards(cards: &[Card]) -> Deck {
        let mut deck = Deck {
            cards: Vec::with_capacity(cards.len()),
            dealt_cards: Vec::with_capacity(cards.len()),
        };
        deck.populate(cards);
        deck
    }

    fn populate(&mut self, cards: &[Card]) {
        self.cards.extend(cards);
    }

    /// Returns the number of remaining undealt cards in the `Deck`
    pub fn undealt_count(&self) -> usize {
        self.cards.len()
    }

    /// Returns the number of dealt cards in the `Deck`
    pub fn dealt_count(&self) -> usize {
        self.dealt_cards.len()
    }

    /// Returns the number of cards, dealt or undealt, within the `Deck`
    pub fn count(&self) -> usize {
        self.undealt_count() + self.dealt_count()
    }

    /// Returns the collection of dealt cards
    pub fn dealt_cards(&self) -> &[Card] {
        self.dealt_cards.as_slice()
    }

    /// Tells you the top card (very next to be drawn) in the undealt deck
    /// without dealing it.
    pub fn top_card(&self) -> Option<Card> {
        if let Some(card) = self.cards.last() {
            Some(*card)
        } else {
            None
        }
    }

    /// Tells you the bottom card (very last to be drawn) in the undealt deck
    /// without dealing it.
    pub fn bottom_card(&self) -> Option<Card> {
        if let Some(card) = self.cards().first() {
            Some(*card)
        } else {
            None
        }
    }

    /// Deals the card from the undealt pile. If there are no cards left, the function
    /// will return an error.
    pub fn deal_one(&mut self) -> Result<Card, &'static str> {
        if self.cards.is_empty() {
            Err("No cards left")
        } else {
            let card = self.cards.pop().unwrap();
            self.dealt_cards.push(card);
            Ok(card)
        }
    }

    /// Deals one or more card from the undealt pile and returns them as an array.
    pub fn deal(&mut self, numcards: usize) -> Vec<Card> {
        let mut result: Vec<Card> = Vec::with_capacity(numcards as usize);
        for _ in 0..numcards {
            let dealt: Result<Card, &'static str> = self.deal_one();
            if let Ok(card) = dealt {
                result.push(card);
            } else {
                // No cards so no point continuing
                break;
            }
        }
        result
    }

    /// Deals one or more card straight to the `Hand`. Returns the number of cards dealt.
    pub fn deal_to_hand(&mut self, hand: &mut Hand, numcards: usize) -> usize {
        let mut dealt: usize = 0;
        for _ in 0..numcards {
            let result: Result<Card, &'static str> = self.deal_one();
            if let Ok(card) = result {
                dealt += 1;
                hand.push_card(card);
            } else {
                // No cards so no point continuing
                break;
            }
        }
        dealt
    }

    /// Return the dealt cards back to the end of the undealt pile. Order is preserved according
    /// to the default order or the last shuffle.
    pub fn reset(&mut self) {
        // Put cards back into undealt deck in reverse order
        self.cards.extend(self.dealt_cards.iter().rev());
        self.dealt_cards.clear();
    }

    /// Resets and shuffles the deck
    pub fn reset_shuffle(&mut self) {
        self.reset();
        self.shuffle();
    }
}