# -*- coding: utf-8 -*-
#
# Author: Ingelrest François (Athropos@gmail.com)
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
# 
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# GNU Library General Public License for more details.
# 
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301 USA

import consts, gtk, prefsManager, signal, sys, os, vte

from gettext import gettext as _

#==========================================================
#
# Functions
#
#==========================================================

def createDlg(parent) :
    """
        Load the dialog description from the disk, and configure it
    """
    global dlg, wTree
    # Set the handler for the VTE, and then create the dialog
    gtk.glade.set_custom_handler(lambda glade, function, widget, str1, str2, int1, int2 : vte.Terminal())
    wTree = gtk.glade.XML(os.path.join(consts.dirRes, 'dlg-output.glade'), domain=consts.appNameShort)
    dlg   = wTree.get_widget('dlg-output')
    # Configure the dialog
    dlg.set_modal(True)
    dlg.set_transient_for(parent)
    dlg.resize(prefsManager.get('outputDlgWidth'), prefsManager.get('outputDlgHeight'))
    # Connect signal handlers: autoconnect is not used, because we would have to use globals(), which may contain duplicated functions
    wTree.signal_connect('onResponse',  onResponse)
    wTree.signal_connect('onDlgDelete', onDlgDelete)
    wTree.signal_connect('onDlgResize', onDlgResize)
    wTree.signal_connect('onBtnPause',  onBtnPause)
    wTree.signal_connect('onBtnStop',   lambda widget : os.kill(processPID, signal.SIGKILL))
    # Configure the (scrollable) VTE
    wTree.get_widget('vteOutput').show_all()
    wTree.get_widget('vteOutput').connect('child-exited', onVTEChildExited)
    wTree.get_widget('scrVTE').get_vscrollbar().set_adjustment(wTree.get_widget('vteOutput').get_adjustment())


def show(parent, cmd, args) :
    """
        Display this dialog and immediately launch cmd
    """
    global processPID, processPaused

    if dlg is None :
        createDlg(parent)

    wTree.get_widget('btnClose').set_sensitive(False)
    wTree.get_widget('btnStop').set_sensitive(True)
    wTree.get_widget('btnPause').set_sensitive(True)
    wTree.get_widget('vteOutput').reset(True, True)
    wTree.get_widget('btnPause').set_label(_('Pause'))
    wTree.get_widget('btnPause').set_image(gtk.image_new_from_stock(gtk.STOCK_MEDIA_PAUSE, gtk.ICON_SIZE_BUTTON))

    processPaused = False
    processPID    = wTree.get_widget('vteOutput').fork_command(cmd, args)

    dlg.show()


def run(cmd, args) :
    """
        Launch this dialog box as a stand alone application
        This means that gtk.main_quit() will be called when this dialog box will exit
    """
    global standAlone

    standAlone = True
    show(None, cmd, args)
    gtk.main()

#==========================================================
#
# Events handlers
#
#==========================================================

def onVTEChildExited(terminal) :
    """
        The process has exited
    """
    global processPID

    processPID = -1
    wTree.get_widget('btnClose').set_sensitive(True)
    wTree.get_widget('btnStop').set_sensitive(False)
    wTree.get_widget('btnPause').set_sensitive(False)


def onDlgResize(dialog, rectangle) :
    """
        The dialog has been resized, so we save its new size
    """
    prefsManager.set('outputDlgWidth',  rectangle.width)
    prefsManager.set('outputDlgHeight', rectangle.height)


def onDlgDelete(dialog, event) :
    """
        Called when the user clicks on the title bar close button
    """
    if processPID == -1 :
        if standAlone :
            gtk.main_quit()
        else :
            dlg.hide()
    # We don't allow the dialog to be destroyed, that's what returning True is useful for
    return True


def onResponse(dialog, response, *args) :
    """
        Response events
    """
    if response == gtk.RESPONSE_CLOSE :
        if standAlone :
            gtk.main_quit()
        else :
            dlg.hide()


def onBtnPause(widget) :
    """
        Pause or resume the process, if any
    """
    global processPaused

    if processPaused :
        processPaused = False
        os.kill(processPID, signal.SIGCONT)
        wTree.get_widget('btnPause').set_label(_('Pause'))
        wTree.get_widget('btnPause').set_image(gtk.image_new_from_stock(gtk.STOCK_MEDIA_PAUSE, gtk.ICON_SIZE_BUTTON))
    else :
        processPaused = True
        os.kill(processPID, signal.SIGSTOP)
        wTree.get_widget('btnPause').set_label(_('Resume'))
        wTree.get_widget('btnPause').set_image(gtk.image_new_from_stock(gtk.STOCK_MEDIA_PLAY, gtk.ICON_SIZE_BUTTON))


#==========================================================
#
# Entry point
#
#==========================================================

dlg           = None
processPID    = -1
standAlone    = False
processPaused = False
