; feed/notify — a notification feed is a thin layer over a recipient's inbox:
; the events directed at a user, optionally verb-filtered, and a digest that
; collapses "alice, bob and 1 other liked X" by (verb, object).
;
; Requires: lib/feed/normalize.sx, lib/feed/stream.sx, lib/feed/fanout.sx
; (feed/inbox-for, feed/-elem?).

; all inbox events for a user (their raw notifications)
(define feed/notifications (fn (inbox user) (feed/inbox-for inbox user)))

; restrict to notification-worthy verbs (e.g. (list "like" "reply" "follow"))
(define
  feed/notify-verbs
  (fn
    (inbox user verbs)
    (feed/filter
      (feed/inbox-for inbox user)
      (fn (ev) (feed/-elem? (get (get ev :activity) :verb) verbs)))))

; group key "verb|object" — deterministic, sortable
(define
  feed/-notify-key
  (fn
    (ev)
    (let
      ((a (get ev :activity)))
      (string-append (get a :verb) "|" (get a :object)))))

; digest: one entry per (verb, object) with the distinct actors and a count,
; ordered by key for determinism.
(define
  feed/notify-digest
  (fn
    (inbox user)
    (let
      ((events (feed/items (feed/inbox-for inbox user))))
      (let
        ((groups (reduce (fn (g ev) (let ((a (get ev :activity)) (k (feed/-notify-key ev))) (let ((cur (get g k {:object (get a :object) :actors (list) :verb (get a :verb)}))) (assoc g k (assoc cur :actors (append (get cur :actors) (list (get a :actor)))))))) {} events)))
        (map
          (fn
            (k)
            (let
              ((grp (get groups k)))
              (assoc grp :count (len (get grp :actors)))))
          (sort (keys groups)))))))
