1use crate::LooseDateTime;
6use chrono::{DateTime, Local};
7use icalendar::Component;
8use std::{fmt::Display, num::NonZeroU32, str::FromStr};
9
10pub trait Event {
12 fn short_id(&self) -> Option<NonZeroU32> {
16 None
17 }
18
19 fn uid(&self) -> &str;
21
22 fn description(&self) -> Option<&str>;
24
25 fn start(&self) -> Option<LooseDateTime>;
27
28 fn end(&self) -> Option<LooseDateTime>;
30
31 fn status(&self) -> Option<EventStatus>;
33
34 fn summary(&self) -> &str;
36}
37
38impl Event for icalendar::Event {
39 fn uid(&self) -> &str {
40 self.get_uid().unwrap_or("")
41 }
42
43 fn description(&self) -> Option<&str> {
44 self.get_description()
45 }
46
47 fn start(&self) -> Option<LooseDateTime> {
48 self.get_start().map(Into::into)
49 }
50
51 fn end(&self) -> Option<LooseDateTime> {
52 self.get_end().map(Into::into)
53 }
54
55 fn status(&self) -> Option<EventStatus> {
56 self.get_status().map(|a| EventStatus::from(&a))
57 }
58
59 fn summary(&self) -> &str {
60 self.get_summary().unwrap_or("")
61 }
62}
63
64#[derive(Debug, Clone, Copy)]
66pub enum EventStatus {
67 Tentative,
69
70 Confirmed,
72
73 Cancelled,
75}
76
77const STATUS_TENTATIVE: &str = "TENTATIVE";
78const STATUS_CONFIRMED: &str = "CONFIRMED";
79const STATUS_CANCELLED: &str = "CANCELLED";
80
81impl AsRef<str> for EventStatus {
82 fn as_ref(&self) -> &str {
83 match self {
84 EventStatus::Tentative => STATUS_TENTATIVE,
85 EventStatus::Confirmed => STATUS_CONFIRMED,
86 EventStatus::Cancelled => STATUS_CANCELLED,
87 }
88 }
89}
90
91impl Display for EventStatus {
92 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
93 write!(f, "{}", self.as_ref())
94 }
95}
96
97impl FromStr for EventStatus {
98 type Err = ();
99
100 fn from_str(value: &str) -> Result<Self, Self::Err> {
101 match value {
102 STATUS_TENTATIVE => Ok(EventStatus::Tentative),
103 STATUS_CONFIRMED => Ok(EventStatus::Confirmed),
104 STATUS_CANCELLED => Ok(EventStatus::Cancelled),
105 _ => Err(()),
106 }
107 }
108}
109
110impl From<&EventStatus> for icalendar::EventStatus {
111 fn from(status: &EventStatus) -> Self {
112 match status {
113 EventStatus::Tentative => icalendar::EventStatus::Tentative,
114 EventStatus::Confirmed => icalendar::EventStatus::Confirmed,
115 EventStatus::Cancelled => icalendar::EventStatus::Cancelled,
116 }
117 }
118}
119
120impl From<&icalendar::EventStatus> for EventStatus {
121 fn from(status: &icalendar::EventStatus) -> Self {
122 match status {
123 icalendar::EventStatus::Tentative => EventStatus::Tentative,
124 icalendar::EventStatus::Confirmed => EventStatus::Confirmed,
125 icalendar::EventStatus::Cancelled => EventStatus::Cancelled,
126 }
127 }
128}
129
130#[derive(Debug, Clone, Copy)]
132pub struct EventConditions {
133 pub startable: bool,
135}
136
137#[derive(Debug)]
138pub(crate) struct ParsedEventConditions {
139 pub end_after: Option<DateTime<Local>>,
141}
142
143impl ParsedEventConditions {
144 pub fn parse(now: &DateTime<Local>, conds: &EventConditions) -> Self {
145 Self {
146 end_after: conds.startable.then_some(*now),
147 }
148 }
149}