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
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
use counted_map::ReassignableCountedMap;

use crate::{
    exposed::Exposed,
    receive::{Receive, ReceiverResult},
    view::View,
};

pub trait Route<E>: Receive<E> {
    fn intercept(&mut self, intercept: Box<dyn Route<E, Output = E>>);

    fn take_intercept(&mut self) -> Option<Box<dyn Route<E, Output = E>>>;

    fn intercept_at_root(&mut self, intercept: Box<dyn Route<E, Output = E>>) {
        let old_intercept = self.take_intercept();
        match old_intercept {
            Some(r) => {
                self.intercept(intercept);
                self.intercept(r);
            },
            None => self.intercept(intercept),
        }
    }
}

pub struct Router<E, R: Receive<E>> {
    intercept: Option<Box<dyn Route<E, Output = E>>>,
    reciever: R,
}

impl<E, R: Receive<E>> Router<E, R> {
    pub fn new(reciever: R) -> Self {
        Self {
            intercept: None,
            reciever,
        }
    }

    pub fn with_intercept(intercept: Box<dyn Route<E, Output = E>>, reciever: R) -> Self {
        Self {
            intercept: Some(intercept),
            reciever,
        }
    }

    pub fn with_intercept_from_receiver(
        intercept: impl Receive<E, Output = E> + 'static,
        receiver: R,
    ) -> Self
    where
        E: 'static,
    {
        Self::with_intercept(Box::new(Router::new(intercept)), receiver)
    }

    pub fn new_exposed(reciever: R) -> Router<E, Exposed<E, R>> {
        Router {
            intercept: None,
            reciever: Exposed::new(reciever),
        }
    }

    pub fn new_exposed_with_viewers(
        reciever: R,
        viewers: ReassignableCountedMap<usize, Box<dyn View<E>>>,
    ) -> Router<E, Exposed<E, R>> {
        Router {
            intercept: None,
            reciever: Exposed::with_viewers(viewers, reciever),
        }
    }

    pub fn new_exposed_with_intercept(
        intercept: Box<dyn Route<E, Output = E>>,
        reciever: R,
    ) -> Router<E, Exposed<E, R>> {
        Router {
            intercept: Some(intercept),
            reciever: Exposed::new(reciever),
        }
    }

    pub fn new_exposed_with_intercept_from_receiver(
        intercept: impl Receive<E, Output = E> + 'static,
        receiver: R,
    ) -> Router<E, Exposed<E, R>>
    where
        E: 'static,
    {
        Router::new_exposed_with_intercept(Box::new(Router::new(intercept)), receiver)
    }

    pub fn get_reciever(&self) -> &R {
        &self.reciever
    }

    pub fn get_reciever_mut(&mut self) -> &mut R {
        &mut self.reciever
    }

    pub fn get_intercept(&self) -> Option<&dyn Route<E, Output = E>> {
        self.intercept.as_ref().map(Box::as_ref)
    }

    pub fn intercept_from_receiver(&mut self, intercept: impl Receive<E, Output = E> + 'static)
    where
        E: 'static,
    {
        let intercept = Box::new(Router::new(intercept));
        self.intercept(intercept);
    }

    pub fn intercept_at_root_from_receiver(&mut self, intercept: impl Receive<E, Output = E> + 'static)
    where
        E: 'static,
    {
        let intercept = Box::new(Router::new(intercept));
        self.intercept_at_root(intercept);
    }
}

impl<E, R: Receive<E>> Receive<E> for Router<E, R> {
    type Output = R::Output;
    fn send(&mut self, event: E) -> ReceiverResult<E, Self::Output> {
        let event = if let Some(ref mut intercept) = self.intercept {
            match intercept.send(event) {
                ReceiverResult::Continue(event) => event,
                ReceiverResult::Stop => return ReceiverResult::Stop,
                ReceiverResult::Delete(event) => {
                    let mut old_intercept = self.take_intercept().unwrap();
                    match old_intercept.take_intercept() {
                        Some(new_intercept) => {
                            self.intercept(new_intercept);
                        }
                        None => self.intercept = None,
                    }
                    event
                }
            }
        } else {
            event
        };

        self.reciever.send(event)
    }
}

impl<E, R: Receive<E>> Route<E> for Router<E, R> {
    fn intercept(&mut self, intercept: Box<dyn Route<E, Output = E>>) {
        match self.intercept {
            Some(ref mut child) => child.intercept(intercept),
            None => self.intercept = Some(intercept),
        }
    }

    fn take_intercept(&mut self) -> Option<Box<dyn Route<E, Output = E>>> {
        self.intercept.take()
    }
}