
;;(defun logger--split-line-1 (line)
;;  ;;(debug)
;;  (let (comment)
;;    (setq line (d-trim-right line))
;;    (when (string-match "^TODO: \\(.*$\\)" line)
;;      (setq comment (substring line (match-beginning 1) (match-end 1)))
;;      comment)))
;;
;;(defun logger--split-line-2 (line)
;;  (let (date comment)
;;    (setq line (d-trim-right line))
;;    (when (string-match "^\\([0-9][0-9][0-9][0-9]-[0-9][0-9]-[0-9][0-9]\\) \\(.*\\)$" line)
;;      (setq date (substring line (match-beginning 1) (match-end 1)))
;;      (setq comment (substring line (match-beginning 2) (match-end 2)))
;;      (list date comment)))
;;  )
;;
;;(defun logger--split-line-3 (line)
;;  (let (date filename comment)
;;    (setq line (d-trim-right line))
;;    (when (string-match "^\\([0-9][0-9][0-9][0-9]-[0-9][0-9]-[0-9][0-9]\\) \\(~/[^ ]*\\) \\(.*\\)$" line)
;;      (setq date     (substring line (match-beginning 1) (match-end 1)))
;;      (setq filename (substring line (match-beginning 2) (match-end 2)))
;;      (setq comment  (substring line (match-beginning 3) (match-end 3)))
;;      (list date filename comment)))
;;  )
;;
;;;
;;; More clever than logger--split-line-1, logger--split-line-2, logger--split-line-3
;;;
;;; USAGE: (logger--split (setq line "2002-02-02 ~/sdfasdfd farticus"))
;;;
;;; USAGE: (logger--split (setq line "2002-02-02 smeggy reggy farticus"))
;;;
;;; USAGE: (logger--split (setq line "TODO EXTRA: smeggy reggy farticus"))
;;;
;;; USAGE: (logger--split (setq line "TODO: smeggy reggy farticus"))
;;;
;;; USAGE: (logger--split (setq line "2008-02-28 > 365-8001 365-8002"))
;;;
;;; (setq line (d-current-line-as-string))
;;; (setq split (logger--split line))
;;;
;;; COOL:
;;; (setq line "2008-11-06 ~/log.txt Voted")
;;; (logger--split line)
;;;
;;; COOL:
;;; (setq line "TODO: I cannot be a wanderer like Stallman")
;;; (logger--split line)
;;;
;;; (setq line "2007-06-15 ~/hairy-lemon/output/davin/*.html")
;;; (logger--split line)
;;;
;;; (setq line "2007-06-15 ~/hairy-lemon/output/davin/*.html Smeggy")
;;; (logger--split line)
;;;
;;; (setq line "2002-02-02 ~/sdfasdfd farticus")
;;; (logger--split line)
;;;
;;; (setq line "TODO: ~/sdf zenophobe")
;;; (logger--split line)
;;;
;;; (logger--split "2009-10-00 d:/home/log.txt Calculator, Glasses and Asthma Medication for exam")
;;; (logger--split "2009-10-00 ~/log.txt Calculator, Glasses and Asthma Medication for exam")
;;;
;;; (d-trim-right nil)
;;;
(defun logger--split (line)
  (let (first second third idx1)
    (assert line)
    (setq line (d-trim-right line))
    (when (not (string= "" line))
      (setq idx1 0)

      ;;(debug)

      (cond
       ((string-match "^\\([0-9][0-9][0-9][0-9]-[0-9][0-9]-[0-9][0-9]\\) " line)
        (setq first (substring line (match-beginning 1) (match-end 1)))
        (setq idx1 (+ idx1 1 (length first))))
       ((string-match "^TODO:" line)
        (setq first "TODO:")
        (setq idx1 (+ idx1 1 (length first))))
       ((string-match "^NOTE:" line)
        (setq first "NOTE:")
        (setq idx1 (+ idx1 1 (length first)))))

      ;;(debug)

      (if (> idx1 (length line))
          (setq line "")
        (setq line (substring line idx1)))

      ;;(debug)

      (when first
        (when (string-match "^\\(~\\|[~a-z]:\\)/[^ ]*" line)
          (setq second (substring line (match-beginning 0) (match-end 0)))
          (setq line (substring line (length second)))
          (if (and (> (length line) 0) (aref line 0)) (setq line (substring line 1))))
        (when (string-match "^.*$" line)
          (setq third (substring line (match-beginning 0) (match-end 0))))
        (list first second third)))))

;; (setq s1 "2005-00-00 ALPHA")
;; (setq s2 "2005-99-99 BETA")
(defun logger--less-than (s1 s2)
  (string< (substring s1 0 10) (substring s2 0 10)))

