; This file contains some functions for Gnus, to be used with
; egowatch.pl.  The main function it adds is add-watch, which is bound
; to (f5) in the gnus-summary-mode-map.  It allows the user to save
; match-data to be used by egowatch.pl, so that later followups will
; prompt an email to the user.
;
; See egowatch.pl for instructions and explanations.
;
; Credits and blame:
;
; This program was written by Jesse Hughes, jesseh@cs.kun.nl.  It may
; be freely modified, distributed, whatever, as long as the source
; file continues to acknowledge the contribution of the original
; author.

; Please email for any fixes, questions, complaints, suggestions, etc.
; I'm not much of a Perl hacker, so criticisms are welcome.

; Format of the watch file:
; newsgroup name:header:contents:expiration
;
; comment character "#"

(require 'string) 

(define-key gnus-summary-mode-map [(f5)] 'add-watch)

;;Maybe some day I'll write this.  It would allow one to mark the
;;articles in the summary buffer that match something in the
;;watch-file.
(defun read-watch-file())

;;Maybe some day I'll write this, too, so that one can delete entries
;;in the watch-file from the summary buffer.  I'm not sure how useful
;;this is.  In any case, at present, one can do this by hand.
(defun del-watch())

;;;
;
; See the perl function quotemeta.
;
;;;
(defun quote-meta (str)
  (let ((ret (string-replace-match "[^a-zA-Z0-9]" str "\\\\\\&" nil t)))
    (if ret
	ret
      str)))

(defun read-exp-date-str ()
  (let ((entered nil))
    (while 
	(progn
	  (setq entered (read-string 
			 "Expiration date: " 
			 (format-time-string 
			  "%D %R"
			  (cons (+
			      (car (current-time))
			      (/ (* 30 24 60 60)
				 (lsh 2 15)))
			     (+ 
			      (car (cdr (current-time)))
			      (% (* 30 24 60 60)
				 (lsh 2 15)))))))
      (let* ((date (car (string-split "[ ]+" entered)))
	     (time (cadr (string-split "[ ]+"entered)))
	     (month (string-to-int (car (string-split "/" date))))
	     (day (string-to-int (cadr (string-split "/" date))))
	     (year (+ 2000 (string-to-int (caddr (string-split "/" date)))))
	     (hour (string-to-int (car (string-split ":" time))))
	     (min (string-to-int (cadr (string-split ":" time)))))
	;seconds minutes hour day month year
	(not (encode-time 0 min hour day month year)))))
	entered))


;;; 
;
; add-watch
; 
;;;

(defun add-watch (header grp type val expiration-date-str) 
  "Adds a record to the egowatch file.\nSee egowatch.pl for explanation of this file.\n\nThe inputs are:\n   header          : A newsgroup header.\n   grp             : Newsgroup.\n   type            : Substring or regexp match type.\n   val             : Match value.\n   expiration-date : Date at which this record expires."
  (interactive 
   (let* ((header 
	   (progn (gnus-summary-scroll-up 0)
		  ;; Select current article
		  (let ((sel (completing-read "Header [subject]: " 
					      '(("Subject" 0)
						("subject" 0)
						("References" 1)
						("references" 1)
						("From" 2)
						("from" 2)
						))))
		    (if (not (string= sel "")) 
			(capitalize sel)
		      "Subject"))))
	  (grp (read-string "Newsgroup: " (if gnus-newsgroup-name gnus-newsgroup-name "")))
	  ;; Question: What is the second element of the alist for 
	  ;; completing-read *used* for?
	  (type (let ((sel 
		       (completing-read "Match type [substring]: " 
					'(("regexp" 0) 
					  ("substring" 1)) nil t)))
		  (if (not (string= sel "")) sel
		    "substring")))	 
	  (field (condition-case nil
		     (progn (set-buffer gnus-original-article-buffer)
			    (if (string= "References" header)
				(mail-fetch-field "Message-ID")
				(mail-fetch-field header)))
		   (error "")))
	  (val (read-string (concat (capitalize type) " match data: ") 
			    (if (string= type "regexp")
				(quote-meta field) field)))
	  (expiration-date-str (read-exp-date-str)))
     (list header grp type val expiration-date-str)))
  (save-excursion
    (if (string= type "substring")
	(setq val (quote-meta val)))
    (set-buffer (find-file-noselect "/home/jesse/.newswatch/newswatch.in" t))
    (goto-char (point-max))
    (if (not (= 0 (current-column)))
	(newline))
    (insert "\"" grp "\",\"" header "\",\"" val "\",\"")
    (call-process "date" "/dev/null" t nil  (concat "-d " expiration-date-str) "+%s")
    (delete-char -1) ;;Remove newline.
    (insert "\"")
    (save-buffer)
  ))



(provide 'ego-watch)