
import dbus.glib
import gobject
import sys

from account import read_account, connect

from telepathy.client.channel import Channel
from telepathy.constants import (
    CONNECTION_HANDLE_TYPE_CONTACT, CONNECTION_STATUS_CONNECTED,
    CHANNEL_TEXT_MESSAGE_TYPE_NORMAL)
from telepathy.interfaces import CHANNEL_TYPE_TEXT, CONN_INTERFACE

class TextChannel(Channel):
    def __init__(self, *stuff):
        Channel.__init__(self, *stuff)
        self.get_valid_interfaces().add(CHANNEL_TYPE_TEXT)

class Message:
    def __init__(self, conn, contact, message):
        self.conn = conn
        self.contact = contact
        self.message = message

        conn[CONN_INTERFACE].connect_to_signal('StatusChanged',
            self.status_changed_cb)
        conn[CONN_INTERFACE].connect_to_signal('NewChannel',
            self.new_channel_cb)

    def run(self):
        self.loop = gobject.MainLoop()
        self.loop.run()

    def quit(self):
        if self.loop:
            self.loop.quit()
            self.loop = None

    def status_changed_cb(self, state, reason):
        if state != CONNECTION_STATUS_CONNECTED:
            return

        handle = conn[CONN_INTERFACE].RequestHandle(
            CONNECTION_HANDLE_TYPE_CONTACT, self.contact)

        print 'got handle %d for %s' % (handle, self.contact)

        conn[CONN_INTERFACE].RequestChannel(
            CHANNEL_TYPE_TEXT, CONNECTION_HANDLE_TYPE_CONTACT, handle, True,
            reply_handler=lambda *stuff: None,
            error_handler=self.request_channel_error_cb)

    def request_channel_error_cb(self, exception):
        print 'error:', exception
        self.quit()

    def new_channel_cb(self, object_path, channel_type, handle_type, handle,
            suppress_handler):
        if channel_type != CHANNEL_TYPE_TEXT:
            return

        print 'got text channel'
        channel = TextChannel(
            self.conn._dbus_object._named_service, object_path)
        channel[CHANNEL_TYPE_TEXT].connect_to_signal('Sent', self.sent_cb)
        channel[CHANNEL_TYPE_TEXT].connect_to_signal('SendError',
            self.send_error_cb)
        channel[CHANNEL_TYPE_TEXT].Send(
            CHANNEL_TEXT_MESSAGE_TYPE_NORMAL, self.message)

    def sent_cb(self, timestamp, type, text):
        print 'message sent: %s' % text
        self.quit()

    def send_error_cb(self, error, timestamp, type, text):
        print 'error sending message: %d' % error

if __name__ == '__main__':
    if len(sys.argv) > 1:
        account_file = sys.argv[1]
    else:
        account_file = 'account'

    manager, protocol, account = read_account(account_file)
    conn = connect(manager, protocol, account)

    try:
        msg = Message(conn, 'dgh@jabber.org', 'hello')
        msg.run()
    except KeyboardInterrupt:
        print "killed"

    conn[CONN_INTERFACE].Disconnect()

