;;; liece-200.el --- Handler routines for 200 numeric reply.
;; Copyright (C) 1998-2000 Daiki Ueno

;; Author: Daiki Ueno <ueno@unixuser.org>
;; Created: 1998-09-28
;; Revised: 1998-11-25
;; Keywords: IRC, liece

;; This file is part of Liece.

;; 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 2, 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 GNU Emacs; see the file COPYING.  If not, write to the
;; Free Software Foundation, Inc., 59 Temple Place - Suite 330,
;; Boston, MA 02111-1307, USA.


;;; Commentary:
;; 

;;; Code:

(eval-when-compile
  (require 'liece-inlines)
  (require 'liece-intl)
  (require 'liece-misc)
  (require 'liece-commands))

(defun* liece-handle-200-messages (number prefix rest)
  "200 replies"
  (or (string-match "[^ ]* \\([^ ]*\\) *\\([^ ]*\\) *:\\(.*\\)" rest)
      (return-from liece-handle-200-messages))
  (let ((target1 (match-string 1 rest))	(target2 (match-string 2 rest))
	(msg (match-string 3 rest)))
    (setq target1 (liece-channel-virtual target1)
	  target2 (liece-channel-virtual target2))
    (cond ((string-equal target1 "")
	   (liece-insert-info liece-200-buffer (concat msg "\n")))
	  ((string-equal target2 "")
	   (liece-insert-info
	    liece-200-buffer (concat target1 " " msg "\n")))
	  (t
	   (liece-insert-info
	    liece-200-buffer (concat target1 " " msg " (" target2 ")\n"))))))

(defun* liece-handle-200-message (prefix rest)
  "RPL_TRACELINK \"Link <version & debug level> <destination> <next server>\""
  (or (string-match "Link \\([^ ]*\\)[ :]*\\([^ ]*\\)[ :]*\\([^ ]*\\)[ :]*\\([^ ]*\\)[ :]*\\([^ ]*\\)[ :]*\\([^ ]*\\)[ :]*\\(.*\\)" rest)
      (return-from liece-handle-200-message))
  (let ((version (match-string 1 rest)) (dest (match-string 2 rest))
	(next (match-string 3 rest)) (ver (match-string 4 rest))
	(sec (match-string 5 rest))
	(q1 (match-string 6 rest)) (q2 (match-string 7 rest)))
    (liece-insert-info liece-200-buffer
			(concat prefix
				" ("
				version (if ver (concat " " ver) "")
				") --- " dest "\n"))
    (liece-insert-info liece-200-buffer
			(concat "\t[" (liece-convert-seconds sec) "]"
				(if (not (string= q1 "")) (concat " " q1) "")
				(if (not (string= q2 "")) (concat "/" q2) "")
				" (next " next ")\n"))))
    
(defun* liece-handle-201-message (prefix rest)
  "RPL_TRACECONNECTING \"Try. <class> <server>\""
  (or (string-match "[^ ]* [^ ]* \\([0-9]*\\)[ :]*\\(.*\\)" rest)
      (return-from liece-handle-201-message))
  (let ((class (match-string 1 rest))
	(server (match-string 2 rest)))
    (liece-insert-info liece-200-buffer
			(format (_ "%s Trying to connect to %s (class %s)\n")
				prefix server class))))

(defun* liece-handle-202-message (prefix rest)
  "RPL_TRACEHANDSHAKE \"H.S. <class> <server>\""
  (or (string-match "[^ ]* [^ ]* \\([0-9]*\\)[ :]*\\(.*\\)" rest)
      (return-from liece-handle-202-message))
  (let ((class (match-string 1 rest)) (server (match-string 2 rest)))
    (liece-insert-info liece-200-buffer
			(format (_ "%s Handshaking with %s (class: %s)\n")
				prefix server class))))

(defun* liece-handle-203-message (prefix rest)
  "RPL_TRACEUNKNOWN \"???? <class> [<client IP address in dot form>]\""
  (or (string-match "[^ ]* [^ ]* \\([^ ]*\\)[ :]+\\(.*\\)" rest)
      (return-from liece-handle-203-message))
  (let ((class (match-string 1 rest)) (who (match-string 2 rest)))
    (liece-insert-info liece-200-buffer
			(concat "Class " class ": unknown " who "\n"))))

(defun* liece-handle-204-message (prefix rest)
  "RPL_TRACEOPERATOR \"Oper <class> <nick>\""
  (or (string-match "[^ ]* [^ ]* \\([^ ]*\\)[ :]+\\(.*\\)" rest)
      (return-from liece-handle-204-message))
  (let ((class (match-string 1 rest)) (who (match-string 2 rest)))
    (liece-insert-info liece-200-buffer
			(concat "Class " class ": operator " who "\n"))))

(defun* liece-handle-205-message (prefix rest)
  "RPL_TRACEUSER \"User <class> <nick>\""
  (or (string-match "[^ ]* [^ ]* \\([0-9]*\\)[ :]*\\(.*\\)" rest)
      (return-from liece-handle-205-message))
  (let ((hops (match-string 1 rest)) (where (match-string 2 rest)))
    (liece-insert-info liece-200-buffer
			(concat "Class " hops ": user " where "\n"))))

(defun* liece-handle-206-message (prefix rest)
  "RPL_TRACESERVER \"Serv <class> <int>S <int>C <server> <nick!user|*!*>@<host|server>\""
  (or (string-match "Serv \\([^ ]*\\) \\(.*\\)" rest)
      (return-from liece-handle-206-message))
  (let ((class (match-string 1 rest)) (pars (match-string 2 rest)))
    (cond
     ((string-match "\\([0-9]*\\)S *\\([0-9]*\\)C *\\([^ ]*\\) *\\([^ ]*\\)[ :]*\\(.*\\)" pars)
      (let ((servers (match-string 1 pars)) (clients (match-string 2 pars))
	    (next (match-string 3 pars)) (by (match-string 4 pars))
	    (type (match-string 5 pars)))
	
	;; This is automatic connection line
	(setq by (if (string-match "^AutoConn\\.!" by)
		     "auto connection"
		   (concat "by " by)))
	
	(liece-insert-info liece-200-buffer
			    (concat prefix " --- " next "\n"))
	(liece-insert-info liece-200-buffer
			    (concat "\t[" clients " clients, "
				    servers " servers]"
				    " Class " class ", Type " type " " by
				    "\n"))))
     (t
      (liece-insert-info liece-200-buffer
			  (format "Class %s: server %s --- %s\n"
				  class prefix pars))))))

(defun* liece-handle-207-message (prefix rest)
  "RPL_TRACESERVICE \"Service <class> <name> <type> <wants>\""
  (or (string-match "[^ ]* Service \\([0-9]*\\) \\(.*\\)" rest)
      (return-from liece-handle-207-message))
  (let ((class (match-string 1 rest)) (service (match-string 2 rest)))
    (liece-insert-info liece-200-buffer
			(concat "Class " class ": service " service "\n"))))

(defun liece-handle-208-message (prefix rest)
  "RPL_TRACENEWTYPE \"<newtype> 0 <client name>\"."
  (liece-insert-info liece-200-buffer
		      (format "%s: RPL_TRACENEWTYPE: Why this?\n" prefix)))

(defun* liece-handle-209-message (prefix rest)
  "RPL_TRACECLASS \"Class <class> <links>\""
  (or (string-match "[^ ]* Class \\([0-9]*\\) \\([0-9]*\\)" rest)
      (return-from liece-handle-209-message))
  (let ((class (match-string 1 rest)) (entries (match-string 2 rest)))
    (liece-insert-info liece-200-buffer
		       (concat "Class " class ": " entries
			       "entries linked\n"))))

(defun* liece-handle-211-message (prefix rest)
  "RPL_STATSLINKINF \"<linkname> <sendq> <sent messages> <sent bytes> <received messages> <received bytes> <time open>\""
  (or (string-match "\\([^ ]*\\) \\([^ ]*\\) \\([^ ]*\\) \\([^ ]*\\) \\([^ ]*\\) \\([^ ]*\\) \\([^ ]*\\)[ :]+\\(.*\\)" rest)
      (return-from liece-handle-211-message))
  (let ((link (match-string 2 rest)) (sendq (match-string 3 rest))
	(sendm (match-string 4 rest)) (sendb (match-string 5 rest))
	(rcvem (match-string 6 rest)) (rcveb (match-string 7 rest))
	(open (match-string 8 rest)))
    (liece-insert-info liece-200-buffer
			(format "%-35s %s: %5s%7s%10s%7s%10s %s\n"
				link prefix sendq sendm sendb
				rcvem rcveb open))))

(defun* liece-handle-212-message (prefix rest)
  "RPL_STATSCOMMANDS \"<command> <count>\""
  (or (string-match "[^ ]* \\([^ ]*\\) \\([0-9]*\\)" rest)
      (return-from liece-handle-212-message))
  (let ((cmd (match-string 1 rest)) (times (match-string 2 rest)))
    (liece-insert-info liece-200-buffer
			(format "%s has been used %s times after startup\n"
				cmd times))))

(defun* liece-handle-213-message (prefix rest)
  "RPL_STATSCLINE \"C <host> * <name> <port> <class>\""
  (or (string-match "[^ ]* C \\([^ ]*\\) \\* \\([^ ]*\\) \\([0-9]*\\) \\([0-9]*\\)" rest)
      (return-from liece-handle-213-message))
  (let ((canon (match-string 1 rest)) (name (match-string 2 rest))
	(port (match-string 3 rest)) (class (match-string 4 rest)))
    (liece-insert-info liece-200-buffer
			(concat "Connect to " canon ":" port
				(if (not (string= class ""))
				    " (Class " class ")" "")
				"\n"))
    (liece-insert-info liece-200-buffer
			(concat "\t[" name "]\n"))))

(defun* liece-handle-214-message (prefix rest)
  "RPL_STATSNLINE \"N <host> * <name> <port> <class>\""
  (or (string-match "[^ ]* N \\([^ ]*\\) \\* \\([^ ]*\\) \\([0-9]*\\) \\([0-9]*\\)" rest)
      (return-from liece-handle-214-message))
  (let ((canon (match-string 1 rest)) (name (match-string 2 rest))
	(port (match-string 3 rest)) (class (match-string 4 rest)))
    (liece-insert-info liece-200-buffer
			(concat "Accept " canon ":" port
				(if (not (string= class ""))
				    " (Class " class ")" "")
				"\n"))
    (liece-insert-info liece-200-buffer
			(concat "\t[" name "]\n"))))

(defun* liece-handle-215-message (prefix rest)
  "RPL_STATSILINE \"I <host> * <host> <port> <class>\""
  (or (string-match "[^ ]* I \\([^ ]*\\) \\(.*\\) \\([^ ]*\\)" rest)
      (return-from liece-handle-215-message))
  (let ((domain (match-string 1 rest)) (passwd (match-string 2 rest))
	(redomain (match-string 3 rest)))
    (liece-insert-info liece-200-buffer
			(format "I:%s:%s:%s\n" domain passwd redomain))))

(defun* liece-handle-216-message (prefix rest)
  "RPL_STATSKLINE \"K <host> * <username> <port> <class>\""
  (or (or (string-match
	   "[^ ]* K \\([^ ]*\\) \\(.\\) \\([^ ]*\\) 0 -1" rest)
	  (string-match
	   "[^ ]* K \\([^ ]*\\) \\([^ ]*\\) \\([^ ]*\\) 0 [:]*-1" rest))
      (return-from liece-handle-216-message))
  (let ((host (match-string 1 rest)) (pass (match-string 2 rest))
	(user (match-string 3 rest)))
    (liece-insert-info liece-200-buffer
			(format "K:%s:%s:%s\n" host pass user))))

(defun* liece-handle-217-message (prefix rest)
  "RPL_STATSQLINE \"Q %s %s %s %d %d\""
  (or (string-match
       "[^ ]* Q \\([^ ]*\\) \\(.\\) \\([^ ]*\\) \\(.*\\)" rest)
      (return-from liece-handle-217-message))
  (let ((reason (match-string 1 rest)) (star (match-string 2 rest))
	(host (match-string 3 rest)) (stuff (match-string 4 rest)))
    (liece-insert-info liece-200-buffer
			(format "Q:%s:%s:%s:%s\n" reason star host stuff))))

(defun* liece-handle-218-message (prefix rest)
  "RPL_STATSYLINE \"Y <class> <ping frequency> <connect  frequency> <max sendq>\""
  (or (string-match "[^ ]* Y " rest)
      (return-from liece-handle-218-message))
  (let* ((args (split-string (substring rest (match-end 0))))
	 (class (pop args)) (pingfreq (pop args)) (confreq (pop args))
	 (maxlinks (pop args)) (qlen (pop args)))
    (liece-insert-info liece-200-buffer
			(concat "Class " class ": \n"))
    (liece-insert-info liece-200-buffer
			(concat "\tPing frequency " pingfreq " (sec)\n"))
    (liece-insert-info liece-200-buffer
			(concat "\tConnection frequency " confreq " (sec)\n"))
    (liece-insert-info liece-200-buffer
			(concat "\tMaximum links " maxlinks "\n"))
    (when qlen
      (liece-insert-info liece-200-buffer
			  (concat "\tMaximum amount of send buffer "
				  qlen " (bytes)\n")))))

(defun liece-handle-219-message (prefix rest)
  "RPL_ENDOFSTATS \"<stats letter> :End of /STATS report\"."
  nil)

(defun liece-handle-221-message (prefix rest)
  "RPL_UMODEIS \"<user mode string>\"."
  (if (string-match "[^ ]* \\(.*\\)" rest)
      (liece-insert-info liece-200-buffer
			  (format (_ "Mode for you is %s\n")
				  (match-string 1 rest)))))

;;;
;;; 230 series not implemented as 7/94
;;;
(defun liece-handle-231-message (prefix rest)
  nil)

(defun liece-handle-232-message (prefix rest)
  nil)

(defun liece-handle-233-message (prefix rest)
  nil)

(defun liece-handle-234-message (prefix rest)
  nil)

(defun liece-handle-235-message (prefix rest)
  nil)

(defun liece-handle-241-message (prefix rest)
  "RPL_STATSLLINE \"L <hostmask> * <servername> <maxdepth>\"."
  (if (string-match "[^ ]* \\(.*\\)" rest)
      (liece-insert-info liece-200-buffer
			  (concat (match-string 1 rest) "\n"))))

(defun liece-handle-242-message (prefix rest)
  "RPL_STATSUPTIME \":Server Up %d days %d:%02d:%02d\"."
  (if (string-match "[^ ]* :\\(.*\\)" rest)
      (liece-insert-info liece-200-buffer
			  (concat (match-string 1 rest) "\n"))))

(defun liece-handle-243-message (prefix rest)
  "RPL_STATSOLINE \"O <hostmask> * <name>\"."
  (if (string-match "[^ ]* \\(.*\\)" rest)
      (liece-insert-info liece-200-buffer
			  (concat (match-string 1 rest) "\n"))))

(defun liece-handle-244-message (prefix rest)
  "RPL_STATSHLINE \"H <hostmask> * <servername>\"."
  (if (string-match "[^ ]* \\(.*\\)" rest)
      (liece-insert-info liece-200-buffer
			  (concat (match-string 1 rest) "\n"))))

(defun liece-handle-245-message (prefix rest)
  "RPL_STATSSLINE \"S <hostmask> * <servicename> <servicetype> <class>\"."
  (if (string-match "[^ ]* \\(.*\\)" rest)
      (liece-insert-info liece-200-buffer
			  (concat (match-string 1 rest) "\n"))))

(defun liece-handle-262-message (prefix rest)
  "RPL_ENDOFTRACE \"<nickname> <target> <version> :End of TRACE\"."
  nil)


;;; @ register message handlers
;;;

(eval-when-compile (require 'liece-handler))

(liece-handler-define-backend "200")

(defmacro liece-register-200-handler (num)
  `(progn
     (liece-handler-define-function
      ,(number-to-string num) '(prefix rest "200")
      ',(intern (format "liece-handle-%03d-message" num)))
     (defvar ,(intern (format "liece-%03d-hook" num)) nil)
     (defvar ,(intern (format "liece-after-%03d-hook" num)) nil)))

(liece-register-200-handler 200)
(liece-register-200-handler 201)
(liece-register-200-handler 202)
(liece-register-200-handler 203)
(liece-register-200-handler 204)
(liece-register-200-handler 205)
(liece-register-200-handler 206)
(liece-register-200-handler 207)
(liece-register-200-handler 208)
(liece-register-200-handler 209)

(liece-register-200-handler 211)
(liece-register-200-handler 212)
(liece-register-200-handler 213)
(liece-register-200-handler 214)
(liece-register-200-handler 215)
(liece-register-200-handler 216)
(liece-register-200-handler 217)
(liece-register-200-handler 218)
(liece-register-200-handler 219)

(liece-register-200-handler 221)

(liece-register-200-handler 231)
(liece-register-200-handler 232)
(liece-register-200-handler 233)
(liece-register-200-handler 234)
(liece-register-200-handler 235)

(liece-register-200-handler 241)
(liece-register-200-handler 242)
(liece-register-200-handler 243)
(liece-register-200-handler 244)
(liece-register-200-handler 245)
(liece-register-200-handler 262)

(provide 'liece-200)

;;; liece-200.el ends here
