# -*- coding: utf-8 -*-

###########################################################################
#    Copyright (C) 2003-2005 by Wido Depping                                      
#    <widod@users.sourceforge.net>                                                             
#
# Copyright: See COPYING file that comes with this distribution
#
###########################################################################


from qt import *

import os
import os.path
from ConfigParser import *
import time

from base.gui.MainWinDesign import MainWinDesign
from base.gui.AboutDialog import AboutDialog
import environment
from base.gui.ServerDialog import ServerDialog
from base.backend.PluginLoader import PluginLoader
from base.gui.PluginLoaderGui import PluginLoaderGui
from base.gui.LanguageDialog import LanguageDialog
from base.utils.backend.LogObject import LogObject
from base.utils.gui.LoggerWidget import LoggerWidget
from base.gui.ImprovedServerDialog import ImprovedServerDialog

class MainWin(MainWinDesign):
    """The main window for Luma."""

    configFile = None

    def __init__(self, parent=None):
        MainWinDesign.__init__(self, parent)
        
        environment.updateUI = self.updateUI
        environment.setBusy = self.setBusy
        environment.reloadPlugins = self.reloadPlugins
        environment.displaySizeLimitWarning = self.displaySizeLimitWarning
        environment.logMessage = self.logMessage
        
        self.pluginItemList = []

        # create the progress bar for the status bar
        statusBar = self.statusBar()
        self.progressBar = QProgressBar(statusBar)
        self.progressBar.setMaximumWidth(150)
        self.progressBar.setTotalSteps(0)
        statusBar.addWidget(self.progressBar, 0, 1)
        
        # create button for logged errors
        self.logButton = QToolButton(None)
        iconPath = os.path.join(environment.lumaInstallationPrefix, "share", "luma", "icons")
        self.logButton.setPixmap(QPixmap(os.path.join(iconPath, "bomb.png")))
        self.connect(self.logButton, SIGNAL("clicked()"), self.showLoggerWindow)
        self.logButtonActivated = False
        
        # Build the plugin toolbar
        #self.pluginToolBar = QToolBar(self, "PLUGINTOOLBAR")
        #self.toolBarLabel = QLabel("Plugin:", self.pluginToolBar)
        #self.pluginBox = QComboBox(self.pluginToolBar)
        #self.connect(self.pluginBox, SIGNAL("activated(const QString &)"), self.pluginSelectionChanged)
        self.pluginToolBar = QToolBar(self, "PLUGINTOOLBAR")
        self.pluginLabel = QLabel(self.pluginToolBar)
        self.pluginLabel.setAlignment(Qt.AlignLeft | Qt.SingleLine | Qt.AlignVCenter)
        self.pluginLabel.setText(self.trUtf8("Pluginname   "))
        font = QFont()
        font.setBold(True)
        self.pluginLabel.setFont(font)
        self.pluginLabel.setSizePolicy(QSizePolicy(QSizePolicy.MinimumExpanding,QSizePolicy.Preferred))
        self.pluginButton = QPushButton(self.pluginToolBar)
        self.pluginButton.setText(self.trUtf8("Choose plugin"))
        self.pluginButton.installEventFilter(self)
        self.pluginButtonClicked = False
        self.connect(self.pluginButton, SIGNAL("clicked()"), self.showPluginSelection)
        self.timerRunning = False
        
        self.pluginBox = QListBox(None)
        font = self.pluginBox.font()
        font.setPointSize(font.pointSize() + 4)
        self.pluginBox.setFont(font)
        self.connect(self.pluginBox, SIGNAL("clicked(QListBoxItem*)"), self.pluginClicked)
        
        self.pluginBoxId = self.taskStack.addWidget(self.pluginBox, -1)

        self.loggerDockWindow = QDockWindow(QDockWindow.InDock, self)
        self.loggerDockWindow.setResizeEnabled(True)
        self.loggerDockWindow.setOrientation(Qt.Horizontal)
        self.loggerDockWindow.setCloseMode(3)
        self.moveDockWindow(self.loggerDockWindow, Qt.DockMinimized)
        self.connect(self.loggerDockWindow,SIGNAL("visibilityChanged(bool)"),self.loggerVisibilitChanged)
        
        self.loggerWidget = LoggerWidget(self.loggerDockWindow)
        self.loggerDockWindow.setWidget(self.loggerWidget)
        
        self.configFile = os.path.join(environment.userHomeDir,  ".luma", "luma")
        
        # Try to read the chosen language. If this fails, fallback to native,
        # which is english.
        # Additionally restore window size.
        trFile = 'NATIVE'
        try:
            configParser = ConfigParser()
            configParser.readfp(open(self.configFile, 'r'))
            
            if configParser.has_section("Defaults"):
                width = None
                height = None
                
                if configParser.has_option("Defaults", "width"):
                    width = configParser.getint("Defaults", "width")
                    
                if configParser.has_option("Defaults", "height"):
                    height = configParser.getint("Defaults", "height")
                    
                if (not (width == None)) and (not (height == None)):
                    self.resize(width, height)
                
                if configParser.has_option("Defaults", "language"):
                    trFile = configParser.get("Defaults", "language")
        except IOError, e:
            tmpString = "Could not read config file. Reason:\n"
            tmpString += str(e)
            environment.logMessage(LogObject("Debug", tmpString))
        
        # Install translator.
        qApp.translator = QTranslator(None)
        if not (trFile == 'NATIVE'):
            qApp.translator.load(trFile)
            qApp.installTranslator(qApp.translator)
            self.languageChanges()
        

        self.PLUGINS = {}
        self.ICONPREFIX = os.path.join(environment.lumaInstallationPrefix, "share", "luma", "icons")
        self.applicationIcon = QPixmap(os.path.join(self.ICONPREFIX, "luma-32.png"))
        self.setIcon(self.applicationIcon)
        
        self.showPluginSelection()
        

