# Copyright (C) 2009  Red Hat, Inc.
# All rights reserved.
#
# 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 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/>.
#
# Author(s): Chris Lumens <clumens@redhat.com>
#
from meh import MAIN_RESPONSE_DEBUG, MAIN_RESPONSE_NONE, MAIN_RESPONSE_QUIT, MAIN_RESPONSE_SAVE
from meh.ui import AbstractIntf, AbstractSaveExceptionWindow, AbstractMainExceptionWindow, AbstractMessageWindow
import os
import sys
import report

import gi
gi.require_version("Gtk", "3.0")

from gi.repository import Gtk

import gettext
_ = lambda x: gettext.translation("python-meh", fallback=True).gettext(x) if x != "" else ""

def find_glade_file(file):
    path = os.environ.get("GLADEPATH", "./:ui/:/tmp/updates/:/tmp/updates/ui/:/usr/share/python-meh/")
    for d in path.split(":"):
        fn = d + file
        if os.access(fn, os.R_OK):
            return fn
    raise RuntimeError("Unable to find glade file %s" % file)

class GraphicalIntf(AbstractIntf):
    def __init__(self, *args, **kwargs):
        AbstractIntf.__init__(self, *args, **kwargs)

    def enableNetwork(self, *args, **kwargs):
        """Should be provided by the inheriting class."""

        return False

    def exitWindow(self, title, message, *args, **kwargs):
        win = ExitWindow(title, message, *args, **kwargs)
        win.run()
        win.destroy()

    def mainExceptionWindow(self, text, exnFile, *args, **kwargs):
        win = MainExceptionWindow(text, exnFile, *args, **kwargs)
        return win

    def messageWindow(self, title, message, *args, **kwargs):
        win = MessageWindow(title, message, *args, **kwargs)
        win.run()
        win.destroy()

    def saveExceptionWindow(self, signature, *args, **kwargs):
        win = SaveExceptionWindow(signature)
        win.run()

class SaveExceptionWindow(AbstractSaveExceptionWindow):
    def __init__(self, signature, *args, **kwargs):
        AbstractSaveExceptionWindow.__init__(self, signature, *args, **kwargs)
        self.signature = signature

    def run(self, *args, **kwargs):
        # Don't need to check the return value of report since it will
        # handle all the UI reporting for us.
        report.report_problem_in_memory(self.signature, report.LIBREPORT_WAIT)

class MainExceptionWindow(AbstractMainExceptionWindow):
    def __init__(self, shortTraceback=None, longTraceback=None, *args, **kwargs):
        AbstractMainExceptionWindow.__init__(self, shortTraceback, longTraceback,
                                             *args, **kwargs)

        builder = Gtk.Builder()
        builder.set_translation_domain("python-meh")
        glade_file = find_glade_file("exception-dialog.glade")
        builder.add_from_file(glade_file)
        builder.connect_signals(self)

        self._main_window = builder.get_object("exceptionWindow")

        # this makes sure the Meh window remains active
        # even if the exception has been triggered in a dialog
        window_group = Gtk.WindowGroup()
        window_group.add_window(self._main_window)

        self._traceback_buffer = builder.get_object("tracebackBuffer")

        self._traceback_buffer.set_text(longTraceback)
        self._response = MAIN_RESPONSE_QUIT

        self._debug_button = builder.get_object("debugButton")

        allowDebug = kwargs.get("allowDebug", sys.stdout.isatty)

        if allowDebug and not allowDebug():
            self._debug_button.set_sensitive(False)

    @property
    def main_window(self):
        return self._main_window

    def destroy(self, *args, **kwargs):
        self._main_window.destroy()

    def run(self, *args, **kwargs):
        self._main_window.show_all()
        # keep our window above dialogs
        self._main_window.set_modal(True)
        self._main_window.set_keep_above(True)
        Gtk.main()
        self.destroy()
        return self._response

    def on_report_clicked(self, button):
        # hide our window to not interfere with libreport window
        self._main_window.hide()
        self._response = MAIN_RESPONSE_SAVE
        Gtk.main_quit()

    def on_quit_clicked(self, button):
        self._response = MAIN_RESPONSE_QUIT
        Gtk.main_quit()

    def on_debug_clicked(self, button):
        self._response = MAIN_RESPONSE_DEBUG
        Gtk.main_quit()

    def on_expander_activated(self, expander, *args):
        if not expander.get_expanded():
            self._main_window.resize(600, 400)
        else:
            #resize the window back to the default size when expander is
            #minimized
            self._main_window.resize(600, 1)

    def on_main_window_deleted(self, *args):
        self._response = MAIN_RESPONSE_NONE
        self.destroy()
        Gtk.main_quit()

class MessageWindow(AbstractMessageWindow):
    def __init__(self, title, text, *args, **kwargs):
        AbstractMessageWindow.__init__(self, title, text, *args, **kwargs)
        self.rc = 0

        self.dialog = Gtk.MessageDialog(buttons=Gtk.ButtonsType.OK,
                                        type=Gtk.MessageType.INFO,
                                        message_format=text)
        self.dialog.set_title(title)
        self.dialog.set_position(Gtk.WindowPosition.CENTER)

    def destroy(self, *args, **kwargs):
        self.dialog.destroy()

    def run(self, *args, **kwargs):
        self.dialog.show_all()
        self.rc = self.dialog.run()
        self.dialog.destroy()

class ExitWindow(MessageWindow):
    def __init__(self, title, text, *args, **kwargs):    # pylint: disable=super-init-not-called
        self.dialog = Gtk.MessageDialog(buttons=Gtk.ButtonsType.NONE,
                                        type=Gtk.MessageType.INFO,
                                        message_format=text)
        self.dialog.set_title(title)
        self.dialog.add_button(_("_Exit"), 0)
        self.dialog.set_position(Gtk.WindowPosition.CENTER)
