#!/usr/bin/python3
import gi, os, jwmkit_utils
from shutil import which
gi.require_version("Gtk", "3.0")
from gi.repository import Gtk,GdkPixbuf

# JWM Kit - A set of Graphical Apps to simplify use of JWM (Joe's Window Manager) <https://codeberg.org/JWMKit/JWM_Kit>
# Copyright © 2020-2022 Calvin Kent McNabb <apps.jwmkit@gmail.com>
#
# This file is part of JWM Kit.
#
# JWM Kit is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License, VERSIONS 2,
# as published by the Free Software Foundation.
#
# JWM Kit 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 JWM Kit.  If not, see <https://www.gnu.org/licenses/>.


def open_file_manager(button):
    os.system('xdg-open ~ &')


def restart(button):
    os.system('jwm -restart &')


def open_term(button, term):
    os.system('{} &'.format(term))


def repair_tool(button):
    os.system('jwmkit_repair &')


def jwm_website():
    os.system('xdg-open http://joewing.net/projects/jwm/ &')


def term_verify(entry, image):
    term = entry.get_text()
    if which(term):
        image.set_from_icon_name(Gtk.STOCK_OK, size=Gtk.IconSize.BUTTON)
        image.set_tooltip_text('Terminal Found')
    else:
        image.set_from_icon_name(Gtk.STOCK_DIALOG_WARNING, size=Gtk.IconSize.BUTTON)
        image.set_tooltip_text('Terminal Not Found\nverify the file name')
    if term == '':
        image.clear()


