##
## user.py -- IRC server interface.
##
## Copyleft 1997 Teemu Kalvas <chery@s2.org>
##

## +class User              ()
##  -method read            (p)     persistent storage object
##  -method write           (p)     persistent storage object
##  -method handle_XXX      (p)     persistent storage object
##  -method handle_cmd_XXX  (p,     persistent storage object
##                           tail)  arguments to the command
##  -method sock
##  -method out
##  -method connected

import curses
import fcntl
import IOCTL
import string
import struct
import sys
import time

import config

class User:
    def __init__(self):
	self.sock = sys.stdin
	self.out = []
	self.connected = 1

    def read(self, p):
	ch = p.screen.window.getch()
	if (ch >= 32 and ch < 127) or (ch >= 160 and ch < 256):
	    p.screen.edit_field.insert(ch)
	else:
	    handler = 'handle_none'
	    if ch >= curses.KEY_MIN and ch <= curses.KEY_MAX:
		handler = 'handle_' + curses.keyname(ch)
            elif ch > 0 and ch < 27:
                handler = 'handle_ctrl_' + chr(ch + 96)
            elif ch >= 27 and ch < 32:
                handler = 'handle_ctrl_' + \
                          ['leftbracket', 'backslash', 'rightbracket', 'caret',
                           'underscore'][ch - 27]
	    if config.__dict__.has_key(handler):
		config.__dict__[handler](self, p)
            elif User.__dict__.has_key(handler):
                User.__dict__[handler](self, p)
	    elif config.verbose:
		p.screen.current.log('*** unknown: ' + handler)

    def write(self, p):
	scr = p.screen
	if scr.touched & 64:
	    scr.log_area = 0
	    scr.stat_area = 0
	    scr.edit_area = 0
	    height, width = struct.unpack('4h',
					  fcntl.ioctl(sys.stdout.fileno(),
						      IOCTL.TIOCGWINSZ,
						      struct.pack('4h', 0, 0,
								  0, 0)))[:2]
	    curses.resizeterm(height, width)
	    scr.log_area = scr.window.subwin(height - 2, width, 0, 0)
	    scr.log_area.scrollok(1)
	    scr.stat_area = scr.window.subwin(1, width, height - 2, 0)
	    scr.edit_area = scr.window.subwin(1, width, height - 1, 0)
	    scr.touched = 63
	if scr.touched & 8:
	    scr.current.redraw()
	if scr.touched & 16:
	    scr.stat_line.redraw()
	if scr.touched & 32:
	    scr.edit_field.redraw()
	scr.edit_area.move(0, scr.edit_field.position -	scr.edit_field.offset)
	if scr.touched & 1:
	    scr.log_area.touchwin()
	    scr.log_area.refresh()
	if scr.touched & 2:
	    scr.stat_area.touchwin()
	    scr.stat_area.refresh()
	scr.edit_area.touchwin()
	scr.edit_area.refresh()
	p.screen.touched = 0
	self.out = []

    def handle_key_backspace(self, p):
	p.screen.edit_field.del_char_left()

    def handle_key_end(self, p):
	p.screen.edit_field.line_end()

    def handle_key_enter(self, p):
	self.handle_ctrl_m(p)

    def handle_key_home(self, p):
	p.screen.edit_field.line_beg()

    def handle_key_left(self, p):
	p.screen.edit_field.char_left()

    def handle_key_npage(self, p):
	p.screen.current.page_down()

    def handle_key_ppage(self, p):
	p.screen.current.page_up()

    def handle_key_right(self, p):
	p.screen.edit_field.char_right()

    def handle_ctrl_a(self, p):
	p.screen.edit_field.line_beg()

    def handle_ctrl_b(self, p):
	p.screen.edit_field.char_left()

    def handle_ctrl_d(self, p):
	p.screen.edit_field.del_char_right()

    def handle_ctrl_e(self, p):
	p.screen.edit_field.line_end()

    def handle_ctrl_f(self, p):
	p.screen.edit_field.char_right()

    def handle_ctrl_k(self, p):
	p.screen.edit_field.del_line_end()

    def handle_ctrl_l(self, p):
	p.screen.touched = p.screen.touched | 63

    def handle_ctrl_m(self, p):
	screen = p.screen
	line = screen.edit_field.get_string()
	if len(line) > 0:
	    if line[0] not in config.cmd_chars:
		current = screen.current
		current.server.out.append('PRIVMSG ' + current.name + ' :' +
					  line)
		current.log('<' + current.server.nick + '> ' + line)
	    else:
		f = string.find(line, ' ')
		if f <> -1:
		    cmd, tail = line[1:f], line[f + 1:]
		else:
		    cmd, tail = line[1:], ''
		handler = 'handle_cmd_' + cmd
		if config.__dict__.has_key(handler):
		    config.__dict__[handler](self, p, tail)
		elif User.__dict__.has_key(handler):
		    User.__dict__[handler](self, p, tail)
	screen.edit_field.reset()

    def handle_ctrl_n(self, p):
	p.screen.current.page_down()

    def handle_ctrl_p(self, p):
	p.screen.current.page_up()

    def handle_ctrl_u(self, p):
	p.screen.edit_field.reset()

    def handle_ctrl_underscore(self, p):
	p.screen.prev()

    def handle_ctrl_backslash(self, p):
	p.screen.next()

    def handle_cmd_ctcp(self, p, tail):
	f = string.find(tail, ' ')
	if f <> -1:
	    p.screen.current.server.out.append('PRIVMSG ' + tail[:f] +
					       ' :\001' + tail[f+1:] + '\001')

    def handle_cmd_exit(self, p, tail):
	p.screen.current.server.out.append('QUIT :' + tail)
	p.screen.current.server.quitting = 1

    def handle_cmd_join(self, p, tail):
	if tail <> '':
	    p.screen.current.server.out.append('JOIN ' + tail)
	else:
	    p.screen.current.server.out.append('JOIN ' + p.screen.current.name)

    def handle_cmd_kick(self, p, tail):
	current = p.screen.current
	f = string.find(tail, ' ')
	if f <> -1:
	    current.server.out.append('KICK ' + current.name + ' ' + tail[:f] +
				      ' :' + tail[f + 1:])
	else:
	    current.server.out.append('KICK ' + current.name + ' ' + tail +
				      ' :')

    def handle_cmd_leave(self, p, tail):
	win = p.screen.current
	name = win.name
	serv = win.server
	if name[0] in '#&' and serv.channels[name][1] <> {}:
	    serv.out.append('PART ' + name + ' :' + tail)
	else:
	    p.screen.current = win.next
	    p.screen.touched = p.screen.touched | 63
	    win.next.prev = win.prev
	    win.prev.next = win.next
	    del serv.channels[name]

    def handle_cmd_me(self, p, tail):
	current = p.screen.current
	serv = current.server
	serv.out.append('PRIVMSG ' + current.name + ' :\001ACTION ' + tail +
			'\001')
	serv.channels[config.low(current.name)][0].log('* ' + serv.nick + ' ' +
						       tail)

    def handle_cmd_msg(self, p, tail):
	server = p.screen.current.server
	f = string.find(tail, ' ')
	if f <> -1:
	    chan = config.low(tail[:f])
	    tail = tail[f + 1:]
	    server.out.append('PRIVMSG ' + chan + ' :' + tail)
	    if server.channels.has_key(chan):
		server.channels[chan][0].log('<' + server.nick + '> ' + tail)
	    else:
		server.window.log('-> *' + chan + '* ' + tail)

    def handle_cmd_ping(self, p, tail):
	serv = p.screen.current.server
	serv.out.append('PING ' + serv.window.name)
	serv.ping_time = time.time()

    def handle_cmd_query(self, p, tail):
	serv = p.screen.current.server
	win = p.screen.new_window(tail, serv)
	serv.channels[config.low(tail)] = win, {}

    def handle_cmd_quit(self, p, tail):
	for serv in p.servers[1:]:
	    serv.out.append('QUIT :' + tail)
	    serv.quitting = 1

    def handle_cmd_quote(self, p, tail):
	p.screen.current.server.out.append(tail)

    def handle_cmd_reload(self, p, tail):
	p.reload = 1

    def handle_cmd_terminate(self, p, tail):
	p.quit = 1

    def handle_cmd_topic(self, p, tail):
	p.screen.current.server.out.append('TOPIC ' + p.screen.current.name +
					   ' :' + tail)

    def handle_cmd_whois(self, p, tail):
	p.screen.current.server.out.append('WHOIS ' + tail + ' ' + tail)

    def handle_cmd_aotest(self, p, tail):
	if config.autoop(tail, p.screen.current.name):
	    str = ''
	else:
	    str = 'not '
	p.screen.current.log('*** ' + tail + ' is ' + str + 'auto-opped')

## End. ##
