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
use std::sync::Arc;

use tokio::sync::{oneshot, Mutex};

use crate::{
    api::json::message::EffectRequest, component::ComponentName, image::RawImage,
    instance::StartEffectError, models::Color,
};

use super::Message;

#[derive(Debug, Clone)]
pub struct InputMessage {
    source_id: usize,
    component: ComponentName,
    data: InputMessageData,
}

impl Message for InputMessage {
    type Data = InputMessageData;

    fn new(source_id: usize, component: ComponentName, data: Self::Data) -> Self {
        Self {
            source_id,
            component,
            data,
        }
    }

    fn source_id(&self) -> usize {
        self.source_id
    }

    fn component(&self) -> ComponentName {
        self.component
    }

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

    fn unregister_source(global: &mut super::GlobalData, input_source: &super::InputSource<Self>) {
        global.unregister_input_source(input_source);
    }
}

pub type StartEffectResponseCallback = Mutex<Option<oneshot::Sender<Result<(), StartEffectError>>>>;

#[derive(Debug, Clone)]
pub enum InputMessageData {
    ClearAll,
    Clear {
        priority: i32,
    },
    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>>,
    },
    Effect {
        priority: i32,
        duration: Option<chrono::Duration>,
        effect: Arc<EffectRequest>,
        response: Arc<StartEffectResponseCallback>,
    },
}

impl InputMessageData {
    pub fn priority(&self) -> Option<i32> {
        match self {
            InputMessageData::ClearAll => None,
            InputMessageData::Clear { priority } => Some(*priority),
            InputMessageData::SolidColor { priority, .. } => Some(*priority),
            InputMessageData::Image { priority, .. } => Some(*priority),
            InputMessageData::LedColors { priority, .. } => Some(*priority),
            InputMessageData::Effect { priority, .. } => Some(*priority),
        }
    }

    pub fn duration(&self) -> Option<chrono::Duration> {
        match self {
            InputMessageData::ClearAll => None,
            InputMessageData::Clear { .. } => None,
            InputMessageData::SolidColor { duration, .. } => *duration,
            InputMessageData::Image { duration, .. } => *duration,
            InputMessageData::LedColors { duration, .. } => *duration,
            InputMessageData::Effect { duration, .. } => *duration,
        }
    }
}