
use std::sync::Arc;

{% for item in uses %}use {{item}};
{% endfor %}

{% if comment_listener %}{{comment_listener}}{% endif %}
#[derive(Clone)]
pub struct Listener {
  {% for ttm in ttms %}l_{{ttm.name}}: Option<Arc<Fn((&Api{% if ttm.tt %}, &{% if ttm.tt.namespace and ttm.tt.object %}{{ttm.tt.namespace}}::{% endif %}{% if ttm.tt.object %}{{ttm.tt.object}}{% endif %}{% endif %})) + Send + Sync + 'static>>,
  {% endfor %}
}

impl Listener {
  pub fn new() -> Self {
    Self {
      {% for ttm in ttms %}l_{{ttm.name}}: None,
      {% endfor %}
    }
  }

  pub(crate) fn has_receive_listen(&self) -> bool {
    self.l_receive.is_some()
  }

  pub(crate) fn lout(&self) -> Lout {
    Lout::new(self.clone())
  }
{% for ttm in ttms %}{% if ttm.comment %}  {{ ttm.comment }}{% endif %}
  pub fn on_{{ttm.name}}<F>(&mut self, fnc: F) -> &mut Self where F: Fn((&Api{% if ttm.tt %}, &{% if ttm.tt.namespace and ttm.tt.object %}{{ttm.tt.namespace}}::{% endif %}{% if ttm.tt.object %}{{ttm.tt.object}}{% endif %}{% endif %})) + Send + Sync + 'static {
    self.l_{{ttm.name}} = Some(Arc::new(fnc));
    self
  }
{% endfor %}
}

{% if comment_lout %}{{comment_lout}}{% endif %}
pub struct Lout {
  listener: Listener,
  supports: Vec<&'static str>
}

impl Lout {
  fn new(listener: Listener) -> Self {
    let supports = vec![
      {% for item in td_types %}"{{item}}",
      {% endfor %}
    ];
    Self {
      listener,
      supports,
    }
  }

  pub fn is_support<S: AsRef<str>>(&self, name: S) -> bool {
    !self.supports.iter()
      .filter(|&&item| item.to_lowercase() == name.as_ref().to_lowercase())
      .collect::<Vec<_>>()
      .is_empty()
  }

{% for ttm in ttms %}{% if ttm.comment %}  {{ ttm.comment }}{% endif %}
  pub fn {{ttm.name}}(&self) -> &Option<Arc<Fn((&Api{% if ttm.tt %}, &{% if ttm.tt.namespace and ttm.tt.object %}{{ttm.tt.namespace}}::{% endif %}{% if ttm.tt.object %}{{ttm.tt.object}}{% endif %}{% endif %})) + Send + Sync + 'static>> {
    &self.listener.l_{{ttm.name}}
  }
{% endfor %}
}
