#!/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 os
import tempfile
import gtk
import glib
import gobject
import ConfigParser
import urllib2
import io
import logging

from lernid import ConnectDialog
from lernid.PasswordDialog import PasswordDialog
from lernid.lernidconfig import save_cache_path
from lernid.lernidconfig import __lernid_data_directory__
from lernid.LernidPreferences import Preferences
from lernid.Event import Event
from lernid.LernidOptions import Options
from lernid.Statusbar import Statusbar
from lernid.IrcBackend import Server



_instance_object = None

class EventManager(gobject.GObject):

    __gtype_name__ = 'EventManager'

    __gsignals__ = {
        'event-connect': (
            gobject.SIGNAL_RUN_LAST, None, (gobject.TYPE_PYOBJECT,)
        ),
        'event-disconnect': (
            gobject.SIGNAL_RUN_LAST, None, (gobject.TYPE_PYOBJECT,)
        ),
        'event-interrupted': (
            gobject.SIGNAL_RUN_LAST, None, (gobject.TYPE_PYOBJECT,)
        ),
    }

    def __init__(self):
        gobject.GObject.__init__(self)
        self._cachefolder = save_cache_path('lernid')
        self._cachefolder_events = os.path.join(self._cachefolder, 'events')
        self._isconnected = False
        self._connectdialog = None
        self._passworddialog = None
        self._widgets = {}
        self._config = ConfigParser.ConfigParser()
        self._defaultconfig = u"""[#ubuntu-classroom -- In English] 
homepage: https://wiki.ubuntu.com/Classroom
classroom: ubuntu-classroom
chat: ubuntu-classroom-chat
icalurl: http://www.google.com/calendar/ical/canonical.com_qg6t4s8i7mg8d4lgfu9f93qid4@group.calendar.google.com/public/basic.ics

[#ubuntu-charlas -- En Español]
homepage: https://wiki.ubuntu.com/Classroom
classroom: ubuntu-charlas
Chat:ubuntu-charlas-chat
locale: es.ES
icalurl: http://www.google.com/calendar/ical/q16aejpuv5kgmoa7b6ridenkpk%40group.calendar.google.com/public/basic.ics
"""