###############################################################################

    def showAboutLuma(self):
        """Shows the about dialog of Luma."""
        
        a = AboutDialog(self)
        a.show()

###############################################################################

    def quitApplication(self):
        """Quits Luma.
        
        Before that, all plugins are unloaded. This way all plugins have the 
        possibility for a cleanup.
        """
        self.unloadPlugins()
        self.savePosition()
        qApp.quit()

###############################################################################

    def showServerEditor(self):
        """Show the dialog for editing the accessible servers."""
        
        #dialog = ServerDialog()
        dialog = ImprovedServerDialog()
        dialog.exec_loop()
        if (dialog.result() == QDialog.Accepted) or dialog.SAVED:
            currentPlugin = self.pluginBox.currentText()
            self.reloadPlugins()
            #self.pluginBox.setCurrentText(currentPlugin)
            #self.pluginSelectionChanged(currentPlugin)

###############################################################################

    def loadPlugins(self, splash=None):
        """ Load all wanted plugins."""
        
        if not (None == splash):
            splash.message("Loading plugins...", Qt.AlignLeft + Qt.AlignBottom, Qt.white)
        
        pluginObject = PluginLoader(self.checkToLoad())
        self.PLUGINS = pluginObject.PLUGINS
        
        self.pluginBox.clear()
        
        pluginNameList = []
        for x in self.PLUGINS.keys():
            tmpObject = self.PLUGINS[x]
            if tmpObject['load'] == True:
                if not (None == splash):
                    tmpMessage = "Loading plugin " + unicode(self.trUtf8(self.PLUGINS[x]['pluginUserString']))
                    splash.message(tmpMessage, Qt.AlignLeft + Qt.AlignBottom, Qt.white)

                pluginNameList.append(self.PLUGINS[x]['pluginName'])
                reference = tmpObject["getPluginWidget"]
                widgetTmp = reference(self.taskStack)
                tmpObject["WIDGET_REF"] = widgetTmp
                tmpObject["WIDGET_ID"] = self.taskStack.addWidget(widgetTmp, -1)
                
        pluginNameList.sort()
        #map(self.pluginBox.insertItem, pluginNameList)
                
        #pluginName = str(self.pluginBox.currentText())
        #if self.PLUGINS.has_key(pluginName):
        #    self.taskStack.raiseWidget(self.PLUGINS[pluginName]["WIDGET_ID"])
        #    try:
        #        self.PLUGINS[pluginName]["WIDGET_REF"].buildToolBar(self)
        #    except AttributeError, e:
        #        pass
        #    
        
        for x in pluginNameList:
            name = self.trUtf8(self.PLUGINS[x]["pluginUserString"])
            icon = self.PLUGINS[x]["icon"]
            item = QListBoxPixmap(icon, QString(name))
            self.pluginBox.insertItem(item)
            
            item.widgetID = self.PLUGINS[x]["WIDGET_ID"]
            item.widgetRef = self.PLUGINS[x]["WIDGET_REF"]
            item.name = name
            self.pluginItemList.append(item)
            
            
        if not (None == splash):
            splash.message("Finished.", Qt.AlignLeft + Qt.AlignBottom, Qt.white)
            
        #self.taskStack.raiseWidget()
            

