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
use crate::errors::{ErrorKind, Result};
use crate::fsshttpb::data::exguid::ExGuid;
use crate::one::property::color_ref::ColorRef;
use crate::one::property::note_tag::{ActionItemStatus, ActionItemType};
use crate::one::property::note_tag_property_status::NoteTagPropertyStatus;
use crate::one::property::note_tag_shape::NoteTagShape;
use crate::one::property::time::Time;
use crate::one::property_set::note_tag_container::Data;
use crate::one::property_set::note_tag_shared_definition_container;
use crate::onestore::object_space::ObjectSpace;

/// A note tag.
///
/// See [\[MS-ONE\] 2.2.42].
///
/// [\[MS-ONE\] 2.2.42]: https://docs.microsoft.com/en-us/openspecs/office_file_formats/ms-one/283e1611-05cb-4468-9be1-2879a3d1c17d
#[derive(Clone, Eq, PartialEq, Ord, PartialOrd, Hash, Debug)]
pub struct NoteTag {
    completed_at: Option<Time>,
    item_status: ActionItemStatus,
    definition: Option<NoteTagDefinition>,
}

impl NoteTag {
    /// When the task has been completed.
    ///
    /// Only set for task-like note tags.
    ///
    /// See [\[MS-ONE\] 2.3.90].
    ///
    /// [\[MS-ONE\] 2.3.90]: https://docs.microsoft.com/en-us/openspecs/office_file_formats/ms-one/2261a830-3dee-42a8-ab85-97686ebe35bc
    pub fn completed_at(&self) -> Option<Time> {
        self.completed_at
    }

    /// The status of the note tag.
    pub fn item_status(&self) -> ActionItemStatus {
        self.item_status
    }

    /// The style and format definition for this note tag.
    pub fn definition(&self) -> Option<&NoteTagDefinition> {
        self.definition.as_ref()
    }
}

/// The definition of a note tag.
///
/// See [\[MS-ONE\] 2.3.41].
///
/// [\[MS-ONE\] 2.3.41]: https://docs.microsoft.com/en-us/openspecs/office_file_formats/ms-one/eb5f52d2-c507-45c8-9bda-f8c74d34533a
#[derive(Clone, Eq, PartialEq, Ord, PartialOrd, Hash, Debug)]
pub struct NoteTagDefinition {
    label: String,
    status: NoteTagPropertyStatus,
    shape: NoteTagShape,
    highlight_color: Option<ColorRef>,
    text_color: Option<ColorRef>,
    action_item_type: ActionItemType,
}

impl NoteTagDefinition {
    /// The note tag's name.
    pub fn label(&self) -> &str {
        &self.label
    }

    /// The note tag's status
    pub fn status(&self) -> &NoteTagPropertyStatus {
        &self.status
    }

    /// The note tag icon shape.
    pub fn shape(&self) -> NoteTagShape {
        self.shape
    }

    /// The note tag's text highlight color.
    pub fn highlight_color(&self) -> Option<ColorRef> {
        self.highlight_color
    }

    /// The note tag's text color.
    pub fn text_color(&self) -> Option<ColorRef> {
        self.text_color
    }

    /// The note tag's action item type.
    pub fn action_item_type(&self) -> ActionItemType {
        self.action_item_type
    }
}

pub(crate) fn parse_note_tags(note_tags: Vec<Data>, space: &ObjectSpace) -> Result<Vec<NoteTag>> {
    note_tags
        .into_iter()
        .map(|data| {
            Ok(NoteTag {
                completed_at: data.completed_at,
                item_status: data.item_status,
                definition: data
                    .definition
                    .map(|definition_id| parse_note_tag_definition(definition_id, space))
                    .transpose()?,
            })
        })
        .collect()
}

pub(crate) fn parse_note_tag_definition(
    definition_id: ExGuid,
    space: &ObjectSpace,
) -> Result<NoteTagDefinition> {
    let object = space
        .get_object(definition_id)
        .ok_or_else(|| ErrorKind::MalformedOneNoteData("note tag definition is missing".into()))?;

    let data = note_tag_shared_definition_container::parse(object)?;

    let definition = NoteTagDefinition {
        label: data.label,
        status: data.status,
        shape: data.shape,
        highlight_color: data.highlight_color,
        text_color: data.text_color,
        action_item_type: data.action_item_type,
    };

    Ok(definition)
}