# Make sure that these names are lower case
        self.classbotnames = ['classbot', 'classroombot', 'clasebot']
        if Options.get('config'):
            try:
                self._configtext = self._read_config()
            except IOError:
                Statusbar.push_message(_('Cannot retrieve configuration'))
                self._configtext = self._defaultconfig
            tf = tempfile.TemporaryFile()
            tf.write(self._configtext)
            tf.seek(0)
            self._config.readfp(tf)
            tf.close()
        else:
            if __lernid_data_directory__.startswith('/'):
                path = '/etc/lernid-classrooms.d'
            else:
                path = os.path.join(os.path.dirname(__file__),'../etc/lernid-classrooms.d')
            path = os.path.abspath(path)
            self._config.read([path+'/'+i for i in os.listdir(path)])
             
    @classmethod
    def get_instance(cls):
        global _instance_object
        if not _instance_object:
            _instance_object = cls()
        return _instance_object

    def _read_config(self):
        uri = Options.get('config')
        if uri.startswith('http://') or uri.startswith('https://'):
            return urllib2.urlopen(uri,None,30).read()
        else:
            try:
                return open(uri).read()
            except IOError:
                logging.critical("Unable to read configuration file "+uri)
                raise

    def _connect_event(self, event, nick):
        if self.is_connected():
            self.disconnect()
        if not self._config.has_option(event, 'eventstart'):
            eventstart = '2011-01-01 00:00:00'
        else:
            eventstart   = self._config.get(event, 'eventstart')
        if not self._config.has_option(event, 'eventend'):
            eventend = '2029-01-01 23:59:59'
        else:
            eventend   = self._config.get(event, 'eventend')
        try:
            homepage = self._config.get(event, 'homepage')
        except:
            homepage = "https://wiki.ubuntu.com/Classroom"
        try:
            icalurl = self._config.get(event, 'icalurl')
        except:
            icalurl = "http://www.google.com/calendar/ical/canonical.com_qg6t4s8i7mg8d4lgfu9f93qid4@group.calendar.google.com/public/basic.ics"
        if Options.get('calendar'):
            icalurl = Options.get('calendar')
        try:
            classroom = self._config.get(event, 'classroom')
            if classroom[0] not in '#&!+':
                classroom = '#' + classroom
        except:
            classroom = ""
        try:
            chat = self._config.get(event, 'chat')
            if chat[0] not in '#&!+':
                chat = '#' + chat
        except:
            chat = "#ubuntu-classroom-chat"
        try:
            logstring= self._config.get(event, 'logstring')
        except:
            logstring = None
        try:
            locale = self._config.get(event, 'locale')
        except:
            locale = None
        try:
            server = self._config.get(event, 'server')
        except:
            server = None
        try:
            question_token = self._config.get(event, 'question_token')
        except:
            question_token = None

        self._event = Event(
            name = event,
            nick = nick,
            homepage = homepage,
            icalurl = icalurl,
            classroom = classroom,
            chat = chat,
            eventstart=eventstart,
            eventend=eventend,
            locale = locale,
            question_token = question_token,
            logstring = logstring,
            server = server
        )
        logging.debug('connecting to event {0}'.format(event))
        Statusbar.push_message(_('Connecting to event'), duration=10)
        self._isconnected = True
        self.emit('event-connect', self._event)

    def _identify_nick(self, nick, password):
        server = Server.get_server('irc.freenode.net', nick, self)
        identifier = server.identify_nick(password)
        def update_statusbar(obj):
            Statusbar.push_message(_('Your nickname is now identified'), duration=15)
        identifier.connect('identified', update_statusbar)
        def retry(obj):
            if not self._passworddialog:
                self._passworddialog = PasswordDialog.new()
            password = self._passworddialog.run()
            if password != None:
                identifier.retry(password)
        identifier.connect('invalid-password', retry)


    def connect_dialog(self, widget=None, parent=None):
        """Show the connect dialog and connect to the resources."""
        if not self._connectdialog:
            self._connectdialog = ConnectDialog.NewConnectDialog()
            self._connectdialog.set_transient_for(parent)
            self._connectdialog.connect('response', self._connect_dialog_first_response)
            config_event = Preferences.get('event')
            if config_event:
                self._connectdialog.set_event(config_event[1:-1])
            self._connectdialog.set_nick(Preferences.get('nick'))
            self._connectdialog.set_transient_for(widget)
        self._connectdialog.show()

    def _connect_dialog_first_response(self, dialog, response):
        if response == gtk.RESPONSE_OK:
            self._connectdialog.hide()
            glib.idle_add(self._connect_dialog_response, dialog, response)

    def _connect_dialog_response(self, dialog, response):
        event = self._connectdialog.get_event()
        Preferences.set('event', '"%s"' % event)
        nick = self._connectdialog.get_nick()
        Preferences.set('nick', nick)
        self._connect_event(event, nick)
        password = self._connectdialog.get_password()
        if password:
            self._identify_nick(nick, password)

    def disconnect(self):
        if not self.is_connected():
            return
        self._isconnected = False
        Statusbar.push_message(_('Disconnecting from event'), duration=10)
        self.emit('event-disconnect', self._event)
        logging.debug('disconnecting')

    def current_event(self):
        return self._event

    def is_connected(self):
        return self._isconnected

    def get_available_events(self):
        return self._config.sections()

    def register_widget(self, widget):
        if widget.name in self._widgets:
            raise ValueError('a widget with that name is already registered')
        self._widgets[widget.name] = widget

    def get_widget_by_name(self, name):
        if name in self._widgets:
            return self._widgets[name]
        return None

