#!/usr/bin/python
#
# Author: ncmprhnsbl
#
# This gtkdialog script opens a window with some options to obtain and update various applications
# for Porteus Linux, it is a gui for  update-*-live scripts

import gi
gi.require_version('Gtk', '3.0')
gi.require_version('Vte', '2.91')
from gi.repository import Gtk, Vte, GLib
from os import getenv, getuid, path, environ
from subprocess import run, Popen
from platform import machine

## Make sure we're in X
display = getenv('DISPLAY')
if display == None:
    print("This program requires an X session!")
    quit()

## prompt root password(gui psu) and re-execute? probly a bit dirty..
## using subprocess rather than os.system() to be script agnostic..
user = getuid()
if user != 0:
    print("You must be root to run this!")
    this_script = path.abspath(__file__)
    run(['psu', this_script])
    quit()

class GtkBrowserUpdate(Gtk.Window):
    def __init__(self):
        Gtk.Window.__init__(self, title = "Porteus Module Centre", border_width = 5, default_height = 480, default_width = 650, icon_name = "cdr")
        self.vb = Gtk.Box(spacing = 5, orientation = Gtk.Orientation.VERTICAL)

        self.l_header_txt = Gtk.Label()
        self.l_header_txt.set_markup("<span size=\"x-large\" weight=\"bold\">Choose a Module to Install or to Update</span>")
        self.vb.pack_start(self.l_header_txt, False, False, 5)

        self.vb.pack_start(Gtk.Separator(), False, False, 5)

        self.scrolledwindow = Gtk.ScrolledWindow(hexpand = True, vexpand = True)
        self.vb.pack_start(self.scrolledwindow, True, True, 5)

        self.vb_inner = Gtk.Box(spacing = 5, orientation = Gtk.Orientation.VERTICAL)

        self.vb_inner_br = Gtk.Box(spacing = 5, orientation = Gtk.Orientation.VERTICAL)
        self.br_txt = Gtk.Label()
        self.br_txt.set_markup("<span size=\"large\" weight=\"bold\">\tNetwork:</span>")
        self.br_txt.set_halign(Gtk.Align.START)
        self.vb_inner_br.pack_start(self.br_txt, False, False, 5)
        self.fb_br = Gtk.FlowBox(max_children_per_line = 5, row_spacing = 25, homogeneous = True)
        self.add_button("Firefox", "Mozilla's web browser", "firefox", self.fb_br)
        if machine() == "x86_64":
            self.add_button("Chrome", "Google's web browser", "chrome", self.fb_br)
            self.add_button("Palemoon", "Lightweight web browser based on older Firefox", "palemoon", self.fb_br)
            self.add_button("Opera", "Chromium based web browser", "opera", self.fb_br)
            self.add_button("Chromium-gost", "Chromium based web browser for Russian banking", "chromium-gost", self.fb_br)
            self.add_button("Vivaldi", "Chromium based web browser", "vivaldi", self.fb_br)
            self.add_button("Telegram", "Desktop Messaging Client", "telegram", self.fb_br)
            self.add_button("Max", "Desktop Messaging Client", "max", self.fb_br)
            self.add_button("AnyDesk", "Remote Desktop Access", "anydesk", self.fb_br)
            self.add_button("Assistant", "Remote Desktop Access", "assistant", self.fb_br)
            self.add_button("RustDesk", "Remote Desktop Access", "rustdesk", self.fb_br)
            self.add_button("Remmina", "Remote Desktop Access", "remmina", self.fb_br)
        self.add_button("Chromium", "The open source web browser with google elements removed", "chromium", self.fb_br)        
        self.add_button("Netsurf", "Very lightweight Web Browser", "netsurf", self.fb_br)
        self.add_button("Yt-dlp", "(Console)Download Videos from the Web", "yt-dlp", self.fb_br)
        self.vb_inner_br.pack_start(self.fb_br, False, False, 5)

        self.vb_inner_grph = Gtk.Box(spacing = 5, orientation = Gtk.Orientation.VERTICAL)
        self.l_grph_txt = Gtk.Label()
        self.l_grph_txt.set_markup("<span size=\"large\" weight=\"bold\">\tGraphics:</span>")
        self.l_grph_txt.set_halign(Gtk.Align.START)
        self.vb_inner_grph.pack_start(self.l_grph_txt, False, False, 5)
        self.fb_grph = Gtk.FlowBox(max_children_per_line = 5, row_spacing = 25, homogeneous = True)
        self.add_button("Gimp", "Gnu Image Manipulation Program", "gimp", self.fb_grph)
        
        self.vb_inner_grph.pack_start(self.fb_grph, False, False, 5)
        
        self.vb_inner_offce = Gtk.Box(spacing = 5, orientation = Gtk.Orientation.VERTICAL)
        self.l_offce_txt = Gtk.Label()
        self.l_offce_txt.set_markup("<span size=\"large\" weight=\"bold\">\tOffice:</span>")
        self.l_offce_txt.set_halign(Gtk.Align.START)
        self.vb_inner_offce.pack_start(self.l_offce_txt, False, False, 5)
        self.fb_offce = Gtk.FlowBox(max_children_per_line = 5, row_spacing = 25, homogeneous = True)
        if machine() == "x86_64":
            self.add_button("Libre Office", "Office Suite", "libreoffice", self.fb_offce)
            self.add_button("OnlyOffice", "Office Suite", "onlyoffice", self.fb_offce)
        self.add_button("WPS Office", "Office Suite", "wps-office", self.fb_offce)
        self.add_button("Printing", "Printing Tools", "printing", self.fb_offce)
        self.add_button("Printing Extra", "Printing Tools", "printing", self.fb_offce)
        self.add_button("Thunderbird", "Mozilla's email client", "thunderbird", self.fb_offce)
        self.vb_inner_offce.pack_start(self.fb_offce, False, False, 5)
        
        if machine() == "x86_64":
            self.vb_inner_virt = Gtk.Box(spacing = 5, orientation = Gtk.Orientation.VERTICAL)
            self.l_virt_txt = Gtk.Label()
            self.l_virt_txt.set_markup("<span size=\"large\" weight=\"bold\">\tVirtual Machine:</span>")
            self.l_virt_txt.set_halign(Gtk.Align.START)
            self.vb_inner_virt.pack_start(self.l_virt_txt, False, False, 5)
            self.fb_virt = Gtk.FlowBox(max_children_per_line = 5, row_spacing = 25, homogeneous = True)
            self.add_button("VirtualBox", "Virtual Computer", "vbox", self.fb_virt)
            self.vb_inner_virt.pack_start(self.fb_virt, False, False, 5)

        self.vb_inner.pack_start(self.vb_inner_br, True, True, 5)
        self.vb_inner.pack_start(self.vb_inner_grph, True, True, 5)
        self.vb_inner.pack_start(self.vb_inner_offce, True, True, 5)
        if machine() == "x86_64":
            self.vb_inner.pack_start(self.vb_inner_virt, True, True, 5)

        self.scrolledwindow.add(self.vb_inner)

        self.vb.pack_start(Gtk.Separator(), False, False, 10)

        self.hb_bottom = Gtk.Box(spacing = 5, homogeneous = False)

        self.cancel_button = Gtk.Button.new_with_label("Close")
        self.cancel_button.connect("clicked", self.on_cancel_clicked)
        self.hb_bottom.pack_end(self.cancel_button, False, False, 2)

        lynx_img = Gtk.Image.new_from_icon_name("browser", Gtk.IconSize.BUTTON)
        help_img = Gtk.Image.new_from_icon_name("help-about", Gtk.IconSize.BUTTON)
        file_img = Gtk.Image.new_from_icon_name("cdr", Gtk.IconSize.BUTTON)

        self.lynx_button = Gtk.Button.new_with_label("Run Lynx")
        self.lynx_button.set_image(lynx_img)
        self.lynx_button.set_always_show_image(True)
        self.lynx_button.connect("clicked", self.on_lynx_clicked)
        self.hb_bottom.pack_end(self.lynx_button, False, False, 2)

        self.help_button = Gtk.Button.new_with_label("Help")
        self.help_button.set_image(help_img)
        self.help_button.set_always_show_image(True)
        self.help_button.connect("clicked", self.on_help_clicked)
        self.hb_bottom.pack_end(self.help_button, False, False, 2)

        self.file_button = Gtk.Button.new_with_label("File")
        self.file_button.set_image(file_img)
        self.file_button.set_always_show_image(True)
        self.file_button.connect("clicked", self.on_file_clicked)
        self.hb_bottom.pack_end(self.file_button, False, False, 2)

        self.vb.pack_start(self.hb_bottom, False, False, 5)

        self.add(self.vb)
        self.help_button.grab_focus()

    def add_button(self, button_text, tooltip, option, fb):
        button = Gtk.Button.new_with_label(button_text)
        button.set_tooltip_text(tooltip)
        button.set_relief(Gtk.ReliefStyle.NONE)
        Gtk.Widget.set_focus_on_click(button, False)
        button.connect("clicked", self.on_button_clicked, button_text, option)
        fb.add(button)

    def on_button_clicked(self, button, *data):
        gterm = GtkTerminal(self, "Updating " + data[0], data[1])
        gterm.run()
        gterm.destroy()

    def on_cancel_clicked(self, button):
        Gtk.main_quit()

    def on_lynx_clicked(self, button):
        Popen(['su', '--login', environ["USER"], 'vterm', '/usr/bin/lynx'], stdin=None, stdout=None, stderr=None, close_fds=True)

    def on_help_clicked(self, button):
        help_dialog = HelpDialog(self)
        help_dialog.run()
        help_dialog.destroy()

    def on_file_clicked(self, button):
        Popen(['dbus-run-session', '/opt/porteus-scripts/xorg/fmanager', '/tmp'], stdin=None, stdout=None, stderr=None, close_fds=True)

