import utils
from utils.HIGDialog import HIGDialog

import gtk
import pango
import textwrap
import threading
import fcntl
import os
import errno


# attributes for rendering text
_ATTR_DEBUG =      {"foreground": "red",
                    "weight": pango.WEIGHT_BOLD,
                    "underline": pango.UNDERLINE_SINGLE}
_ATTR_DEPRECATED = {"foreground": "navy",
                    "weight": pango.WEIGHT_BOLD}
_ATTR_ERROR =      {"foreground": "red",
                    "weight": pango.WEIGHT_BOLD}
_ATTR_INFO =       {"foreground": "green"}
_ATTR_GTK =        {"foreground": "orange",
                    "weight": pango.WEIGHT_BOLD}
_ATTR_NORMAL =     { }


#
# Class for viewing log files.
#
class LogViewer(HIGDialog, threading.Thread):

    def __init__(self, logfile):

        threading.Thread.__init__(self, name = "LogViewer")

        self.__stop = threading.Event()
        self.__logfile = logfile

        HIGDialog.__init__(self, None, "", "", (gtk.STOCK_CLOSE,
                                                gtk.RESPONSE_CLOSE))
        self.set_property("title", _("Log Messages"))

        view = gtk.TextView()
        view.set_size_request(-1, 240)
        view.set_editable(False)
        self.__log = view.get_buffer()

        scrwin = gtk.ScrolledWindow()
        scrwin.set_policy(gtk.POLICY_NEVER, gtk.POLICY_AUTOMATIC)
        scrwin.add(view)

        align = gtk.Alignment(0.0, 0.0, 0.0, 0.0)
        align.set_property("border-width", 6)
        align.set_property("right-padding", 2)
        align.add(scrwin)

        self.vbox.pack_start(align, False, False, 0)
        self.show_all()

        def stop(*args):
            self.__halt()
            
        def destroy(*args):
            self.__halt()
            self.destroy()

        button = self.action_area.get_children()[-1]
        button.connect("clicked", destroy)
        self.connect("destroy", stop)


    def __del__(self):
        # ensure that the thread stops
        self.__halt()


    def __halt(self):
        self.__stop.set()
        self.join()


    def __append_log(self, text, attributes):

        if (attributes):
            tag = self.__log.create_tag(None, **attributes)
            self.__log.insert_with_tags(self.__log.get_end_iter(), text + "\n",
                                        tag)
        else:
            self.__log.insert(self.__log.get_end_iter(), text + "\n")


    def run(self):

        fdesc = open(self.__logfile)
        fcntl.fcntl(fdesc, fcntl.F_SETFL, os.O_NONBLOCK)

        while not self.__stop.isSet():

            try:
                while True:

                    if self.__stop.isSet():
                        break
                    
                    line = fdesc.readline()
                    if not line:
                        break

                    attr = self.__analyze_message(line)
                    for chunk in textwrap.wrap(line):
                        utils.run_in_main_thread(self.__append_log, chunk, attr)

            except IOError, exc:
                if exc.errno != errno.EAGAIN:
                    raise

            self.__stop.wait(0.5)

        fdesc.close()


    def __analyze_message(self, message):

        """
        Analyzes the given log message and returns the appropriate attribute.
        """

        if ("DeprecationWarning: " in message):
            return _ATTR_DEPRECATED
        elif ("Error: " in message):
            return _ATTR_ERROR
        elif ("Info: " in message):
            return _ATTR_INFO
        elif ("Debug: " in message):
            return _ATTR_DEBUG
        elif ("GtkWarning: " in message):
            return _ATTR_GTK
        else:
            return _ATTR_NORMAL

