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
use keri_core::{
    actor::event_generator,
    event_message::cesr_adapter::{parse_event_type, EventType},
    oobi::{Role, Scheme},
    prefix::{IdentifierPrefix, SelfSigningPrefix},
    query::reply_event::{ReplyEvent, ReplyRoute},
};

use crate::identifier::Identifier;

use super::MechanicsError;

impl Identifier {
    /// Generates reply event with `end_role_add` route.
    pub fn add_watcher(&self, watcher_id: IdentifierPrefix) -> Result<String, MechanicsError> {
        String::from_utf8(
            event_generator::generate_end_role(&self.id, &watcher_id, Role::Watcher, true)
                .encode()?,
        )
        .map_err(|_e| MechanicsError::EventFormatError)
    }

    /// Generates reply event with `end_role_cut` route.
    pub fn remove_watcher(&self, watcher_id: IdentifierPrefix) -> Result<String, MechanicsError> {
        String::from_utf8(
            event_generator::generate_end_role(&self.id, &watcher_id, Role::Watcher, false)
                .encode()?,
        )
        .map_err(|_e| MechanicsError::EventFormatError)
    }

    async fn finalize_add_role(
        &self,
        signer_prefix: &IdentifierPrefix,
        event: ReplyEvent,
        sig: Vec<SelfSigningPrefix>,
    ) -> Result<(), MechanicsError> {
        let (dest_identifier, messages_to_send) =
            self.known_events
                .finalize_add_role(signer_prefix, event, sig)?;
        // TODO: send in one request
        for ev in messages_to_send {
            self.communication
                .send_message_to(dest_identifier.clone(), Scheme::Http, ev)
                .await?;
        }
        Ok(())
    }

    pub async fn finalize_add_watcher(
        &self,
        event: &[u8],
        sig: SelfSigningPrefix,
    ) -> Result<(), MechanicsError> {
        let parsed_event =
            parse_event_type(event).map_err(|_e| MechanicsError::EventFormatError)?;
        match parsed_event {
            EventType::Rpy(rpy) => match rpy.get_route() {
                ReplyRoute::EndRoleAdd(_) => {
                    Ok(self.finalize_add_role(&self.id, rpy, vec![sig]).await?)
                }
                ReplyRoute::EndRoleCut(_) => todo!(),
                _ => Err(MechanicsError::WrongEventTypeError),
            },
            _ => Err(MechanicsError::WrongEventTypeError),
        }
    }
}