class GtkTerminal(Gtk.Dialog):
    def __init__(self, parent, header_txt, option):
        Gtk.Dialog.__init__(self, "Porteus Terminal", parent, 0)
        self.add_buttons(Gtk.STOCK_OK, Gtk.ResponseType.OK)

        self.set_default_size(450, 550)

        self.vb = self.get_content_area()

        self.l_header_txt = Gtk.Label()
        self.l_header_txt.set_markup("<span size=\"x-large\" weight=\"bold\">" + header_txt + "</span>")
        self.vb.add(self.l_header_txt)

        self.terminal = Vte.Terminal()
        self.pty = Vte.Pty.new_sync(Vte.PtyFlags.DEFAULT)
        self.terminal.set_pty(self.pty)
        self.pty.spawn_async(None, ['/opt/porteus-scripts/update', option], None, GLib.SpawnFlags.DO_NOT_REAP_CHILD, None, None, -1, None, self.ready)

        self.scrolledwindow = Gtk.ScrolledWindow()
        self.scrolledwindow.add(self.terminal)
        self.vb.pack_start(self.scrolledwindow, True, True, 5)

        self.show_all()

    def ready(self, pty, task):
        # print('ready')
        None

class HelpDialog(Gtk.Dialog):
    def __init__(self, parent):
        Gtk.Dialog.__init__(self, "Help", parent, 0)
        self.add_buttons(Gtk.STOCK_OK, Gtk.ResponseType.OK)

        self.set_default_size(550, 500)

        self.help_header_txt = "<span size=\"x-large\" weight=\"bold\">Porteus Module Centre Help</span>"
        self.help_txt = "Porteus Module Centre is to help you get or update selected software. \nChoose by \
clicking a button and follow the y/n prompts in the terminal window that opens. Some option offer a choice, either to download a premade \
module from our server or to build it from official packages. \
\n\nIf you choose the latter, for Firefox, Chrome, Chromium, or Opera you can choose your preferred language and \
set a custom homepage (the default homepage is the Porteus forum: https://forum.porteus.org).\
\n\nAt the end, the chosen module(s) can be found in /tmp directory. Multiple modules can be chosen (one at a time).\
\n\nThe Run Lynx button launches a terminal with the included Lynx text based Web browser.\
\n\nYou can use the File button below to open a Privileged (Root user) Filemanager or you can use the normal (Guest user) Filemanager, \
to move the module to your porteus modules directory or somewhere else outside the live filesystem to survive reboot. Don\'t forget \
to activate it (double click). The last activated browser will become the icon visible on the toolbar."

        self.l_header_txt = Gtk.Label()
        self.l_header_txt.set_markup(self.help_header_txt)

        self.vb = self.get_content_area()
        self.vb.add(self.l_header_txt)

        self.scrolledwindow = Gtk.ScrolledWindow(hexpand = True, vexpand = True)
        self.vb.pack_start(self.scrolledwindow, True, True, 5)

        self.textview = Gtk.TextView(border_width = 20, editable = False, wrap_mode = Gtk.WrapMode.WORD, justification = Gtk.Justification.FILL, cursor_visible = False)
        self.textbuffer = self.textview.get_buffer()
        self.textbuffer.set_text(self.help_txt)

        self.scrolledwindow.add(self.textview)

        self.show_all()


win = GtkBrowserUpdate()
win.connect("delete-event", Gtk.main_quit)
win.show_all()
Gtk.main()
