;; lib/relations/api.sx — relationship lifecycle + current-db convenience layer.
;;
;; A relations db is a live Datalog db holding rel(Src,Dst,Kind) facts (and, for
;; federation, peer_rel/trust facts) under the engine ruleset
;; (lib/relations/engine.sx). The query functions live in engine.sx; this module
;; owns db construction, the assert/retract lifecycle, and a current-db
;; convenience layer for callers that load a fact base once and query without
;; threading the db around. This mirrors lib/acl/api.sx.

(define
  relations-build-db
  (fn (facts) (dl-program-data facts relations-rules)))

(define relations-current-db nil)

(define
  relations/load!
  (fn
    (facts)
    (do
      (set! relations-current-db (relations-build-db facts))
      relations-current-db)))

(define
  relations-ensure-db!
  (fn
    ()
    (do
      (when
        (= relations-current-db nil)
        (set! relations-current-db (relations-build-db (list))))
      relations-current-db)))

;; Add a relationship to the current db (re-saturates).
(define
  relations/relate
  (fn
    (src dst kind)
    (dl-assert! (relations-ensure-db!) (relations-rel src dst kind))))

;; Remove a relationship from the current db (re-saturates).
(define
  relations/unrelate
  (fn
    (src dst kind)
    (dl-retract! (relations-ensure-db!) (relations-rel src dst kind))))

(define
  relations/children
  (fn (node kind) (relations-children-of (relations-ensure-db!) node kind)))

(define
  relations/parents
  (fn (node kind) (relations-parents-of (relations-ensure-db!) node kind)))

(define
  relations/related
  (fn (node kind) (relations-related (relations-ensure-db!) node kind)))

(define
  relations/descendants
  (fn (node kind) (relations-descendants (relations-ensure-db!) node kind)))

(define
  relations/ancestors
  (fn (node kind) (relations-ancestors (relations-ensure-db!) node kind)))

(define
  relations/reachable?
  (fn (a b kind) (relations-reachable? (relations-ensure-db!) a b kind)))

(define
  relations/roots
  (fn (kind) (relations-roots (relations-ensure-db!) kind)))

(define
  relations/leaves
  (fn (kind) (relations-leaves (relations-ensure-db!) kind)))

(define
  relations/cycle?
  (fn (node kind) (relations-cycle? (relations-ensure-db!) node kind)))

(define
  relations/acyclic?
  (fn (kind) (relations-acyclic? (relations-ensure-db!) kind)))

(define
  relations/siblings
  (fn (node kind) (relations-siblings (relations-ensure-db!) node kind)))

(define
  relations/out-degree
  (fn (node kind) (relations-out-degree (relations-ensure-db!) node kind)))

(define
  relations/in-degree
  (fn (node kind) (relations-in-degree (relations-ensure-db!) node kind)))

(define
  relations/connected?
  (fn (a b kind) (relations-connected? (relations-ensure-db!) a b kind)))

(define
  relations-relate-many!
  (fn
    (db triples)
    (do
      (for-each
        (fn
          (t)
          (dl-assert!
            db
            (relations-rel (first t) (nth t 1) (nth t 2))))
        triples)
      db)))

(define
  relations-unrelate-node!
  (fn
    (db node)
    (do
      (for-each
        (fn
          (s)
          (dl-retract! db (relations-rel node (get s :Dst) (get s :Kind))))
        (dl-query db (list (quote rel) node (quote Dst) (quote Kind))))
      (for-each
        (fn
          (s)
          (dl-retract! db (relations-rel (get s :Src) node (get s :Kind))))
        (dl-query db (list (quote rel) (quote Src) node (quote Kind))))
      db)))

(define
  relations/relate-many!
  (fn (triples) (relations-relate-many! (relations-ensure-db!) triples)))

(define
  relations/unrelate-node!
  (fn (node) (relations-unrelate-node! (relations-ensure-db!) node)))