###############################################################################

    def unloadPlugins(self):
        """ Tries to unload all plugins.
        
        All children of the widget stack and icon view are deleted, 
        also alle references to them.
        """
        
        for x in self.PLUGINS.keys():
            tmpObject = self.PLUGINS[x]
            
            if tmpObject['load']:
                widgetRef = tmpObject["WIDGET_REF"]
                #tmpObject["PLUGIN_CODE"].postprocess()
                
                # We use deleteLater() because of a bug in QT. 
                widgetRef.deleteLater()
                
        self.PLUGINS = {}

###############################################################################

    def configurePlugins(self):
        """Show the dialog for configuring the plugins.
        """
        
        dialog = PluginLoaderGui(PluginLoader('ALL').PLUGINS, self)
        dialog.exec_loop()

###############################################################################

    def checkToLoad(self):
        """Return a list of plugin names to load.
        
        The plugins configuration file is opened and the list of plugins to 
        load is read.
        """
        
        defaultsHome = os.path.join(environment.userHomeDir, ".luma", "plugins")
        pluginList = []
        try:
            configParser = ConfigParser()
            configParser.readfp(open(defaultsHome, 'r'))
            for x in configParser.sections():
                if not configParser.has_option(x, "load"):
                    continue
                if configParser.getint(x, "load") == 1:
                    pluginList.append(x)
        except Exception, errorData:
            errorString = "Could not open file for plugin defaults.\n"
            errorString += "Reason: " + str(errorData)
            environment.logMessage(LogObject("Debug", errorString))
            pluginList = "ALL"

        return pluginList

###############################################################################

    def reloadPlugins(self):
        """Unload plugins and reload them afterwards.
        """
        
        self.unloadPlugins()
        
        self.pluginItemList = []
        
        toolBars = self.toolBars(Qt.DockTop)
        
        for x in toolBars:
            if not (str(x.name()) == "PLUGINTOOLBAR"):
                x.deleteLater()
        
        self.loadPlugins()
        
        self.showPluginSelection()
        translatedNamed = unicode(self.trUtf8("Pluginname")) + "   "
        self.pluginLabel.setText(translatedNamed)

###############################################################################

    def updateUI(self):
        """ Updates the progress bar of the GUI and keeps it responsive.
        """
        
        qApp.processEvents()
        progress = self.progressBar.progress()
        self.progressBar.setProgress(progress + 1)
            

###############################################################################

    def setBusy(self, busy=True):
        """ Set the X mouse cursor busy. 
        
        Better for user feedback.
        """
        
        if busy:
            # set cursor busy
            cursor = QCursor()
            cursor.setShape(Qt.WaitCursor)
            qApp.setOverrideCursor(cursor)
        else:
            qApp.restoreOverrideCursor()
            self.progressBar.setProgress(0)

###############################################################################

    def showLanguageDialog(self):
        """ Show the language dialog and install the chosen language.
        
        Afterwards all plugins are reloaded, otherwise the language changes 
        would have no effect.
        """
        
        configParser = ConfigParser()
            
        try:
            configParser.readfp(open(self.configFile, 'r'))
        except Exception, errorData:
            tmpString = "Could not read language settings file. Reason:\n"
            tmpString += str(errorData)
            environment.logMessage(LogObject("Debug", tmpString))
            
        if not(configParser.has_section("Defaults")):
            configParser.add_section("Defaults")
            
        language = "NATIVE"
        
        if configParser.has_option("Defaults", "language"):
            language = configParser.get("Defaults", "language")
            
        language = os.path.split(language)[-1]
        
        dialog = LanguageDialog()
        dialog.setCurrentLanguage(language)
        dialog.exec_loop()
        
        if dialog.result() == QDialog.Accepted:
            trFile = dialog.getLanguageFile()
            if trFile == 'NATIVE':
                qApp.removeTranslator(qApp.translator)
            else:
                qApp.translator.load(trFile)
                qApp.installTranslator(qApp.translator)
               
            self.languageChanges()
                
            configParser.set("Defaults", "language", trFile)
            
            try:
                configParser.write(open(self.configFile, 'w'))
            except Exception, errorData:
                tmpString = "Could not save language settings file. Reason:\n"
                tmpString += str(errorData)
                environment.logMessage(LogObject("Error", tmpString))
                
            self.reloadPlugins()

