;;; jao-words.el --- utilities for word stats        -*- lexical-binding: t; -*-

;; Copyright (C) 2026  Jose Antonio Ortega Ruiz

;; Author: Jose Antonio Ortega Ruiz <mail@jao.io>
;; Keywords: text

;; This program is free software; you can redistribute it and/or modify
;; it under the terms of the GNU General Public License as published by
;; the Free Software Foundation, either version 3 of the License, or
;; (at your option) any later version.

;; This program is distributed in the hope that it will be useful,
;; but WITHOUT ANY WARRANTY; without even the implied warranty of
;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
;; GNU General Public License for more details.

;; You should have received a copy of the GNU General Public License
;; along with this program.  If not, see <https://www.gnu.org/licenses/>.

;;; Commentary:

;; Simple word counting and classification

;;; Code:

(defun jao-words--count-words (raw-word-list)
  (cl-loop with result = nil
           for elt in raw-word-list
           do (cl-incf (cdr (or (assoc elt result)
                                (first (push (cons elt 0) result)))))
           finally return (sort result
                                (lambda (a b) (string< (car a) (car b))))))

(defun jao-words--word-lines (buffer word)
  (let ((lines nil)
        (last-line nil)
        (case-fold-search nil)
        (rx (format "\\b%s\\b" (regexp-quote word))))
    (with-current-buffer buffer
      (save-excursion
        (goto-char (point-min))
        (while (and (re-search-forward rx nil t) (< (length lines) 12))
          (let* ((line (line-number-at-pos))
                 (d (- line (or last-line line))))
            (when (<= d 10)
              (when last-line
                (push last-line lines)
                (push line lines)))
            (setq last-line (line-number-at-pos))))))
    (mapconcat #'number-to-string (nreverse lines) " ")))

(defun jao-words-show-stats ()
  (interactive)
  (let* ((words (split-string (downcase (buffer-string)) "\\W+" t))
         (word-list (jao-words--count-words words))
         (buffer (current-buffer)))
    (with-current-buffer (get-buffer-create "*word-statistics*")
      (erase-buffer)
      (insert "| word | occurences | lines |
               |-----------+------------|--------------------|\n")
      (dolist (elt word-list)
        (let* ((word (car elt))
               (count (cdr elt))
               (lines (jao-words--word-lines buffer word)))
          (insert (format "| %s | %d | %s |\n" word count lines))))
      (org-mode)
      (indent-region (point-min) (point-max))
      (goto-char 5)
      (next-line 2)
      (org-table-next-field)
      (org-table-sort-lines nil ?N)))
  (pop-to-buffer "*word-statistics*"))


(provide 'jao-words)
;;; jao-words.el ends here
