;; content-on-sx — document statistics (word/char/block counts, reading time).
;;
;; Counts derive from the plain-text projection (asText, tree-accurate via
;; section recursion) and a tree block count (inline class check, so this needs
;; no section.sx). Reading time uses 200 wpm, rounded up.
;;
;; Requires (loaded by harness): block.sx, doc.sx, text.sx (asText).

(define
  ct-words
  (fn (s) (filter (fn (w) (if (= w "") false true)) (split s " "))))

(define ct-ceil-div (fn (a b) (quotient (+ a (- b 1)) b)))

(define
  ct-stat-section?
  (fn (b) (and (st-instance? b) (= (get b :class) "CtSection"))))
(define
  ct-stat-count
  (fn
    (blocks)
    (if
      (= (len blocks) 0)
      0
      (let
        ((b (first blocks)))
        (+
          (+
            1
            (if
              (ct-stat-section? b)
              (let
                ((ch (st-iv-get b "children")))
                (if (list? ch) (ct-stat-count ch) 0))
              0))
          (ct-stat-count (rest blocks)))))))

(define content/word-count (fn (doc) (len (ct-words (asText doc)))))
(define content/char-count (fn (doc) (string-length (asText doc))))
(define content/block-count (fn (doc) (ct-stat-count (doc-blocks doc))))
(define
  content/reading-minutes
  (fn
    (doc)
    (let
      ((w (content/word-count doc)))
      (if (= w 0) 0 (ct-ceil-div w 200)))))

(define content/stats (fn (doc) {:blocks (content/block-count doc) :reading-minutes (content/reading-minutes doc) :words (content/word-count doc) :chars (content/char-count doc)}))