(defun logger--stable-sort-lines ()
  (let ((list))
    (setq list (d-current-buffer-to-lines))
    (setq list (stable-sort list 'logger--less-than))
    (erase-buffer)
    (let ((ptr list))
      (while ptr
        ;;(debug)
        (insert (car ptr) "\n")
        (setq ptr (cdr ptr))))))

(defun logger--insert-blank-lines ()
  (let (date old-date)
    (goto-char (point-min))
    (while (< (point) (point-max))
      (setq old-date date)
      (setq date (car (logger--split (d-current-line-as-string))))
      ;;(message "date=%s" date)
      (if (not (string= date old-date))
          (insert "\n")
          ;;(debug)
        )
      (forward-line 1))))

;;;
;;; (setq list (directory-files-deep "~/" t "log.txt"))
;;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;
;;; (setq logger--buf-list (directory-files-deep "~/" t "log.txt"))
;;; (insert (prin1-to-string logger--buf-list))

;;(setq logger--buf-list-all (directory-files-deep "~/" t "^log\\(-200[0-9]\\)?.txt$"))
;;(insert (prin1-to-string logger--buf-list-all))

(progn
  (setq logger--buf-list-all '(
                               "~/log.txt"
                               ;;"~/c++-projects/log.txt"
                               "~/dlisp/log.txt"
                               "~/hairy-lemon/src/50webs-com/research/log.txt"
                               "~/hairy-lemon/src/50webs-com/webdesign/log.txt"
                               "~/hairy-lemon/src/log.txt"
                               ;;"~/java-projects/log.txt"
                               ;;"~/text/log.txt")
                               ))

  (setq logger--buf-list
        (mapcar (function (lambda (x) (if (string-match "/log-[0-9][0-9][0-9][0-9]\\.txt$" x) nil x)))
                logger--buf-list-all))
  (setq logger--buf-list (delete "~/text/my-life.txt" logger--buf-list))
  (setq logger--buf-list (delete nil logger--buf-list))

  )