class FirstRun(Gtk.Window):

    def __init__(self):
        Gtk.Window.__init__(self, title="JWM Kit First Run")
        try:
            self.set_icon_from_file('/usr/share/pixmaps/jwmkit/config.svg')
        except gi.repository.GLib.Error:
            self.set_icon_name('edit-paste')
        term = jwmkit_utils.find_terminal()
        self.set_border_width(20)
        main_box = Gtk.Box(orientation=Gtk.Orientation.VERTICAL, spacing=0)
        self.add(main_box)

        about_button = Gtk.Button(image=Gtk.Image(stock=Gtk.STOCK_ABOUT))
        about_button.set_always_show_image(True)
        about_button.set_tooltip_text('About')
        about_button.set_property("width-request", 50)
        about_button.set_no_show_all(True)
        about_button.set_visible(True)
        about_button.connect('clicked', jwmkit_utils.get_about, self)

        label = Gtk.Label()
        label.set_markup('<big><big><b>Welcome to JWM Kit</b></big></big>\nPrepare your configuration')
        box = Gtk.Box(orientation=Gtk.Orientation.HORIZONTAL, spacing=20)
        main_box.add(box)

        pb = GdkPixbuf.Pixbuf.new_from_file_at_scale('/usr/share/pixmaps/jwmkit/config.svg', 48, 48,
                                                     preserve_aspect_ratio=True)
        image = Gtk.Image()
        image.set_from_pixbuf(pb)

        box.pack_start(image, False, False, 0)
        box.pack_start(label, False, False, 0)
        box.pack_end(about_button, False, False, 20)
        box = Gtk.Box(orientation=Gtk.Orientation.HORIZONTAL, spacing=10)
        main_box.add(box)
        box.pack_start(Gtk.Label(), True, True, 50)
        box = Gtk.Box(orientation=Gtk.Orientation.HORIZONTAL, spacing=10)
        main_box.add(box)
        box.pack_start(Gtk.Separator(orientation=Gtk.Orientation.HORIZONTAL), True, True, 50)
        box = Gtk.Box(orientation=Gtk.Orientation.HORIZONTAL, spacing=10)
        main_box.add(box)
        box.pack_start(Gtk.Separator(orientation=Gtk.Orientation.HORIZONTAL), True, True, 50)
        box = Gtk.Box(orientation=Gtk.Orientation.HORIZONTAL, spacing=10)
        box.set_border_width(10)
        main_box.add(box)
        label = Gtk.Label()
        label.set_markup('\n')
        label.set_markup("\n<b>New install?</b>\n\tComplete either the simple, advanced, or expert option provided "
                         "below.\n\tThen use the permission button to configure how JWM Kit request permission.\n\t"
                         "Failure to complete these task could leave JWM Kit and/or JWM unusable\n")
        box.add(label)
        box = Gtk.Box(orientation=Gtk.Orientation.HORIZONTAL, spacing=10)
        box.set_border_width(5)
        main_box.add(box)
        label = Gtk.Label()
        label.set_markup('<b>Simple</b>')
        box.add(label)

        box = Gtk.Box(orientation=Gtk.Orientation.HORIZONTAL, spacing=10)
        box.set_border_width(5)
        main_box.add(box)
        restore_button = Gtk.Button(label=' Default', image=Gtk.Image(stock=Gtk.STOCK_COPY))

        restore_button.set_always_show_image(True)
        restore_button.set_property("width-request", 110)
        restore_button.set_tooltip_text('Replace current configuration with the JWM Kit Default')
        restore_button.connect("clicked", self.restore_action)
        label = Gtk.Label(label="Replace the current configuration with the JWM Kit default")
        box.add(restore_button)
        box.add(label)

        box = Gtk.Box(orientation=Gtk.Orientation.HORIZONTAL, spacing=10)
        box.set_border_width(5)
        main_box.add(box)
        label = Gtk.Label()
        label.set_markup('<b>Advanced</b>')
        box.add(label)
        box.pack_start(Gtk.Label(label='*Requires a restore point.'), False, False, 15)

        box = Gtk.Box(orientation=Gtk.Orientation.HORIZONTAL, spacing=10)
        box.set_border_width(5)
        main_box.add(box)
        repair_button = Gtk.Button(label=' Repair', image=Gtk.Image(stock=Gtk.STOCK_REFRESH))
        repair_button.set_always_show_image(True)
        repair_button.set_property("width-request", 110)
        repair_button.set_tooltip_text('JWM Kit Repair & Restore')
        repair_button.connect("clicked", repair_tool)
        label = Gtk.Label(label="Find & repair errors or Revert to restore point")
        box.add(repair_button)
        box.add(label)

        box = Gtk.Box(orientation=Gtk.Orientation.HORIZONTAL, spacing=10)
        box.set_border_width(5)
        main_box.add(box)
        label = Gtk.Label()
        label.set_markup('<b>Expert</b>')
        box.add(label)
        box.pack_start(Gtk.Label(label='*Not Recommended'), False, False, 40)

        box = Gtk.Box(orientation=Gtk.Orientation.HORIZONTAL, spacing=10)
        box.set_border_width(5)
        main_box.add(box)
        info_button = Gtk.Button(label=' Info', image=Gtk.Image(stock=Gtk.STOCK_INFO))
        info_button.set_always_show_image(True)
        info_button.set_property("width-request", 110)
        info_button.set_tooltip_text('Information how to manually restructure the config')
        info_button.connect("clicked", self.show_info)
        label = Gtk.Label(label="Manually restructure an exiting configuration with the info and tools provided")
        box.add(info_button)
        box.add(label)

        box = Gtk.Box(orientation=Gtk.Orientation.HORIZONTAL, spacing=10)
        box.set_border_width(5)
        main_box.add(box)
        label = Gtk.Label()
        label.set_markup('\n<b>Authentication</b>')
        box.pack_start(label, True, True, 0)

        label = Gtk.Label()
        label.set_markup("Configure how JWM Kit request permission.")
        root_button = Gtk.Button(label='Permissions', image=Gtk.Image(stock=Gtk.STOCK_DIALOG_AUTHENTICATION))
        root_button.set_property("width-request", 110)
        root_button.connect('clicked', self.auth_window, term)
        root_button.set_tooltip_text('Configure how JWM Kit tools request permission')

        box = Gtk.Box(orientation=Gtk.Orientation.HORIZONTAL, spacing=10)
        box.set_border_width(10)
        main_box.add(box)
        box.add(root_button)
        box.add(label)

        box = Gtk.Box(orientation=Gtk.Orientation.HORIZONTAL, spacing=10)
        box.set_border_width(5)
        main_box.add(box)
        label = Gtk.Label()
        label.set_markup('<b>Useful Tools</b>')
        box.pack_start(label, True, True, 0)

        box = Gtk.Box(orientation=Gtk.Orientation.HORIZONTAL, spacing=10)
        box.set_border_width(5)
        main_box.add(box)

        term_button = Gtk.Button(label=' Terminal')
        term_button.set_always_show_image(True)
        term_button.set_property("width-request", 130)
        term_button.connect("clicked", open_term, term)
        box.pack_start(term_button, True, True, 0)

        fm_button = Gtk.Button(label=' File Manager')
        fm_button.set_always_show_image(True)
        fm_button.set_property("width-request", 130)
        fm_button.connect("clicked", open_file_manager)
        box.pack_start(fm_button, True, True, 0)

        restart_button = Gtk.Button(label=' Restart JWM')
        restart_button.set_always_show_image(True)
        restart_button.set_property("width-request", 130)
        restart_button.connect("clicked", restart)
        box.pack_start(restart_button, True, True, 0)

    def show_info(self, button):
        jwmkit_utils.viewer(self, '/usr/share/doc/jwmkit/firstrun.txt', 'no-edit')

    def restore_action(self, button):
        response = self.confirm_dialog("Replace the current configuration with the JWM Kit default", 'Confirm Restore')
        if response == -8:
            self.restore_default()
            os.system('jwm -restart')

    def confirm_dialog(self, message, title):
        confirm_dialog = Gtk.Dialog(title, self, 0)
        if title != 'Report':
            confirm_dialog.add_buttons(Gtk.STOCK_NO, Gtk.ResponseType.NO, Gtk.STOCK_YES, Gtk.ResponseType.YES)
        else:
            confirm_dialog.add_buttons(Gtk.STOCK_OK, Gtk.ResponseType.OK)
        confirm_dialog.set_default_size(370, -1)
        label = Gtk.Label(label=message)
        box = confirm_dialog.get_content_area()
        box.set_border_width(20)
        box.set_spacing(20)
        box.add(label)
        confirm_dialog.show_all()
        response = confirm_dialog.run()
        confirm_dialog.destroy()
        return response

    def restore_default(self):
        # Replace user's JWM config with the JWM Kit default
        report = os.popen('jwmkit_repair --restore_default').read().strip('\n')
        self.confirm_dialog(report, 'Report')

    def auth_window(self, button, term):
        def entry_lock1(entry):
            if entry.get_active() in (3, 16):
                term_entry1.set_sensitive(True)
                cmd_entry1.set_sensitive(True)
            elif entry.get_active() == 0:
                term_entry1.set_sensitive(True)
                cmd_entry1.set_sensitive(False)
                cmd_entry1.set_text('su -c')
            elif entry.get_active() == 11:
                term_entry1.set_sensitive(True)
                cmd_entry1.set_sensitive(False)
                cmd_entry1.set_text('su-to-root -c')
            else:
                if cmd_entry1.get_text() in ('su -c', 'su-to-root -c'):
                    cmd_entry1.set_text('')
                term_entry1.set_sensitive(False)
                term1_warn.clear()
                cmd_entry1.set_sensitive(False)
            if entry.get_active() == 3:
                term_label.set_text("Reboot:")
                cmd_label.set_text("Power off:")
                term_entry1.set_tooltip_text('Reboot command')
                cmd_entry1.set_tooltip_text('Shutdown command')
            if entry.get_active() in (0, 11, 16):
                term_label.set_text("Terminal:")
                cmd_label.set_text("Command:")
                if term_entry1.get_text() == '':
                    term_entry1.set_text(term)
                term_entry1.set_tooltip_text('Terminal\nExamples: xterm, lxterminal, gnome-terminal')
                cmd_entry1.set_tooltip_text('Authentication command\nExamples: sudo, su, doas')
            elif entry.get_active() != 3:
                term_entry1.set_text('')
                cmd_entry1.set_tooltip_text('')
                term_entry1.set_tooltip_text('')

        def entry_lock2(entry):
            if entry.get_active() == 12:
                term_entry2.set_sensitive(True)
                cmd_entry2.set_sensitive(True)
                if term_entry2.get_text() == '':
                    term_entry2.set_text(term)
                term_entry2.set_tooltip_text('Terminal\nExamples: xterm, lxterminal, gnome-terminal')
                cmd_entry2.set_tooltip_text('Authentication command\nExamples: sudo, su, doas')
            elif entry.get_active() == 0:
                term_entry2.set_sensitive(True)
                cmd_entry2.set_sensitive(False)
                cmd_entry2.set_text('su -c')
                if term_entry2.get_text() == '':
                    term_entry2.set_text(term)
            elif entry.get_active() == 7:
                term_entry2.set_sensitive(True)
                cmd_entry2.set_sensitive(False)
                cmd_entry2.set_text('su-to-root -c')
                if term_entry2.get_text() == '':
                    term_entry2.set_text(term)
                term_entry2.set_tooltip_text('Terminal\nExamples: xterm, lxterminal, gnome-terminal')
                cmd_entry2.set_tooltip_text('Authentication command\nSet to: su-to-root -c')
            else:
                if cmd_entry2.get_text() in ('su -c', 'su-to-root -c'):
                    cmd_entry2.set_text('')
                term_entry2.set_sensitive(False)
                cmd_entry2.set_sensitive(False)
                term_entry2.set_text('')
                term_entry2.set_tooltip_text('')
                cmd_entry2.set_tooltip_text('')

        def set_widgets():
            for option in logout_options:
                log_combo.append_text(option)
            for option in time_options:
                time_combo.append_text(option)
            if pre_set[0].lower().startswith("term") or pre_set[0].lower().startswith("custom"):
                pre_settings = pre_set[0].split(':')
                term_entry1.set_text(pre_settings[1])
                cmd_entry1.set_text(pre_settings[2])
                pre_set[0] = pre_settings[0]
            elif pre_set[0].lower().startswith("nox:") or pre_set[0].lower().startswith("su:"):
                pre_settings = pre_set[0].split(':')
                term_entry1.set_text(pre_settings[1])
                pre_set[0] = pre_settings[0]

            if pre_set[1].lower().startswith("term"):
                pre_settings = pre_set[1].split(':')
                term_entry2.set_text(pre_settings[1])
                cmd_entry2.set_text(pre_settings[2])
                pre_set[1] = 'term'
            elif pre_set[1].lower().startswith("nox:") or pre_set[1].lower().startswith("su:"):
                pre_settings = pre_set[1].split(':')
                term_entry2.set_text(pre_settings[1])
                pre_set[1] = pre_settings[0]
            pre_set[0], pre_set[1] = pre_set[0].lower(), pre_set[1].lower()
            if pre_set[0].lower() in log_parms:
                log_combo.set_active(log_parms.index(pre_set[0]))
            if pre_set[1].lower() in time_parms:
                time_combo.set_active(time_parms.index(pre_set[1]))

        def save_setting_su():
            path = os.path.expanduser("~")
            path = '{}/.config/jwmkit/setting_su'.format(path)
            log_data = log_parms[log_combo.get_active()]
            time_data = time_parms[time_combo.get_active()]
            if log_data in ('term', 'custom'):
                log_data = '{}:{}:{}'.format(log_data, term_entry1.get_text(), cmd_entry1.get_text())
            elif log_data in ('nox', 'su'):
                log_data = '{}:{}'.format(log_data, term_entry1.get_text())
            if time_data == 'term':
                time_data = '{}:{}:{}'.format(time_data, term_entry2.get_text(), cmd_entry2.get_text())
            elif time_data in ('nox', 'su'):
                time_data = '{}:{}'.format(time_data, term_entry2.get_text())
            output = 'logout={}\ntime={}\neditor={}\narchiver={}\n' \
                     'filemanager={}\n'.format(log_data, time_data, pre_set[2], pre_set[3], pre_set[4])

            with open(path, "w+") as f:
                f.write(output)

        pre_set = jwmkit_utils.read_setting_su()
        log_combo, time_combo = Gtk.ComboBoxText(), Gtk.ComboBoxText()
        term_entry1, term_entry2, cmd_entry1, cmd_entry2 = Gtk.Entry(), Gtk.Entry(), Gtk.Entry(), Gtk.Entry()
        term1_warn, term2_warn = Gtk.Image(), Gtk.Image()

        term_entry1.connect('changed', term_verify, term1_warn)
        term_entry2.connect('changed', term_verify, term2_warn)

        term_entry1.set_sensitive(False)
        term_entry2.set_sensitive(False)
        cmd_entry1.set_sensitive(False)
        cmd_entry2.set_sensitive(False)

        term_entry1.set_property("width-request", 100)
        term_entry2.set_property("width-request", 100)
        cmd_entry1.set_property("width-request", 100)
        cmd_entry2.set_property("width-request", 100)
        log_combo.set_property("width-request", 420)
        time_combo.set_property("width-request", 420)
        logout_options = ("su | Terminal", "sudo | Built in prompt", "ConsoleKit", "Custom",
                          "Do not ask permission", "elogind  ( loginctl )", "gksu ( Real )", "gksu ( Fake )",
                          "gksudo ( Real )", "gksudo ( Fake )", "Puppy ( wmreboot / wmpoweroff )",
                          "su-to-root -c | Terminal", "su-to-root -X -c", "sudo ( no password )",
                          "sudo --askpass", "System D ( systemctl )", "Terminal", "doas ( no password )")
        time_options = ("su | Terminal", "sudo | Built in prompt", "Do not ask permission", "gksu ( Real )",
                        "gksu ( Fake )", "gksudo ( Real )", "gksudo ( Fake )", "su-to-root -c | Terminal",
                        "su-to-root -X -c", "sudo ( no password )", "sudo --askpass", "System D ( timedatectl )",
                        "Terminal")

        log_parms = ("su", "sudop", "", "custom", "nosu", "elogind", "gksu_r", "gksu", "gksudo_r", "gksudo", "puppy",
                     "nox", "x", "sudo", "sudoa", "sysd", "term", "doas")

        time_parms = ("su", "sudop", "nosu", "gksu_r", "gksu",  "gksudo_r", "gksudo", "nox", "x", "sudo", "sudoa",
                      "sysd", "term")

        term_label = Gtk.Label(label="Terminal:")
        cmd_label = Gtk.Label(label="Command:")
        log_combo.connect("changed", entry_lock1)
        time_combo.connect("changed", entry_lock2)
        set_widgets()

        auth_dialog = Gtk.Dialog("Authentication", self, 0)
        auth_dialog.set_default_size(500, -1)
        auth_dialog.add_buttons(Gtk.STOCK_CANCEL, Gtk.ResponseType.NO, Gtk.STOCK_SAVE, Gtk.ResponseType.OK)
        box = auth_dialog.get_content_area()
        box.set_border_width(20)
        column = Gtk.Box(orientation=Gtk.Orientation.VERTICAL, spacing=15)
        box.add(column)
        row = Gtk.Box(orientation=Gtk.Orientation.HORIZONTAL, spacing=15)
        column.add(row)
        label = Gtk.Label()
        label.set_markup("<big><b>Authentication</b></big>")
        image = Gtk.Image.new_from_icon_name(Gtk.STOCK_DIALOG_AUTHENTICATION, size=Gtk.IconSize.DIALOG)
        row.pack_start(image, False, False, 15)
        row.pack_start(label, False, False, 0)

        label = Gtk.Label()
        label.set_markup('<big><b>Disclaimer</b></big>')
        label.set_tooltip_text("JWM Kit provides the options for the convince of the user.\nYou are responsible "
                               "for the security of your system. Neither the\nauthor of JWM Kit nor anyone involved "
                               "with JWM Kit is to be held\nresponsible for your system's security.")
        row.pack_end(label, False, False, 10)

        row = Gtk.Box(orientation=Gtk.Orientation.HORIZONTAL, spacing=15)
        column.add(row)
        row.pack_start(Gtk.Label(label='Choose how the following tools request permission'), False, False, 15)

        row = Gtk.Box(orientation=Gtk.Orientation.HORIZONTAL, spacing=5)
        column.add(row)
        row.pack_end(log_combo, False, False, 0)
        row.pack_end(Gtk.Label(label="JWM Kit Logout:"), False, False, 0)

        row = Gtk.Box(orientation=Gtk.Orientation.HORIZONTAL, spacing=5)
        column.add(row)
        row.pack_end(cmd_entry1, False, False, 0)
        row.pack_end(cmd_label, False, False, 5)
        row.pack_end(term_entry1, False, False, 0)
        row.pack_start(term1_warn, False, False, 0)
        row.pack_end(term_label, False, False, 5)

        row = Gtk.Box(orientation=Gtk.Orientation.HORIZONTAL, spacing=5)
        column.add(row)
        row.pack_end(time_combo, False, False, 0)
        row.pack_end(Gtk.Label(label="JWM Kit Time:"), False, False, 0)

        row = Gtk.Box(orientation=Gtk.Orientation.HORIZONTAL, spacing=5)
        column.add(row)
        row.pack_end(cmd_entry2, False, False, 0)
        row.pack_end(Gtk.Label(label="Command:"), False, False, 5)
        row.pack_end(term_entry2, False, False, 0)
        row.pack_start(term2_warn, False, False, 0)
        row.pack_end(Gtk.Label(label="Terminal:"), False, False, 5)

        row = Gtk.Box(orientation=Gtk.Orientation.HORIZONTAL, spacing=5)
        column.add(row)
        row.add(Gtk.Label())
        auth_dialog.show_all()
        response = auth_dialog.run()
        if response == -5:
            save_setting_su()
        auth_dialog.destroy()


win = FirstRun()
win.connect("delete-event", Gtk.main_quit)
win.set_position(Gtk.WindowPosition.CENTER)
win.show_all()
Gtk.main()

# TODO
#  -
#  Useful Tools : entry to execute commands
#  -
#  Permission config
#  - Time - Add "Custom" option for specifying a command
#  -  - - To simplify merge custom option with terminal
#  - Determine available options
#  First run ( no setting_su file or file is corrupt )
#  -  run test to determine available options
#  -  preselect the best available option
#  -  warn if user select an unavailable option
#  - - Example It appear sudo is not installed or properly configured.  ( or systemd, etc )
#  -
#  Usability
#  - Reduce instruction text
#  - Make it more obvious the user needs to select only 1 out of [ Default, Repair, and Info ]

