;;; liece-400.el --- Handler routines for 400 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))

(defun* liece-handle-400-messages (number prefix rest)
  "400 replies -- ERRORS"
  (or (string-match "[^ ]* \\([^ ]*\\) *\\([^ ]*\\) *:\\(.*\\)" rest)
      (return-from liece-handle-400-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= target1 "")
	   (liece-insert-error liece-400-buffer
				(concat msg "\n")))
	  ((string= target2 "")
	   (liece-insert-error liece-400-buffer
				(concat msg " (" target1 ")\n")))
	  (t
	   (liece-insert-error liece-400-buffer
				(format"%s %s (%s)\n" target1 msg target2))))))

(defun liece-handle-401-message (prefix rest)
  "ERR_NOSUCHNICK \"<nickname> :No such nick/channel\"."
  (if (string-match "[^ ]+ \\([^ ]+\\)" rest)
      (let ((name (match-string 1 rest)))
	(liece-nick-change name nil)
	(liece-send "WHOWAS %s" name))))

(defun liece-handle-406-message (prefix rest)
  "ERR_WASNOSUCHNICK \"<nickname> :There was no such nickname\"."
  (if (string-match "[^ ]+ \\([^ ]+\\)" rest)
      (let ((nick (match-string 1 rest)))
	(liece-nick-change nick nil)
	(liece-message (_ "No such user %s") nick))))

(defun liece-handle-412-message (prefix rest)
  "ERR_NOTEXTTOSEND \":No text to send\"."
  (liece-message (_ "No text to send")))

(defun liece-iterate-nick (nick)
  (let* ((fmt (format "%s_" nick))
	 (new (substring fmt 0 (min 9 (length fmt)))))
    (if (string= nick new)
	(liece-iterate-nick (format "_%s" nick))
      new)))

(defun liece-handle-432-message (prefix rest)
  "ERR_ERRONEUSNICKNAME	\"<nickname> :Erroneous nickname\"."
  (let ((nick (cond ((string-match "^[^ ]+ +\\([^ ]+\\)" rest)
		     (match-string 1 rest))
		    ((string-match "^ *\\([^ ]+\\)" rest)
		     (match-string 1 rest)))))
    (with-current-buffer liece-command-buffer
      (if (eq liece-nick-accepted 'ok)
	  (setq liece-real-nickname liece-nickname-last))
      (liece-message
       (_ "Erroneous nickname %s.  Choose a new one with %s.")
       nick (substitute-command-keys "\\[liece-command-nickname]"))
      (liece-beep))))

(defun liece-handle-433-message (prefix rest)
  "ERR_NICKNAMEINUSE \"<nickname> :Nickname is already in use\"."
  (let ((nick (cond ((string-match "^[^ ]+ +\\([^ ]+\\)" rest)
		     (match-string 1 rest))
		    ((string-match "^ *\\([^ ]+\\)" rest)
		     (match-string 1 rest)))))
    (cond
     ((and (not (eq liece-nick-accepted 'ok))
	   liece-auto-iterate-nick)
      (liece-send "NICK %s" (liece-iterate-nick nick))
      (setq liece-nick-accepted 'sent))
     (t
      (if (eq liece-nick-accepted 'ok)
	  (setq liece-real-nickname liece-nickname-last))
      (with-current-buffer liece-command-buffer
	(liece-message
	 (_ "Nickname %s already in use.  Choose a new one with %s.")
	 nick (substitute-command-keys "\\[liece-command-nickname]"))
	(liece-beep))))))

(defun liece-handle-442-message (prefix rest)
  "ERR_NOTONCHANNEL \"<channel> :You're not on that channel\"."
  (if (string-match "[^ ]+ \\([^ ]+\\) +:\\(.*\\)" rest)
      (let* ((chnl (liece-channel-virtual (match-string 1 rest)))
	     (rest (match-string 2 rest)))
	(if (liece-channel-member chnl liece-current-channels)
	    (liece-channel-part chnl)
	  (liece-message (_ "You're not on channel %s") chnl)))))

(defun liece-handle-443-message (prefix rest)
  "ERR_USERONCHANNEL \"<channel> <nickname> :is already on channel\"."
  (if (string-match "[^ ]+ \\([^ ]+\\) \\([^ ]+\\)" rest)
      (let ((chnl (match-string 1 rest))
	    (rest (match-string 2 rest)))
	(when (prog1 (liece-channel-p chnl)
		(setq chnl (liece-channel-virtual chnl)))
	  (or (liece-channel-member chnl liece-current-channels)
	      (liece-channel-join chnl)))
	(liece-message (_ "You're already on channel %s") chnl))))

(defun liece-handle-464-message (prefix rest)
  "ERR_PASSWDMISMATCH \":Password incorrect\"."
  (liece-message
   (_ "Password incorrect from %s. Try again with password.") prefix)
  (setq liece-reconnect-with-password t))

(defun liece-handle-482-message (prefix rest)
  "ERR_CHANOPRIVSNEEDED	\"<channel> :You're not channel operator\"."
  (liece-message (_ "You are not a channel operator")))


;;; @ register message handlers
;;;

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

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

(defmacro liece-register-400-handler (num)
  `(progn
     (liece-handler-define-function
      ,(number-to-string num) '(prefix require "400")
      ',(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-400-handler 401)
(liece-register-400-handler 406)

(liece-register-400-handler 412)

(liece-register-400-handler 432)
(liece-register-400-handler 433)

(liece-register-400-handler 442)
(liece-register-400-handler 443)

(liece-register-400-handler 464)

(liece-register-400-handler 482)

(provide 'liece-400)

;;; liece-400.el ends here
