1use std::any::type_name;
2use std::collections::{BTreeMap, BTreeSet, HashMap, HashSet};
3use std::fmt::Debug;
4use crate::api::{ApiTrait, EventHandler};
5use dce_util::mixed::{DceErr, DceResult};
6use dce_util::atom_tree::ATree;
7use dce_util::atom_tree::{KeyFactory, TreeTraverBreak};
8use std::sync::{Arc, RwLockReadGuard};
9use log::debug;
10use crate::protocol::RoutableProtocol;
11use crate::request::{PathParam, Context};
12
13pub const PATH_PART_SEPARATOR: char = '/';
14pub const SUFFIX_BOUNDARY: char = '.';
15const VARIABLE_OPENER: char = '{';
16const VARIABLE_CLOSING: char = '}';
17const VAR_TYPE_OPTIONAL: char = '?';
18const VAR_TYPE_EMPTABLE_VECTOR: char = '*';
19const VAR_TYPE_VECTOR: char = '+';
20
21pub const CODE_NOT_FOUND: isize = 404;
22
23#[derive(Debug)]
24pub struct Router<Rp: RoutableProtocol + 'static> {
25    path_part_separator: char,
26    suffix_boundary: char,
27    api_buffer: Vec<&'static (dyn ApiTrait<Rp> + Send + Sync)>,
28    raw_omitted_paths: HashSet<&'static str>,
29    id_api_mapping: HashMap<&'static str, &'static (dyn ApiTrait<Rp> + Send + Sync)>,
30    apis_mapping: HashMap<&'static str, Vec<&'static (dyn ApiTrait<Rp> + Send + Sync)>>,
32    apis_tree: Arc<ATree<ApiBranch<Rp>, &'static str>>,
33    before_controller: Option<EventHandler<Rp>>,
34    after_controller: Option<EventHandler<Rp>>,
35}
36
37impl<Rp: RoutableProtocol + Debug + 'static> Router<Rp> {
38    pub fn new() -> DceResult<Self> {
39        Ok(Self {
40            path_part_separator: PATH_PART_SEPARATOR,
41            suffix_boundary: SUFFIX_BOUNDARY,
42            api_buffer: vec![],
43            raw_omitted_paths: Default::default(),
44            id_api_mapping: Default::default(),
45            apis_mapping: Default::default(),
46            apis_tree: ATree::new(ApiBranch::new("", vec![]))?,
47            before_controller: None,
48            after_controller: None,
49        })
50    }
51
52    pub fn set_separator(mut self, path_part_separator: char , suffix_separator: char) -> Self {
53        self.path_part_separator = path_part_separator;
54        self.suffix_boundary = suffix_separator;
55        self
56    }
57
58    pub fn suffix_boundary(&self) -> char {
59        self.suffix_boundary
60    }
61
62    pub fn apis_tree(&self) -> &Arc<ATree<ApiBranch<Rp>, &'static str>> {
63        &self.apis_tree
64    }
65
66    pub fn before_controller(&self) -> &Option<EventHandler<Rp>> {
67        &self.before_controller
68    }
69
70    pub fn after_controller(&self) -> &Option<EventHandler<Rp>> {
71        &self.after_controller
72    }
73
74    pub fn set_event_handlers(mut self, before_controller: Option<EventHandler<Rp>>, after_controller: Option<EventHandler<Rp>>) -> Self {
75        self.before_controller = before_controller;
76        self.after_controller = after_controller;
77        self
78    }
79
80    pub fn push(mut self, supplier: fn() -> &'static (dyn ApiTrait<Rp> + Send + Sync)) -> Self {
81        let api = supplier();
82        if api.omission() {
83            self.raw_omitted_paths.insert(api.path());
84        }
85        if ! api.id().is_empty() {
86            self.id_api_mapping.insert(api.id(), api);
87        }
88        self.api_buffer.push(api);
89        self
90    }
91
92    pub fn consumer_push(self, consumer: fn(Self) -> Self) -> Self {
93        consumer(self)
94    }
95
96    fn omitted_path(&self, path: &'static str) -> String {
97        let parts = path.split(PATH_PART_SEPARATOR).collect::<Vec<_>>();
98        parts.iter().enumerate()
99            .filter(|(i, _)| ! self.raw_omitted_paths.contains(parts[0..=*i].join(PATH_PART_SEPARATOR.to_string().as_str()).as_str()))
101            .map(|t| t.1.to_string())
102            .collect::<Vec<_>>()
103            .join(PATH_PART_SEPARATOR.to_string().as_str())
104    }
105
106    fn closing(&mut self) -> DceResult<()> {
107        self.build_tree()?;
108        while let Some(api) = self.api_buffer.pop() {
109            let path = self.omitted_path(api.path());
110            let mut apis = vec![api];
111            let mut suffixes = api.suffixes().clone();
112            for index in (0..self.api_buffer.len()).rev() {
113                if path.eq_ignore_ascii_case(self.omitted_path(&self.api_buffer[index].path()).as_str()) {
114                    let sibling_api = self.api_buffer.remove(index);
116                    suffixes.extend(sibling_api.suffixes().clone());
117                    apis.insert(0, sibling_api);
118                }
119            }
120            for suffix in suffixes {
122                let suffixed_path = self.suffix_path(&path, &*suffix);
123                self.apis_mapping.insert(Box::leak(suffixed_path.into_boxed_str()), apis.iter()
124                    .filter(|api| api.suffixes().contains(&suffix))
125                    .map(|api| *api)
126                    .collect::<Vec<_>>());
127            }
128        }
129        Ok(())
130    }
131
132    fn suffix_path(&self, path: &String, suffix: &str) -> String {
133        format!("{}{}", path, if suffix.is_empty() { "".to_owned() } else { format!("{}{}", SUFFIX_BOUNDARY, suffix) })
134    }
135
136    fn build_tree(&mut self) -> DceResult<()> {
137        let suffix_less_apis_groups: Vec<Vec<_>> = self.api_buffer.iter().map(|a| a.path()).collect::<HashSet<_>>()
138            .iter().map(|path| self.api_buffer.iter().filter_map(|api| if api.path().eq(*path) { Some(*api) } else { None }).collect()).collect();
139        self.apis_tree.build(
141            suffix_less_apis_groups.iter().map(|apis| ApiBranch::new(apis[0].path(), apis.clone())).collect::<Vec<_>>(),
142            Some(|tree: &ATree<ApiBranch<Rp>, &'static str>, mut remains: Vec<ApiBranch<Rp>>| {
146                let mut fills: BTreeMap<Vec<&'static str>, ApiBranch<Rp>> = BTreeMap::new();
147                while let Some(element) = remains.pop() {
148                    let paths: Vec<_> = element.path.split(PATH_PART_SEPARATOR).collect();
149                    for i in 0..paths.len() - 1 {
150                        let path = paths[..=i].to_vec();
151                        if matches!(tree.get_by_path(&path), None) && ! fills.contains_key(&path) {
152                            let api_path = ApiBranch::new(Box::leak(path.clone().join(PATH_PART_SEPARATOR.to_string().as_str()).into_boxed_str()), vec![]);
154                            fills.insert(path, api_path);
155                        }
156                    }
157                    fills.insert(paths, element);
159                }
160                while let Some((paths, nb)) = fills.pop_first() {
161                    let _ = tree.set_by_path(paths, nb);
162                }
163            }),
164        )?;
165        self.apis_tree.traversal(|tree| {
167            let is_var_elem = ! matches!(tree.read().map_err(DceErr::closed0)?.var_type, VarType::NotVar);
168            let mut current = tree.clone();
169            let mut is_omitted_passed_child = false;
170            while let Some(parent) = current.parent() {
171                if ! parent.read().map_err(DceErr::closed0)?.is_omission {
172                    let mut parent_writable = parent.write().map_err(DceErr::closed0)?;
173                    match parent_writable.var_type {
174                        VarType::Required(_) => parent_writable.is_mid_var = true,
175                        VarType::NotVar => {},
176                        _ => panic!("Ambiguous type var '{}' cannot in middle.", parent_writable.key()),
177                    }
178                    if is_var_elem {
180                        parent_writable.var_children.push(tree.clone());
181                    } else if is_omitted_passed_child {
182                        parent_writable.omitted_passed_children.insert(tree.read().map_err(DceErr::closed0)?.key(), tree.clone());
183                    }
184                    break;
185                }
186                is_omitted_passed_child = true;
187                current = parent;
188            }
189            Ok(TreeTraverBreak::Continue)
190        })
191    }
192
193    pub fn ready(mut self) -> DceResult<&'static Arc<Router<Rp>>> {
194        self.closing()?;
195        Ok(Box::leak(Box::new(Arc::new(self))))
196    }
197
198    fn locate(
199        &self,
200        mut path: &str,
201        api_finder: impl Fn(&Vec<&'static (dyn ApiTrait<Rp> + Send + Sync)>) -> DceResult<&'static (dyn ApiTrait<Rp> + Send + Sync)>,
202    ) -> DceResult<(&'static (dyn ApiTrait<Rp> + Send + Sync), HashMap<&'static str, PathParam>, Option<&'static str>)> {
203        let request_path = path;
204        let mut api;
205        let mut path_args = Default::default();
206        let mut suffix = None;
207        loop {
209            let mut apis = self.apis_mapping.get(path);
210            if let Some((tmp_path, tmp_path_args, tmp_suffix)) = if apis.is_some() { None } else { self.match_var_path(path) } {
211                apis = self.apis_mapping.get(self.suffix_path(&self.omitted_path(tmp_path), tmp_suffix).as_str());
214                (path_args, suffix) = (tmp_path_args, Some(tmp_suffix));
215            }
216            api = api_finder(apis.ok_or_else(|| DceErr::openly(CODE_NOT_FOUND, format!(r#"path "{}" route failed, could not matched by Router"#, path)))?)?;
217            if api.redirect().is_empty() {
218                break;
219            }
220            path = api.redirect();
221        }
222        debug!(r#"{}: path "{}" matched api "{}""#, type_name::<Rp>(), request_path, api.path());
223        Ok((api, path_args, suffix))
224    }
225
226    fn match_var_path(
227        &self,
228        path: &str,
229    ) -> Option<(&'static str, HashMap<&'static str, PathParam>, &'static str)> {
230        let path_parts = path.split(self.path_part_separator).collect::<Vec<_>>();
231        let mut loop_items = vec![(self.apis_tree.clone(), 0_usize)];
232        let mut target_api_branch = None;
233        let mut suffix = "";
234        let mut path_args = HashMap::new();
235        'outer: while let Some((api_branch, part_number)) = loop_items.pop() {
236            let is_last_part = part_number == path_parts.len() - 1;
237            let is_overflowed = part_number >= path_parts.len();
238            if is_overflowed && ! api_branch.read().ok()?.apis.is_empty() {
239                target_api_branch = Some(api_branch.clone());
241                break;
242            }
243            if let Some((sub_api_branch, matched_suffix)) = if is_overflowed { None } else {
245                self.find_consider_suffix(&path_parts[part_number], is_last_part, api_branch.children().read().ok()?, &api_branch.read().ok()?.omitted_passed_children)
246            } {
247                loop_items.push((sub_api_branch.clone(), 1 + part_number));
249                suffix = matched_suffix;
250            } else {
251                let insert_pos = loop_items.len();
252                for var_api_branch in api_branch.read().ok()?.var_children.clone() {
253                    let var_api_branch_read = var_api_branch.read().ok()?;
254                    if ! var_api_branch_read.is_mid_var {
255                        let mut suffix_extractor = |path_parts: Vec<&str>, consumer: &mut dyn FnMut(Vec<&str>) -> Option<PathParam>| -> Option<PathParam> {
258                            let mut path_parts = path_parts.clone();
259                            if let Some(mut last_part) = path_parts.pop() {
260                                if let Some(tmp_suffix) = var_api_branch_read.apis.iter().flat_map(|api| api.suffixes()).collect::<BTreeSet<_>>()
263                                    .iter().find(|suf| last_part.ends_with(format!("{}{}", self.suffix_boundary, &****suf).as_str())) {
264                                    last_part = &last_part[0..last_part.len() - tmp_suffix.len() - 1];
265                                    suffix = &**tmp_suffix;
266                                }
267                                path_parts.push(last_part);
268                            }
269                            consumer(path_parts)
270                        };
271                        match var_api_branch_read.var_type {
273                            VarType::Optional(var_name) if is_overflowed => path_args.insert(var_name, PathParam::Option(None)),
275                            VarType::Optional(var_name) if is_last_part =>
277                                suffix_extractor(path_parts, &mut |pps| path_args.insert(var_name, PathParam::Option(Some(pps[part_number].to_string())))),
278                            VarType::Required(var_name) if is_last_part =>
279                                suffix_extractor(path_parts, &mut |pps| path_args.insert(var_name, PathParam::Required(pps[part_number].to_string()))),
280                            VarType::EmptableVector(var_name) if is_overflowed => path_args.insert(var_name, PathParam::Vector(vec![])),
281                            VarType::EmptableVector(var_name) | VarType::Vector(var_name) if !is_overflowed =>
283                                suffix_extractor(path_parts, &mut |pps| path_args.insert(var_name, PathParam::Vector(pps[part_number..].iter().map(|p| p.to_string()).collect::<Vec<_>>()))),
284                            _ => continue,
286                        };
287                        target_api_branch = Some(var_api_branch.clone());
288                        break 'outer;
289                    } else if let VarType::Required(var_name) = var_api_branch_read.var_type {
290                        path_args.insert(var_name, PathParam::Required(path_parts[part_number].to_string()));
292                        loop_items.insert(insert_pos, (var_api_branch.clone(), 1 + part_number));
293                    }
294                }
295            }
296        }
297        target_api_branch?.read().map(|branch| (branch.path, path_args, suffix)).ok()
298    }
299
300    fn find_consider_suffix(
301        &self,
302        part: &str,
303        is_last_part: bool,
304        children: RwLockReadGuard<BTreeMap<&'static str, Arc<ATree<ApiBranch<Rp>, &'static str>>>>,
305        omitted_passed_children: &BTreeMap<&'static str, Arc<ATree<ApiBranch<Rp>, &'static str>>>,
306    ) -> Option<(Arc<ATree<ApiBranch<Rp>, &'static str>>, &'static str)> {
307        let matches = children.get(part).or_else(|| omitted_passed_children.get(part));
308        if matches.is_none() && is_last_part {
309            let mut boundary = part.len();
310            while let Some(previous) = part[0..boundary].rfind(self.suffix_boundary) {
311                let matches = children.get(&part[0..previous]).or_else(|| omitted_passed_children.get(&part[0..previous]));
313                if let Some(matches) = matches {
314                    return matches.read().ok()?.apis.iter()
315                        .flat_map(|api| api.suffixes())
316                        .find(|suffix| part[previous + 1 ..].eq(&***suffix))
317                        .map(|suffix| (matches.clone(), &**suffix));
318                }
319                boundary = previous;
320            }
321        }
322        return matches.map(|tree| (tree.clone(), ""));
324    }
325
326    #[cfg(feature = "async")]
327    async fn routed_handle(result: DceResult<(&'static (dyn ApiTrait<Rp> + Send + Sync), HashMap<&'static str, PathParam>, Option<&'static str>)>, context: &mut Context<Rp>) -> DceResult<()> {
328        let (api, path_args, suffix) = result?;
329        context.set_routed_info(api, path_args, suffix);
330        api.call_controller(context).await
331    }
332
333    #[cfg(not(feature = "async"))]
334    fn routed_handle(result: DceResult<(&'static (dyn ApiTrait<Rp> + Send + Sync), HashMap<&'static str, PathParam>, Option<&'static str>)>, context: &mut Context<Rp>) -> DceResult<()> {
335        let (api, path_args, suffix) = result?;
336        context.set_routed_info(api, path_args, suffix);
337        api.call_controller(context)
338    }
339
340    #[cfg(feature = "async")]
341    pub async fn route(context: &mut Context<Rp>) -> DceResult<()> {
342        Self::routed_handle(context.router().locate(context.rp().path(), |apis| context.rp().api_match(apis)), context).await
343    }
344
345    #[cfg(not(feature = "async"))]
346    pub fn route(context: &mut Context<Rp>) -> DceResult<()> {
347        Self::routed_handle(context.router().locate(context.rp().path(), |apis| context.rp().api_match(apis)), context)
348    }
349
350    fn id_locate(&self, id: &str) -> DceResult<(&'static (dyn ApiTrait<Rp> + Send + Sync), HashMap<&'static str, PathParam>, Option<&'static str>)> {
351        self.id_api_mapping.get(id).map_or_else(
352            || Err(DceErr::openly(CODE_NOT_FOUND, format!(r#"id "{}" route failed, could not matched by Router"#, id))),
353            |api| {
354                debug!(r#"{}: id "{}" matched api "{}""#, type_name::<Rp>(), id, api.path());
355                Ok((*api, Default::default(), None))
356            })
357    }
358
359    #[cfg(feature = "async")]
360    pub async fn id_route(context: &mut Context<Rp>) -> DceResult<()> {
361        Self::routed_handle(context.router().id_locate(context.rp().path()), context).await
362    }
363
364    #[cfg(not(feature = "async"))]
365    pub fn id_route(context: &mut Context<Rp>) -> DceResult<()> {
366        Self::routed_handle(context.router().id_locate(context.rp().path()), context)
367    }
368}
369
370#[derive(PartialEq, Debug, Clone)]
371enum VarType {
372    Required(&'static str),
373    Optional(&'static str),
374    EmptableVector(&'static str),
375    Vector(&'static str),
376    NotVar,
377}
378
379#[derive(Debug)]
380pub struct ApiBranch<Rp: RoutableProtocol + 'static> {
381    path: &'static str,
382    var_type: VarType,
383    is_mid_var: bool,
384    is_omission: bool,
385    apis: Vec<&'static (dyn ApiTrait<Rp> + Send + Sync)>,
386    var_children: Vec<Arc<ATree<ApiBranch<Rp>, &'static str>>>,
387    omitted_passed_children: BTreeMap<&'static str, Arc<ATree<ApiBranch<Rp>, &'static str>>>,
388}
389
390impl<Rp: RoutableProtocol> ApiBranch<Rp> {
391    fn new(path: &'static str, apis: Vec<&'static (dyn ApiTrait<Rp> + Send + Sync)>) -> ApiBranch<Rp> {
392        ApiBranch {
393            path,
394            var_type: VarType::NotVar,
395            is_mid_var: false,
396            is_omission: apis.iter().any(|api| api.omission()),
397            apis,
398            var_children: Default::default(),
399            omitted_passed_children: Default::default(),
400        }.fill_var_type()
401    }
402
403    fn fill_var_type(mut self) -> ApiBranch<Rp> {
404        let key = self.key();
405        if key.starts_with(VARIABLE_OPENER) && key.ends_with(VARIABLE_CLOSING) {
406            if self.is_omission {
407                panic!("Var path could not be omissible.");
408            }
409            let var = key[1..key.len() - 1].trim();
410            self.var_type = match var.chars().last() {
411                Some(VAR_TYPE_OPTIONAL) => VarType::Optional(var[0..var.len() - 1].trim_end()),
412                Some(VAR_TYPE_EMPTABLE_VECTOR) => VarType::EmptableVector(var[0..var.len() - 1].trim_end()),
413                Some(VAR_TYPE_VECTOR) => VarType::Vector(var[0..var.len() - 1].trim_end()),
414                _ => VarType::Required(var),
415            }
416        }
417        self
418    }
419}
420
421impl<Rp: RoutableProtocol> KeyFactory<&'static str> for ApiBranch<Rp> {
422    fn key(&self) -> &'static str {
423        self.path.rfind(PATH_PART_SEPARATOR).map_or_else(|| self.path.trim(), |index| &self.path[index+1 ..].trim())
424    }
425
426    fn child_of(&self, parent: &Self) -> bool {
427        self.path.rfind(PATH_PART_SEPARATOR).map_or_else(|| parent.path.is_empty(), |index| &self.path[..index] == parent.path)
428    }
429}
430
431impl<Rp: RoutableProtocol> PartialEq for ApiBranch<Rp> {
432    fn eq(&self, other: &Self) -> bool {
433        self.path == other.path
434    }
435}