;;(setq logger--buf-list '("l1.txt" "l2.txt"))
;;
;; (logger--generate-browser)
;;
(defun logger--generate-browser ()

  (save-some-buffers 'NO-QUESTIONS)
  (if (get-buffer "*logger*") (kill-buffer "*logger*"))
  (generate-new-buffer "*logger*")

  (let* (;;(ptr-file     '("~/dlisp/log.txt"))
         (ptr-file     logger--buf-list)
         (dest-buf     (get-buffer "*logger*"))
         (source-buf   nil)
         (cur-list     nil)
         (non-cur-list nil)
         (line         nil)
         (p            nil))

    ;;(debug)
    (message "*** log 1") ;; ~/hairy-lemon/src/50webs-com/research/log.txt
    (while ptr-file
      (assert (and 123 (file-exists-p (car ptr-file))))
      (progn

        (if (d-currently-editing-file (car ptr-file))
            (setq cur-list (cons (car ptr-file) cur-list))
          (setq non-cur-list (cons (car ptr-file) non-cur-list)))

        (let ((auto-mode-alist '(("" . fundamental-mode)))) (setq source-buf (find-file-read-only (car ptr-file))))

        ;;(setq source-buf (find-file-literally (car ptr-file)))

        (assert (eq (current-buffer) source-buf))

        (setq p (point))
        ;;(debug)

        (let (date comment list new-list)
          (goto-char (point-min))
          (while (< (point) (point-max))
            (setq list (logger--split (d-current-line-as-string)))
            ;;(debug)
            (when list
              ;;(debug)
              (setq date     (nth 0 list))
              (setq comment  (nth 2 list))

              (if (nth 1 list) (setq comment (concat (nth 1 list) " " comment)))

              ;;(if comment (debug))

              (setq new-list (list date (car ptr-file) comment))
              (if (not (or (string-match "NOTE:" date) (string-match "TODO:" date)))
                  (save-excursion

                    ;;(if (not (string= comment "")) (debug))

                    (set-buffer dest-buf)
                    (goto-char (point-max))

                    ;;(debug)

                    (let ((ptr new-list))
                      (assert ptr)
                      ;;(assert (car ptr))
                      (while ptr
                        (assert ptr)
                        ;;(assert (car ptr))
                        (if (car ptr) (insert (car ptr) " "))
                        (setq ptr (cdr ptr))))
                    (insert "\n"))))
            (forward-line 1)))

        ;;(debug)
        (goto-char p)
        )
      (setq ptr-file (cdr ptr-file)))

    (message "*** log 2 begin stable sort")
    ;;(debug)

    (progn
      (switch-to-buffer dest-buf)
      ;;(debug)
      (logger--stable-sort-lines)
      ;;(sort-lines nil (point-min) (point-max))
      (text-mode)
      ;;(setq major-mode 'fundamental-mode)
      (use-local-map logger--map)
      (setq truncate-lines t)
      (logger--insert-blank-lines)
    )

    ;;(debug)

    (message "*** log 3 begin TODO's")

    (save-excursion
      (setq ptr-file logger--buf-list)
      ;;(setq ptr-file '("~/log.txt" "~/dlisp/log.txt"))
      (while ptr-file
        (when (file-exists-p (car ptr-file))
          (message "shen")
          (find-file (car ptr-file))
          (setq p (point))
          (save-excursion
            (set-buffer dest-buf)
            (let (str dashes)
              ;; (setq s "Hello")
              (setq str (concat "----- FILE: " (car ptr-file)))
              (setq dashes (make-string (- (frame-width) (length str)) ?-))
              (insert str dashes "\n")
              ))
          ;;(save-excursion (set-buffer dest-buf) (insert "\n"))
          (goto-char (point-min))
          (while (re-search-forward "^TODO:" nil t)
            (save-excursion
              (setq comment (nth 2 (logger--split (d-current-line-as-string))))
              (when comment
                ;;(debug)
                (set-buffer dest-buf)
                (goto-char (point-max))
                (insert "TODO: ")
                (insert (car ptr-file))
                (insert " ")
                (insert comment)
                (insert "\n")))
            (forward-line 1)
            (let ((count 0)
                  (line ""))
              (while (looking-at ">.*$")
                (incf count)
                (setq line (d-current-line-as-string))
                (forward-line 1)
                (save-excursion
                  (set-buffer dest-buf)
                  (goto-char (point-max))
                  (insert line "\n")))
              (if (> count 0)
                  (save-excursion
                    (set-buffer dest-buf)
                    (goto-char (point-max))
                    (insert "\n")))))
          (goto-char p))
        (setq ptr-file (cdr ptr-file))))

    ;;(debug)
    (message "*** log 4 begin CULL BUFFERS")

    (progn
      (let ((ptr cur-list)
            (buf nil))
        (while ptr
          (setq buf (d-currently-editing-file (car ptr)))
          (assert buf)
          (set-buffer buf)
          (setq buffer-read-only nil)
          (setq ptr (cdr ptr))))
      (let ((ptr non-cur-list)
            (buf nil))
        (while ptr
          (setq buf (d-currently-editing-file (car ptr)))
          (assert buf)
          ;;(debug)
          (kill-buffer buf)
          (setq ptr (cdr ptr)))))

    (message "*** log 5 goto point max")

    (progn
      ;;
      ;; NOTE: adds an extra line to the bottom for cosmetic value
      ;;
      (set-buffer "*logger*")
      (goto-char (point-max))
      (insert "\n")
      (read-only-mode 1)
      )
    )
  )

(defun logger--generate ()
  (interactive)

  ;;(logger--generate-browser)

  (if (string= (buffer-name) "*logger*")

      (logger--goto-source)

    (if (member (safe-compress-file-name (buffer-file-name)) logger--buf-list)
        (let (split filename)

          (setq split (logger--split (d-current-line-as-string)))
          (setq filename (safe-compress-file-name (buffer-file-name)))

          (logger--generate-browser)
          ;;(debug)
          (goto-char (point-min))

          (switch-to-buffer "*logger*")

          ;;(debug)
          ;; (d-trim-string nil)

          (if split
              (re-search-forward (concat "^"
                                         (regexp-quote (nth 0 split))
                                         " "
                                         (regexp-quote filename)
                                         " "
                                         (regexp-quote (d-trim-string (nth 2 split)))))
            (message "Split not found")
            (goto-char (point-max)))

          (beginning-of-line))

      (logger--generate-browser)
      ;;(forward-line -1)
      ;;(beginning-of-line)
      )))

;;(global-set-key [pause] 'log)
;; (setq l '("2008-11-06" nil "~/log.txt Voted"))
;; (setq l "2008-11-06 ~/log.txt Voted")
;; (logger--split l)
;;
(defun logger--goto-source ()
  (interactive)
  (let ((cur (logger--split (d-current-line-as-string))))
    (if (not cur)
        (error "No match")
      ;;(debug)
      ;;(if (not (nth 1 cur)) (debug))
      (message "shon")
      (find-file (nth 1 cur))
      (goto-char (point-min))
      (re-search-forward (concat "^" (regexp-quote (nth 0 cur)) " " (regexp-quote (nth 2 cur))))
      (beginning-of-line))))

(setq logger--map (make-keymap))
(define-key logger--map [return] 'logger--goto-source)

;;(setq auto-mode-alist
;;      (append '(
;;                ("\\.log$" . text-mode)
;;                ) auto-mode-alist))

(provide 'logger)
