#!/usr/bin/python
# -*- coding: utf-8 -*-
### BEGIN LICENSE
# Copyright (C) 2009 Jono Bacon <jono@ubuntu.com>
# Copyright (C) 2010 Michael Budde <mbudde@gmail.com>
# Copyright (c) 2011 John S Gruber <johnsgruber@gmail.com>
#
#This program is free software: you can redistribute it and/or modify it
#under the terms of the GNU General Public License version 3, as published
#by the Free Software Foundation.
#
#This program is distributed in the hope that it will be useful, but
#WITHOUT ANY WARRANTY; without even the implied warranties of
#MERCHANTABILITY, SATISFACTORY QUALITY, 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 this program.  If not, see <http://www.gnu.org/licenses/>.
### END LICENSE

import gtk
import gobject
import urlparse
import logging
import pango
import time

from lernid.LernidPreferences import Preferences
from lernid.widgets.IrcWidget import IrcWidget

from lernid import IrcBackend
from lernid.LernidOptions import Options

class Chatroom(IrcWidget):

    __gtype_name__ = 'LernidNativeChatroom'

    __gsignals__ = {
        'members-changed': (
            gobject.SIGNAL_RUN_LAST, None, (object,)
        ),
    }

    def __init__(self):
        IrcWidget.__init__(self, 'chatroom')
        self.set_property('can-focus', True)

        builder = self.builder_with_file('ChatWidget.ui')

        scroll = builder.get_object('scroll')
        self._adjust = scroll.get_vadjustment()

        self.add(builder.get_object('vbox1'))
        self._textview = builder.get_object('textview')
        self._textview.modify_font(pango.FontDescription('Monospace'))
        self._textview.set_sensitive(False)
        self._textview.connect('size-allocate', self._scroll)
        self._at_bottom = None

        self._buffer = self._textview.get_buffer()
        text_color = self._textview.get_style().text[gtk.STATE_INSENSITIVE]
        self._buffer.create_tag('gray', foreground_gdk=text_color)
        self._buffer.create_tag('highlight', weight=700)
        self._buffer.create_tag('italicize', style=pango.STYLE_ITALIC)
        self._bold = pango.FontDescription()
        self._bold.set_weight(700)

        self._input = builder.get_object('input')
        self._input.connect('icon-press', self._send_text)
        self._input.connect('activate', self._send_text)
        self._input.connect('key-press-event', self._key_pressed)
        self._input.modify_font(pango.FontDescription('Monospace'))

        self._questioncheckbox = builder.get_object('questioncheckbox')

        self._init_hyperlinks()

    def do_event_connect(self, eventman, event):
        IrcWidget.do_event_connect(self, eventman, event)
        self._server = IrcBackend.Server.get_server('irc.freenode.net', event.nick, eventman)
        self._nick = event.nick
        channelname = Options.get('chatroom', event.chat)
        if len(channelname) == 0:
            return
        if channelname[0] not in '#&!+':
            channelname = '#' + channelname
        self._chatchan = self._server.get_channel(channelname)
        self._chan = self._chatchan   # Save for IRC widget use
        schedule = eventman.get_widget_by_name('schedule')
        self._get_question_token = schedule.get_question_token
#TRANSLATORS: Future versions will need translations of this word as plugins to match the locale of the target classroom session. The word will prefix questions asked in the chatroom of the instructor
        qt = _('QUESTION:')
        qt = self._get_question_token()
        self._questioncheckbox.set_label(qt)
#TRANSLATORS: %s will be a token from the locale of the target classroom session rather than the student's locale
        tooltip =  _('"%s" directs your question to the classroom for an answer from the instructor') % qt
        self._questioncheckbox.set_tooltip_text(tooltip)

        def joined(server):
            logging.debug('connected to chatroom')
            self._input.set_sensitive(True)
            self._questioncheckbox.set_sensitive(True)
            self._textview.set_sensitive(True)
        self.event_connect_signal(self._chatchan, 'joined', joined)
        self.event_connect_signal(self._chatchan, 'message-received', self._message_received)
        self.event_connect_signal(self._chatchan, 'message-sent', self._message_sent)
        def members_changed(chan, members):
            self.emit('members-changed', members)
        self.event_connect_signal(self._chatchan, 'members-changed', members_changed)

    def do_event_disconnect(self, eventman, event):
        self._input.set_sensitive(False)
        self._questioncheckbox.set_sensitive(False)
        self._textview.set_sensitive(False)
        istart, iend = self._buffer.get_bounds()
        self._buffer.delete(istart, iend)
        self._server.disconnect()
        self.event_disconnect_signals()

    def get_input_widget(self):
        return self._input

    def _key_pressed(self, widget, event):
        if (event.keyval == gtk.keysyms.Tab):
            self._try_autocomplete()
            return True
        else:
            return False

    def _try_autocomplete(self):
        text = self._input.get_text()
        pos = self._input.get_position()

        if pos == 0 or text[pos-1] == ' ':
            return

        if len(text) > pos and text[pos] == ' ':
            space = False
        else:
            space = True

        partial_nick = text[:pos].split(' ')[-1]

        members = self._chatchan.get_members()
        nicks = filter(lambda x: partial_nick in x[:len(partial_nick)], members)

        if len(nicks) == 1:
            completion = nicks[0][len(partial_nick):]

            completion += ':'
            if space:
                completion += ' '

        elif len(nicks) > 1:
            iend = self._buffer.get_end_iter()
            nicks.sort()
            self._buffer.insert_with_tags_by_name(iend, "\n" + ' '.join(nicks), 'gray')

            self._at_bottom = (self._adjust.value == self._adjust.upper -
                               self._adjust.page_size)

            # sort by length
            nicks.sort(lambda x,y: cmp(len(x), len(y)))

            completion = ''
            for i in range(len(partial_nick), len(nicks[0])):
                # filter nicknames with the same next character
                filtered_nicks = filter(lambda x: nicks[0][i] == x[i], nicks)
                if len(nicks) == len(filtered_nicks):
                    completion += nicks[0][i]
                else:
                    break
        else: # no match
            return

        self._input.insert_text(completion, pos)
        self._input.set_position(pos + len(completion))

    def _send_text(self, *args):
        text = self._input.get_text()
        if text == '':
            return
        if text.startswith('/'):
            self._append_to_buffer(_('IRC commands are not yet supported.'))
        elif self._questioncheckbox.get_active():
            self._questioncheckbox.set_active(False)
            self._chatchan.send_message(self._get_question_token() + u' ' + unicode(text))
        else:
            self._chatchan.send_message(text)
        self._input.set_text('')

    def _message_received(self, chan, sender, text, msgtype):
        self._append_to_buffer(text, sender, msgtype)

    def _message_sent(self, chan, text):
        self._adjust.value = self._adjust.upper - self._adjust.page_size
        self._append_to_buffer(text, chan._conn._acquired_nick)

    def _scroll(self, textview, alloc):
        if self._at_bottom is None:
            self._at_bottom = True
        if self._at_bottom:
            self._adjust.value = self._adjust.upper - self._adjust.page_size
