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
use std::{convert::TryFrom, sync::Arc};

use super::InputMessageData;
use crate::{image::RawImage, models::Color};

#[derive(Debug, Clone)]
pub struct MuxedMessage {
    data: MuxedMessageData,
}

impl MuxedMessage {
    pub fn new(data: MuxedMessageData) -> Self {
        Self { data }
    }

    pub fn data(&self) -> &MuxedMessageData {
        &self.data
    }
}

impl std::ops::Deref for MuxedMessage {
    type Target = MuxedMessageData;

    fn deref(&self) -> &Self::Target {
        &self.data
    }
}

#[derive(Debug, Clone)]
pub enum MuxedMessageData {
    SolidColor {
        priority: i32,
        duration: Option<chrono::Duration>,
        color: Color,
    },
    Image {
        priority: i32,
        duration: Option<chrono::Duration>,
        image: Arc<RawImage>,
    },
    LedColors {
        priority: i32,
        duration: Option<chrono::Duration>,
        led_colors: Arc<Vec<Color>>,
    },
}

impl MuxedMessageData {
    pub fn priority(&self) -> i32 {
        match self {
            MuxedMessageData::SolidColor { priority, .. } => *priority,
            MuxedMessageData::Image { priority, .. } => *priority,
            MuxedMessageData::LedColors { priority, .. } => *priority,
        }
    }

    pub fn color(&self) -> Option<Color> {
        match self {
            MuxedMessageData::SolidColor { color, .. } => Some(*color),
            _ => None,
        }
    }
}

impl TryFrom<InputMessageData> for MuxedMessageData {
    type Error = ();

    fn try_from(value: InputMessageData) -> Result<Self, Self::Error> {
        match value {
            InputMessageData::ClearAll
            | InputMessageData::Clear { .. }
            | InputMessageData::Effect { .. } => Err(()),
            InputMessageData::SolidColor {
                priority,
                duration,
                color,
            } => Ok(Self::SolidColor {
                priority,
                duration,
                color,
            }),
            InputMessageData::Image {
                priority,
                duration,
                image,
            } => Ok(Self::Image {
                priority,
                duration,
                image,
            }),
            InputMessageData::LedColors {
                priority,
                duration,
                led_colors,
            } => Ok(Self::LedColors {
                priority,
                duration,
                led_colors,
            }),
        }
    }
}