;; Get the select code from cmd-more.
(require 'tools)

; Alists have the form (("name") ("anothername") ("foo"))
(defvar zwrite-recipient-list (list (list (user-login-name))))
(defvar zwrite-instance-list (list (list )))
(defvar zwrite-class-list (list (list )))
(defvar zwrite-last-class nil)

(defun zwrite-add-to-list (list name)
  "Make a new entry at the beginning of LIST which contains NAME as
it's car.  Creates a list suitable for use as an alist."
  (if (not (assoc name list))
      (let ((new-entry (cons name nil))
	    (new-cell (cons (car list) (cdr list))))
	(setcar list new-entry)
	(setcdr list new-cell)
	list)))

(defun zwrite-personal (&optional recip)
  (interactive)
  (setq zwrite-last-recipient
	(zwrite-get-option "Send personal message to"
			   recip zwrite-last-recipient
			   zwrite-recipient-list))
  (zwrite-triple "message" "personal" zwrite-last-recipient nil
		 (cons zwrite-last-recipient zwrite-recipient-list)))

(defun zwrite-instance (&optional inst)
  (interactive)
  (setq zwrite-last-instance  
	(zwrite-get-option "Write to instance" 
			   inst zwrite-last-instance
			   zwrite-instance-list))
  (zwrite-triple "message" zwrite-last-instance "*" nil 
		 (cons zwrite-last-instance zwrite-instance-list)))
  
(defun zwrite-class (&optional class)
  (interactive)
  (debug)
  (setq zwrite-last-class
	(zwrite-get-option "Write to class(instance)"
			   class zwrite-last-class
			   zwrite-class-list))
  (string-match "\\(.*\\)(\\(.*\\))" zwrite-last-class)
  (zwrite-triple (substring zwrite-last-class (match-beginning 1) (match-end 1))
		 (substring zwrite-last-class (match-beginning 2) (match-end 2))
		 "*" nil (cons zwrite-last-class zwrite-class-list)))

(defun zwrite-get-option (prompt specified last list)
  (or specified
      (let ((input (completing-read 
		    (format "%s [%s]: " prompt last)
		    list)))
	(if (equal input "") nil input))
      last))

(defun zwrite-triple (class instance recipient &optional
			    generic-buffer-name save-pair)
  "Start a zwrite process to the given triple.  Allow the
user to enter a message.  Run zwrite-hook."
  (debug)
  (if (string-equal instance "")
      (error "Ken you're being lame."))
  (let ((b (generate-new-buffer 
	    (if generic-buffer-name
		"*Zwrite*"
	      (format "*Zwrite to <%s,%s,%s>*" class instance recipient)))))
    (switch-to-buffer b)
    (if (< (window-height) zwrite-min-height)
	(enlarge-window (- zwrite-min-height (window-height))))
    (indented-text-mode)
    (insert "*** Zwrite process status: checking for subscribers\n\n")
    (setq local-abbrev-table zwrite-abbrev-table)
    (setq abbrev-mode t)
    (setq major-mode 'zwrite-mode)
    (setq mode-name "Zwrite")
    (make-local-variable 'zwrite-target)
    (make-local-variable 'zwrite-process)
    (make-local-variable 'zwrite-save-pair)
    (setq zwrite-target (list class instance recipient))
    (setq zwrite-save-pair save-pair)
    (use-local-map (make-sparse-keymap))
    (local-set-key "\C-c\C-c" 'zwrite-send)
    (message "Press C-c C-c to send message")
    (setq zwrite-process (start-process "Zwrite" b (concat zwrite-path "zwrite")
			   (if (equal recipient "*")
			       "-n"
			     recipient)
			   "-c" class "-i" instance))
    (set-process-sentinel zwrite-process 'zwrite-sentinel)
    (set-process-filter zwrite-process 'zwrite-filter)
    (run-hooks 'zwrite-hook)))


(defun zwrite-filter (proc str)
  (save-excursion
    (set-buffer (process-buffer proc))
    (goto-char (point-min))
    (search-forward ": ")
    (let ((start (point)))
      (end-of-line)
      (delete-region start (point)))
    (cond
     ((string-match (regexp-quote "Type your message now") str)
      (insert "Ready for message"))
     ((string-match (regexp-quote "Not logged in") str)
      (insert "*** NO SUBSCRIBERS ***"))
     ((string-match (regexp-quote "Message sent") str)
      (insert "zwrite successful")
      (if zwrite-save-pair
	  (zwrite-add-to-list (cdr zwrite-save-pair) (car zwrite-save-pair)))
      (message "Message sent to %s" zwrite-target))
     (t
      (insert str)))))