###############################################################################

    def displaySizeLimitWarning(self):
        statusBar = self.statusBar()
        statusBar.message("Search request reached server side size limit!", 10000)
        
        
###############################################################################

    def savePosition(self):
        width = self.width()
        height = self.height()
        
        configParser = ConfigParser()
            
        try:
            configParser.readfp(open(self.configFile, 'r'))
        except Exception, errorData:
            tmpString = "Could not read settings file. Reason:\n"
            tmpString += str(errorData)
            environment.logMessage(LogObject("Debug", tmpString))
            
        if not(configParser.has_section("Defaults")):
            configParser.add_section("Defaults")
            
        configParser.set("Defaults", "width", width)
        configParser.set("Defaults", "height", height)
        
        try:
            configParser.write(open(self.configFile, 'w'))
        except Exception, errorData:
            tmpString = "Could not save window settings. Reason:\n"
            tmpString += str(errorData)
            environment.logMessage(LogObject("Error", tmpString))

###############################################################################


    def showLoggerWindow(self):
        statusBar = self.statusBar()
        statusBar.removeWidget(self.logButton)
        self.logButton = None
        self.logButtonActivated = False
        
        self.moveDockWindow(self.loggerDockWindow, Qt.DockBottom)
        self.loggerWidget.displayMessages()
        
###############################################################################

    def loggerVisibilitChanged(self, visible):
        if not visible:
            self.moveDockWindow(self.loggerDockWindow, Qt.DockMinimized)
            
###############################################################################

    def logMessage(self, messageObject):
        if isinstance(messageObject, LogObject):
            self.loggerWidget.newMessage(messageObject)
               
            if "Error" == messageObject.getLogType():
                if not self.logButtonActivated:
                    self.logButton = QToolButton(None)
                    self.logButton.setAutoRaise(True)
                    iconPath = os.path.join(environment.lumaInstallationPrefix, "share", "luma", "icons")
                    self.logButton.setPixmap(QPixmap(os.path.join(iconPath, "bomb.png")))
                    self.connect(self.logButton, SIGNAL("clicked()"), self.showLoggerWindow)
                    statusBar = self.statusBar()
                    statusBar.addWidget(self.logButton, 0, 1)
                    self.logButtonActivated = True
        else:
            pass

###############################################################################

    def eventFilter(self, object, event):
        if (event.type() == QEvent.Enter):
            if object == self.pluginButton:
                if not self.timerRunning:
                    self.pluginButtonClicked = False
                    QTimer.singleShot( 500, self.checkCursorPosition)
                
        return 0
                
###############################################################################

    def checkCursorPosition(self):
        self.timerRunning = False
        if self.pluginButtonClicked:
            return
            
	# Annoying behavior.. disabled # bgrotan
        #if self.pluginButton.hasMouse():
        #    self.showPluginSelection()
            
###############################################################################

    def showPluginSelection(self):
        self.pluginButtonClicked = True
        self.taskStack.raiseWidget(self.pluginBoxId)
        
###############################################################################
    
    def pluginClicked(self, item):
        if item == None:
            return
            
        self.taskStack.raiseWidget(item.widgetID)
        self.pluginLabel.setText(unicode(item.text()) + "   ")
        
        toolBars = self.toolBars(Qt.DockTop)
        
        for x in toolBars:
            if not (str(x.name()) == "PLUGINTOOLBAR"):
                x.deleteLater()
        
        #build the toolbar for the selected plugin
        try:
            item.widgetRef.buildToolBar(self)
        except AttributeError, e:
            pass
            
            
###############################################################################

    def __tr(self,s,c = None):
        return qApp.translate("MainWin",s,c)
        
###############################################################################

    def languageChanges(self):
        self.languageChange()
        self.pluginButton.setText(self.trUtf8("Choose plugin"))
        
        #for x in self.pluginItemList:
        #    x.setText(qApp.translate(str(x.name))
        #    print "foo"
        
        
        
        
        
        
        
