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
use std::slice::Iter;

use super::card::Card;

#[derive(Copy, Clone, Debug)]
pub enum Orientation {
    Horizontal,
    Vertical,
}

#[derive(Debug)]
pub struct StackSelection {
    pub len: usize,
    pub held: bool,
}

#[derive(Debug)]
pub struct StackDetails {
    pub orientation: Orientation,
    pub len: usize,
    pub face_up_len: usize,
    pub visible_len: usize,
    pub spread_len: usize,
    pub selection: Option<StackSelection>,
}

impl StackDetails {
    pub fn face_up_index(&self) -> usize {
        self.len.saturating_sub(self.face_up_len)
    }

    pub fn visible_index(&self) -> usize {
        self.len.saturating_sub(self.visible_len)
    }

    pub fn spread_index(&self) -> usize {
        self.len.saturating_sub(self.spread_len)
    }

    pub fn selection_index(&self) -> Option<usize> {
        self.selection
            .as_ref()
            .map(|selection| self.len.saturating_sub(selection.len))
    }

    pub fn unspread_len(&self) -> usize {
        self.visible_len.saturating_sub(self.spread_len)
    }

    pub fn held(&self) -> bool {
        self.selection
            .as_ref()
            .map(|selection| selection.held)
            .unwrap_or_default()
    }
}

#[derive(Debug)]
pub struct Stack<'a> {
    pub cards: &'a [Card],
    pub details: StackDetails,
}

impl<'a, 'b> IntoIterator for &'b Stack<'a> {
    type Item = &'a Card;
    type IntoIter = Iter<'a, Card>;

    fn into_iter(self) -> Self::IntoIter {
        self.cards.iter()
    }
}