#!/usr/bin/python3
# -*- coding: UTF-8 -*-

import gi
import os
import re, sys

gi.require_version('Gtk', '3.0')
from gi.repository import Gtk, Gdk, Pango
import json

import gettext
import locale

gi.require_version('Gtk', '3.0')
gi.require_version('Gdk', '3.0')
from gi.repository import Gtk, Gdk

locale.bindtextdomain("ubl-udevrules", "/usr/share/locale")
locale.textdomain("ubl-udevrules")
gettext.bindtextdomain('ubl-udevrules', '/usr/share/locale')
gettext.textdomain('ubl-udevrules')
_ = gettext.gettext

builder = Gtk.Builder()
builder.set_translation_domain("ubl-udevrules")
LAYOUT_STYLE_LEGACY, LAYOUT_STYLE_NEW = range(2)

builder.add_from_file('/usr/share/ubl-udevrules/ui/ubl-udevrules.glade')
#builder.add_from_file('ui/ubl-udevrules.glade')

class base:
    def __init__(self):
        # win = InfoClass()
        self.window = builder.get_object("main_window")
        self.window.set_title(_("GUI configuring UDEV rules for connecting USB devices"))
        self.udev_rules_treeview = builder.get_object("udev_rules_treeview")
        renderer_text = Gtk.CellRendererText()
        column_text = Gtk.TreeViewColumn(_("Available rules"), renderer_text, text=0)
        self.udev_rules_treeview.append_column(column_text)
        self.udev_rules_treeview.get_selection().connect("changed", self.select_rule)

        values = ["usb-storage", "usb-modems", "usb", "gphoto2"]

        self.combo_udev_types = Gtk.ListStore(str)

        for value in values:
            self.combo_udev_types.append([value])

        self.accept_new_rule_button = builder.get_object("accept_new_rule_button")
        self.accept_new_rule_button.connect("clicked", self.on_accept_new_rule_button_clicked)

        self.udev_types_combobox = builder.get_object("udev_types_combobox")

        self.udev_types_combobox.set_model(self.combo_udev_types)
        renderer_text = Gtk.CellRendererText()
        self.udev_types_combobox.pack_start(renderer_text, True)
        self.udev_types_combobox.add_attribute(renderer_text, "text", 0)
        self.udev_types_combobox.set_entry_text_column(0)
        self.udev_types_combobox.set_active(0)

        self.udev_rules_liststore = Gtk.ListStore(str)
        rules = [f"/etc/udev/rules.d/{f}" for f in os.listdir('/etc/udev/rules.d/') if
                 re.match(r'.*ubl_udevrules.*\.rules', f)]

        for rule in rules:
            self.udev_rules_liststore.append([rule.strip()])

        self.udev_rules_treeview.set_model(self.udev_rules_liststore)

        self.devices_treeview = builder.get_object("devices_treeview")
        self.devices_log_treeview = builder.get_object("devices_log_treeview")

        self.devices_liststore = Gtk.ListStore(str, str, str, str)
        self.devices_log_liststore = Gtk.ListStore(str, str, str, str)
        usbs = os.popen("lsusb").readlines()
        for usb in usbs:
            usb_ = usb.split(" ")
            self.devices_liststore.append([usb.strip(), usb_[1], usb_[3],
                                           " ".join(str(line).strip() for line in usb_[6:])])
            self.devices_log_liststore.append([usb.strip(), usb_[1], usb_[3],
                                               " ".join(str(line).strip() for line in usb_[6:])])
        self.devices_treeview.set_model(self.devices_liststore)
        self.devices_log_treeview.set_model(self.devices_log_liststore)

        renderer_text = Gtk.CellRendererText()
        column_text = Gtk.TreeViewColumn(_("Available usb"), renderer_text, text=0)
        self.devices_treeview.append_column(column_text)
        self.devices_treeview.get_selection().connect("changed", self.select_device)

        renderer_text = Gtk.CellRendererText()
        column_text = Gtk.TreeViewColumn(_("Available usb"), renderer_text, text=0)
        self.devices_log_treeview.append_column(column_text)
        self.devices_log_treeview.get_selection().connect("changed", self.select_log_device)

        self.udev_log_rule_treeview = builder.get_object("udev_log_rule_treeview")
        self.udev_log_rule_liststore = Gtk.ListStore(str, str)
        self.udev_log_rule_treeview.get_selection().connect("changed", self.select_udev_log_line)

        if os.path.exists("/etc/udev/rules.d/98-ubl_udevrules_logs.rules"):
            with open("/etc/udev/rules.d/98-ubl_udevrules_logs.rules") as log_file:
                data = log_file.readlines()

                first_line = data[0].split("echo connected ${devnode}")[1].split("$(date)")[0].strip().split(" ")
                for item in first_line:
                    item = item.split("=")[0]
                    self.udev_log_rule_liststore.append(["ENV", item])

        self.udev_log_rule_treeview.set_model(self.udev_log_rule_liststore)

        renderer_text = Gtk.CellRendererText()
        renderer_text.set_property("editable", False)
        column_text = Gtk.TreeViewColumn(_("Type"), renderer_text, text=0)

        self.udev_log_rule_treeview.append_column(column_text)

        renderer_text = Gtk.CellRendererText()
        renderer_text.set_property("editable", True)
        renderer_text.connect("edited", self.on_text_env_edited)
        column_text = Gtk.TreeViewColumn(_("Attribute"), renderer_text, text=1)
        self.udev_log_rule_treeview.append_column(column_text)
        self.log_path_entry = builder.get_object("log_path_entry")

        self.edit_rule_button = builder.get_object("edit_rule_button")
        self.edit_rule_button.connect("clicked", self.on_edit_rule_button_clicked)

        self.delete_rule_button = builder.get_object("delete_rule_button")
        self.delete_rule_button.connect("clicked", self.on_delete_rule_button_clicked)

        self.open_device_attrs_button = builder.get_object("open_device_attrs_button")
        self.open_device_attrs_button.connect("clicked", self.on_open_device_attrs_button_clicked)

        self.open_device_envs_button = builder.get_object("open_device_envs_button")
        self.open_device_envs_button.connect("clicked", self.on_open_device_envs_button_clicked)

        self.open_device_envs_log_button = builder.get_object("open_device_envs_log_button")
        self.open_device_envs_log_button.connect("clicked", self.on_open_device_log_envs_button_clicked)

        self.add_attr_button_logs = builder.get_object("add_attr_button_logs")
        self.add_attr_button_logs.connect("clicked", self.on_add_attr_button_logs_clicked)

        self.remove_attr_button_logs = builder.get_object("remove_attr_button_logs")
        self.remove_attr_button_logs.connect("clicked", self.on_remove_attr_button_logs_clicked)

        self.delete_udev_log_button = builder.get_object("delete_udev_log_button")
        self.delete_udev_log_button.connect("clicked", self.on_delete_udev_log_button_clicked)

        self.save_udev_log_button = builder.get_object("save_udev_log_button")
        self.save_udev_log_button.connect("clicked", self.on_save_udev_log_button_clicked)

        self.window.show_all()

    def on_save_udev_log_button_clicked(self, button):
        with open("/etc/udev/rules.d/98-ubl_udevrules_logs.rules", "w") as log_file:
            first_line = "ENV{DRIVER}==\"usb-storage\",ACTION==\"add\", RUN+=\"/bin/sh -c 'echo connected ${devnode} "
            second_line = "ENV{DRIVER}==\"usb-storage\",ACTION==\"remove\", RUN+=\"/bin/sh -c 'echo disconnected ${devnode} "
            for item in self.udev_log_rule_liststore:
                first_line += f"{item[1]}=%E" + "{" + f"{item[1]}" + "} "
                second_line += f"{item[1]}=%E" + "{" + f"{item[1]}" + "} "
            path = self.log_path_entry.get_text()
            if path != "":
                first_line_end = f"$(date)>> {path}'\"\n"
                second_line_end = f"$(date)>> {path}'\"\n"
            else:
                first_line_end = f"$(date)>> /var/log/ubl-udevrules.log'\"\n"
                second_line_end = f"$(date)>> /var/log/ubl-udevrules.log'\"\n"
            first_line += first_line_end
            second_line += second_line_end

            log_file.write(first_line)
            log_file.write(second_line)

            os.system("udevadm control --reload")

    def on_delete_udev_log_button_clicked(self, button):
        os.system("rm -rf /etc/udev/rules.d/98-ubl_udevrules_logs.rules")
        os.system("udevadm control --reload")
        self.udev_log_line_selection.unselect_all()
        self.udev_log_rule_liststore.clear()

    def select_udev_log_line(self, selection):
        (self.model_udev_log, self.iter_udev_log) = selection.get_selected()
        self.udev_log_line_selection = selection

    def on_add_attr_button_logs_clicked(self, button):
        self.udev_log_rule_liststore.append(["ENV", ""])

    def on_remove_attr_button_logs_clicked(self, button):
        try:
            (model, iter) = self.udev_log_line_selection.get_selected()
            self.udev_log_rule_liststore.remove(iter)
            self.udev_log_line_selection.unselect_all()
        except Exception as e:
            print(e)

    def on_text_env_edited(self, widget, path, text):
        self.udev_log_rule_liststore[path][1] = text

    def on_accept_new_rule_button_clicked(self, button):
        tree_iter = self.udev_types_combobox.get_active_iter()
        if tree_iter is not None:
            model = self.udev_types_combobox.get_model()
            value = model[tree_iter][0]
            rules = len([f"/etc/udev/rules.d/{f}" for f in os.listdir('/etc/udev/rules.d/') if
                         re.match(r'.*ubl_udevrules.*\.rules', f)])
            if rules == 0:
                os.system(f"cp /usr/share/ubl-udevrules/templates/{value}.rules /etc/udev/rules.d/80-ubl_udevrules.rules")
                self.udev_rules_liststore.append(["/etc/udev/rules.d/80-ubl_udevrules.rules"])
            else:
                os.system(
                    f"cp /usr/share/ubl-udevrules/templates/{value}.rules /etc/udev/rules.d/80-ubl_udevrules-{rules + 1}.rules")
                self.udev_rules_liststore.append([f"/etc/udev/rules.d/80-ubl_udevrules-{rules + 1}.rules"])
            os.system("udevadm control --reload")

    def select_device(self, selection):
        (self.model, self.iter) = selection.get_selected()
        self.device_selection = selection

    def select_log_device(self, selection):
        (self.model_log, self.iter_log) = selection.get_selected()
        self.device_log_selection = selection

    def select_rule(self, selection):
        (self.model_udev_rules, self.iter_udev_rules) = selection.get_selected()
        self.udev_rule_selection = selection

    def on_edit_rule_button_clicked(self, button):
        if hasattr(self, 'model_udev_rules') and hasattr(self, 'iter_udev_rules'):
            if self.model_udev_rules and self.iter_udev_rules:
                udev_path = self.model_udev_rules.get_value(self.iter_udev_rules, 0)
                self.udev_rule_selection.unselect_all()
                win = UdevRulesWindow(udev_path)

    def on_delete_rule_button_clicked(self, button):
        if hasattr(self, 'model_udev_rules') and hasattr(self, 'iter_udev_rules'):
            if self.model_udev_rules and self.iter_udev_rules:
                udev_path = self.model_udev_rules.get_value(self.iter_udev_rules, 0)
                self.udev_rules_liststore.remove(self.iter_udev_rules)
                self.udev_rule_selection.unselect_all()
                os.system(f"rm -rf {udev_path}")
                udev_name = udev_path.split(".rules")[0].split("/")[-1]
                self.json_del("userlists", udev_path, udev_name)
                self.json_del("grouplists", udev_path, udev_name)
                self.json_del("otherlists", udev_path, udev_name)
                udev_name = udev_path.split(".rules")[0].split("/")[-1].split("-")
                if len(udev_name) > 2:
                    os.system(f"rm -rf /etc/systemd/system/usb-mount{udev_name[2]}@.service")
                elif len(udev_name) == 2:
                    os.system("rm -rf /etc/systemd/system/usb-mount@.service")
                os.system("systemctl daemon-reload")
                os.system("udevadm control --reload")

    def json_del(self, type, udev_path, udev_name):
        try:
            with open(f"/usr/share/ubl-udevrules/{type}/list-udev.json", "r") as js_file:
                data = json.load(js_file)
            if udev_path in data.keys():
                with open(f"/usr/share/ubl-udevrules/{type}/list-udev.json", "w+") as js_file:
                    if udev_path in data.keys():
                        del data[udev_path]
                        json.dump(data, js_file)
                        os.system(f"rm -rf /usr/share/ubl-udevrules/{type}/{udev_name}.json")
        except KeyError:
            pass

    def on_open_device_attrs_button_clicked(self, button):
        if hasattr(self, 'model') and hasattr(self, 'iter'):
            if self.model and self.iter:
                bus = self.model.get_value(self.iter, 1)
                device = self.model.get_value(self.iter, 2)[0:-1]
                name = self.model.get_value(self.iter, 3)
                self.device_selection.unselect_all()
                win = DevicesWindow(bus, device, name, "attrs")

    def on_open_device_envs_button_clicked(self, button):
        if hasattr(self, 'model') and hasattr(self, 'iter'):
            if self.model and self.iter:
                bus = self.model.get_value(self.iter, 1)
                device = self.model.get_value(self.iter, 2)[0:-1]
                name = self.model.get_value(self.iter, 3)
                self.device_selection.unselect_all()
                win = DevicesWindow(bus, device, name, "envs")

    def on_open_device_log_envs_button_clicked(self, button):
        if hasattr(self, 'model_log') and hasattr(self, 'iter_log'):
            if self.model_log and self.iter_log:
                bus = self.model_log.get_value(self.iter_log, 1)
                device = self.model_log.get_value(self.iter_log, 2)[0:-1]
                name = self.model_log.get_value(self.iter_log, 3)
                self.device_log_selection.unselect_all()
                win = DevicesWindow(bus, device, name, "envs")

    def on_button_env_add_clicked(self, button):
        global ENVS
        ENVS.append(self.combo_env.get_active_text() + "=%E{" + self.combo_env.get_active_text() + "}")
        ENVS = list(set(ENVS))
        strk = ""
        for env in ENVS:
            strk += "    " + env + "\n"
        self.textbuffer_log.set_text(str(strk))


class DevicesWindow:
    def __init__(self, bus, device, name, type):
        builder_template = Gtk.Builder()
        builder_template.add_from_file('/usr/share/ubl-udevrules/ui/templates.glade')
        #builder_template.add_from_file('ui/templates.glade')
        self.window = builder_template.get_object("device_attributes_window")
        self.window.set_title(name)
        self.device_attrs_textview = builder_template.get_object("device_attrs_textview")
        self.device_attrs_buffer = self.device_attrs_textview.get_buffer()

        self.close_device_window_button = builder_template.get_object("close_device_window_button")
        self.close_device_window_button.connect("clicked", self.on_close_device_window_button_clicked)

        if type == "attrs":
            line = os.popen(f"udevadm info -q path -n /dev/bus/usb/{bus}/{device}").readline().strip()
            line_ = line.split("/")[-1]
            print(f"udevadm info -a -p /sys{line}/{line_}*")
            info = os.popen(f"udevadm info -a -p /sys{line}/{line_}*").readlines()
        elif type == "envs":
            line = os.popen(f"udevadm info -q path -n /dev/bus/usb/{bus}/{device}").readline().strip()
            line_ = line.split("/")[-1]
            info = os.popen(f"udevadm info -p /sys{line}/{line_}*").readlines()

        info = "".join(str(line) for line in info)
        self.device_attrs_buffer.set_text(info)

        self.window.show_all()

    def on_close_device_window_button_clicked(self, button):
        self.window.destroy()


class UdevRulesWindow:
    def __init__(self, udev_path):
        builder_template = Gtk.Builder()
        builder_template.add_from_file('/usr/share/ubl-udevrules/ui/templates.glade')
        #builder_template.add_from_file('ui/templates.glade')
        self.window = builder_template.get_object("udev_rules_window")
        self.udev_path = udev_path
        # name = udev_path.split("/")[-1]
        self.window.set_title(self.udev_path)
        self.device_attrs_textview = builder_template.get_object("device_attrs_textview")
        self.device_attrs_buffer = self.device_attrs_textview.get_buffer()

        self.udev_rules_treeview = builder_template.get_object("udev_rules_treeview")
        self.udev_rule_combo_liststore = Gtk.ListStore(str)
        self.udev_rule_combo_liststore.append(["ATTRS"])
        self.udev_rule_combo_liststore.append(["ATTR"])
        self.udev_rule_combo_liststore.append(["ENV"])

        self.udev_rule_liststore = Gtk.ListStore(str, str, str, str)
        self.user_binding_checkbox = builder_template.get_object("user_binding_checkbox")
        self.user_binding_checkbox.connect("toggled", self.on_use_user_binding_toggled)

        with open(udev_path) as f:
            file = f.readlines()
            if file[-1] == "":
                file = file[:-1]
            if len(file) >= 7:
                if 'LABEL="dont_remove_usb"' in file[-6]:
                    file = file[:-7]
                elif 'LABEL="dont_remove_usb"' in file[-3]:
                    file = file[:-4]
                elif 'LABEL="dont_remove_usb"' in file[-1]:
                    file = file[:-2]
            elif 'LABEL="dont_remove_usb"' in file[-1]:
                file = file[:-2]
            if file[0].strip() != "#type:usb-storage":
                self.user_binding_checkbox.set_sensitive(False)
            file = file[3:]
            if len(file) > 0:
                for line in file:
                    line = line.strip()
                    line = line.split(",")[0].split("==")
                    atr = line[0]
                    if "ATTRS" in atr:
                        val = line[1]
                        atr = re.sub("ATTRS{", "", atr)
                        atr = re.sub("}", "", atr)
                        val = re.sub("\"", "", val)
                        self.udev_rule_liststore.append(["ATTRS", atr, "==", val])
                    elif "ATTR" in atr:
                        val = line[1]
                        atr = re.sub("ATTR{", "", atr)
                        atr = re.sub("}", "", atr)
                        val = re.sub("\"", "", val)
                        self.udev_rule_liststore.append(["ATTR", atr, "==", val])
                    elif "ENV" in atr:
                        val = line[1]
                        atr = re.sub("ENV{", "", atr)
                        atr = re.sub("}", "", atr)
                        val = re.sub("\"", "", val)
                        self.udev_rule_liststore.append(["ENV", atr, "==", val])

        self.udev_rules_treeview.set_model(self.udev_rule_liststore)

        renderer_combo = Gtk.CellRendererCombo()
        renderer_combo.set_property("editable", True)
        renderer_combo.set_property("model", self.udev_rule_combo_liststore)
        renderer_combo.set_property("text-column", 0)
        renderer_combo.set_property("has-entry", False)
        renderer_combo.connect("edited", self.on_udev_rule_combo_liststore_changed)

        column_combo = Gtk.TreeViewColumn(_("Type"), renderer_combo, text=0)
        self.udev_rules_treeview.append_column(column_combo)

        renderer_text = Gtk.CellRendererText()
        renderer_text.set_property("editable", True)
        renderer_text.connect("edited", self.on_text_atr_edited)
        column_text = Gtk.TreeViewColumn(_("Attribute"), renderer_text, text=1)
        self.udev_rules_treeview.append_column(column_text)

        renderer_text = Gtk.CellRendererText()
        column_text = Gtk.TreeViewColumn(_("Equal sign"), renderer_text, text=2)
        self.udev_rules_treeview.append_column(column_text)

        renderer_text = Gtk.CellRendererText()
        renderer_text.set_property("editable", True)
        renderer_text.connect("edited", self.on_text_val_edited)
        column_text = Gtk.TreeViewColumn(_("Values"), renderer_text, text=3)
        self.udev_rules_treeview.append_column(column_text)
        self.udev_rules_treeview.get_selection().connect("changed", self.select_udev_line)

        self.add_attr_button = builder_template.get_object("add_attr_button")
        self.add_attr_button.connect("clicked", self.on_add_attr_button_clicked)

        self.scroll_userlist = builder_template.get_object("scroll_userlist")
        self.scroll_grouplist = builder_template.get_object("scroll_grouplist")
        self.box_others = builder_template.get_object("box_others")
        self.scroll_userlist.set_sensitive(False)
        self.scroll_grouplist.set_sensitive(False)
        self.box_others.set_sensitive(False)
        self.remove_attr_button = builder_template.get_object("remove_attr_button")
        self.remove_attr_button.connect("clicked", self.on_remove_attr_button_clicked)

        self.userlist_treeview = builder_template.get_object("userlist_treeview")
        self.liststore_users_auth = Gtk.ListStore(str, bool, str)

        users = os.popen("cut -d: -f1,3 /etc/passwd | egrep ':[0-9]{4}$' | cut -d: -f1 | sort").readlines()
        data_liststore = None
        with open("/usr/share/ubl-udevrules/userlists/list-udev.json") as main_userlist_file:
            data = json.load(main_userlist_file)
            if self.udev_path in data.keys():
                with open(data[self.udev_path]) as userlist_file:
                    data_liststore = json.load(userlist_file)
        if data_liststore:
            self.scroll_userlist.set_sensitive(True)
            self.scroll_grouplist.set_sensitive(True)
            self.box_others.set_sensitive(True)
            self.user_binding_checkbox.set_active(True)
            for user in users:
                user_re = re.sub("\n", "", user)
                if user_re in data_liststore.keys():
                    if data_liststore[user_re] == 7:
                        self.liststore_users_auth.append([user_re, True, _("No rights")])
                    elif data_liststore[user_re] == 3:
                        self.liststore_users_auth.append([user_re, True, _("Read")])
                    elif data_liststore[user_re] == 1:
                        self.liststore_users_auth.append([user_re, True, _("Read, Write")])
                    elif data_liststore[user_re] == 0:
                        self.liststore_users_auth.append([user_re, True, _("All")])
                else:
                    self.liststore_users_auth.append([user_re, False, _("No rights")])
        else:
            for user in users:
                user_re = re.sub("\n", "", user)
                self.liststore_users_auth.append([user_re, False, _("No rights")])

        self.userlist_treeview.set_model(self.liststore_users_auth)

        self.grouplist_treeview = builder_template.get_object("grouplist_treeview")

        self.liststore_groups_auth = Gtk.ListStore(str, bool, str)
        groups = os.popen("getent group | awk -F: '{print $1}' | sort").readlines()

        data_liststore = None
        with open("/usr/share/ubl-udevrules/grouplists/list-udev.json") as main_grouplist_file:
            data = json.load(main_grouplist_file)
            if self.udev_path in data.keys():
                with open(data[self.udev_path]) as grouplist_file:
                    data_liststore = json.load(grouplist_file)
        if data_liststore:
            self.scroll_userlist.set_sensitive(True)
            self.scroll_grouplist.set_sensitive(True)
            self.box_others.set_sensitive(True)
            self.user_binding_checkbox.set_active(True)
            for group in groups:
                group_re = re.sub("\n", "", group)
                if group_re in data_liststore.keys():
                    if data_liststore[group_re] == 7:
                        self.liststore_groups_auth.append([group_re, True, _("No rights")])
                    elif data_liststore[group_re] == 3:
                        self.liststore_groups_auth.append([group_re, True, _("Read")])
                    elif data_liststore[group_re] == 1:
                        self.liststore_groups_auth.append([group_re, True, _("Read, Write")])
                    elif data_liststore[group_re] == 0:
                        self.liststore_groups_auth.append([group_re, True, _("All")])
                else:
                    self.liststore_groups_auth.append([group_re, False, _("No rights")])
        else:
            for group in groups:
                group_re = re.sub("\n", "", group)
                self.liststore_groups_auth.append([group_re, False, _("No rights")])

        self.grouplist_treeview.set_model(self.liststore_groups_auth)

        values = [_("All"), _("Read"), _("Read, Write"), _("No rights")]  # 0:all, 1:r, 2:rw, 3:rwx

        self.combo_values_user_liststore = Gtk.ListStore(str)
        self.combo_values_group_liststore = Gtk.ListStore(str)
        self.combo_values_anybody_liststore = Gtk.ListStore(str)

        for value in values:
            self.combo_values_user_liststore.append([value])
            self.combo_values_group_liststore.append([value])
            self.combo_values_anybody_liststore.append([value])

        renderer_text = Gtk.CellRendererText()
        column_text = Gtk.TreeViewColumn(_("User"), renderer_text, text=0)
        self.userlist_treeview.append_column(column_text)

        renderer_toggle = Gtk.CellRendererToggle()
        renderer_toggle.set_radio(True)
        renderer_toggle.connect("toggled", self.on_cell_selectuser_liststore, 1)
        column_toggle = Gtk.TreeViewColumn(_("Selected"), renderer_toggle, active=1)
        self.userlist_treeview.append_column(column_toggle)

        renderer_combo = Gtk.CellRendererCombo()
        renderer_combo.set_property("editable", True)
        renderer_combo.set_property("model", self.combo_values_user_liststore)
        renderer_combo.set_property("text-column", 0)
        renderer_combo.set_property("has-entry", False)
        renderer_combo.connect("edited", self.on_combo_user_right_changed)

        column_combo = Gtk.TreeViewColumn(_("Rights"), renderer_combo, text=2)
        self.userlist_treeview.append_column(column_combo)

        renderer_text = Gtk.CellRendererText()
        column_text = Gtk.TreeViewColumn(_("Group"), renderer_text, text=0)
        self.grouplist_treeview.append_column(column_text)

        renderer_toggle = Gtk.CellRendererToggle()
        renderer_toggle.set_radio(True)
        renderer_toggle.connect("toggled", self.on_cell_selectgroup_liststore, 1)
        column_toggle = Gtk.TreeViewColumn(_("Selected"), renderer_toggle, active=1)
        self.grouplist_treeview.append_column(column_toggle)

        renderer_combo = Gtk.CellRendererCombo()
        renderer_combo.set_property("editable", True)
        renderer_combo.set_property("model", self.combo_values_group_liststore)
        renderer_combo.set_property("text-column", 0)
        renderer_combo.set_property("has-entry", False)
        renderer_combo.connect("edited", self.on_combo_group_right_changed)

        column_combo = Gtk.TreeViewColumn(_("Rights"), renderer_combo, text=2)
        self.grouplist_treeview.append_column(column_combo)

        self.other_users_combobox = builder_template.get_object("other_users_combobox")
        self.other_users_combobox.set_model(self.combo_values_anybody_liststore)
        renderer_text = Gtk.CellRendererText()
        self.other_users_combobox.pack_start(renderer_text, True)
        self.other_users_combobox.add_attribute(renderer_text, "text", 0)
        self.other_users_combobox.set_entry_text_column(0)

        data_liststore = None
        with open("/usr/share/ubl-udevrules/otherlists/list-udev.json") as main_otherlist_file:
            data = json.load(main_otherlist_file)
            if self.udev_path in data.keys():
                with open(data[self.udev_path]) as otherlist_file:
                    data_liststore = json.load(otherlist_file)
        if data_liststore:
            if data_liststore["others"] == 7:
                self.other_users_combobox.set_active(3)
            elif data_liststore["others"] == 3:
                self.other_users_combobox.set_active(1)
            elif data_liststore["others"] == 1:
                self.other_users_combobox.set_active(2)
            elif data_liststore["others"] == 0:
                self.other_users_combobox.set_active(0)
        else:
            self.other_users_combobox.set_active(3)
        self.save_udev_button = builder_template.get_object("save_udev_button")
        self.save_udev_button.connect("clicked", self.on_save_udev_button_clicked)

        self.close_udev_window_button = builder_template.get_object("close_udev_window_button")
        self.close_udev_window_button.connect("clicked", self.on_close_device_window_button_clicked)

        self.window.show_all()

    def on_cell_selectuser_liststore(self, widget, path, index):
        self.liststore_users_auth[path][index] = not self.liststore_users_auth[path][index]

    def on_cell_selectgroup_liststore(self, widget, path, index):
        self.liststore_groups_auth[path][index] = not self.liststore_groups_auth[path][index]

    def on_use_user_binding_toggled(self, button):
        if button.get_active():
            self.scroll_userlist.set_sensitive(True)
            self.scroll_grouplist.set_sensitive(True)
            self.box_others.set_sensitive(True)
        else:
            self.scroll_userlist.set_sensitive(False)
            self.scroll_grouplist.set_sensitive(False)
            self.box_others.set_sensitive(False)

    def select_udev_line(self, selection):
        (self.model, self.iter) = selection.get_selected()
        self.udev_line_selection = selection

    def fill_combo(self, values, combo, index):
        liststore = Gtk.ListStore(str)
        for v in values:
            liststore.append([v])
        combo.set_model(liststore)
        renderer_text = Gtk.CellRendererText()
        combo.pack_start(renderer_text, True)
        combo.add_attribute(renderer_text, "text", 0)
        combo.set_entry_text_column(0)
        combo.set_active(index)
        return liststore

    def on_text_atr_edited(self, widget, path, text):
        self.udev_rule_liststore[path][1] = text

    def on_text_val_edited(self, widget, path, text):
        self.udev_rule_liststore[path][3] = text

    def on_udev_rule_combo_liststore_changed(self, widget, path, text):
        self.udev_rule_liststore[path][0] = text

    def on_combo_user_right_changed(self, widget, path, text):
        self.liststore_users_auth[path][2] = text

    def on_combo_group_right_changed(self, widget, path, text):
        self.liststore_groups_auth[path][2] = text

    def on_close_device_window_button_clicked(self, button):
        self.window.destroy()

    def on_save_udev_button_clicked(self, button):
        udev_name = self.udev_path.split(".rules")[0].split("/")[-1].split("-")
        win = InfoClass()
        if len(self.udev_rule_liststore) == 0:
            win.print_error(_("Add permission attributes"))
        else:
            error_flag = False
            for item in self.udev_rule_liststore:
                if item[1] == "" or item[3] == "":
                    error_flag = True
                    break
            if not error_flag:
                with open(self.udev_path, "r") as f:
                    file = f.readlines()
                    if file[-1] == "":
                        file = file[:-1]
                    if len(file) > 7:
                        if 'LABEL="dont_remove_usb"' in file[-3]:
                            end = file[-4:]
                        elif 'LABEL="dont_remove_usb"' in file[-6]:
                            end = file[-7:]
                        elif 'LABEL="dont_remove_usb"' in file[-1]:
                            end = file[-2:]
                    elif 'LABEL="dont_remove_usb"' in file[-1]:
                        end = file[-2:]
                    start = file[:3]

                if self.user_binding_checkbox.get_active():
                    self.json_creation("/usr/share/ubl-udevrules/userlists/list-udev.json", "userlists", self.liststore_users_auth)
                    self.json_creation("/usr/share/ubl-udevrules/grouplists/list-udev.json", "grouplists",
                                       self.liststore_groups_auth)
                    tree_iter = self.other_users_combobox.get_active_iter()
                    if tree_iter is not None:
                        model = self.other_users_combobox.get_model()
                        value = model[tree_iter][0]
                    self.json_creation("/usr/share/ubl-udevrules/otherlists/list-udev.json", "otherlists", value)
                    if len(udev_name) == 2:
                        if len(end) == 2 or len(end) == 3 or len(end) == 4 or len(end) == 6:
                            end.append("ENV{DRIVER}==\"usb-storage\", ENV{UDISKS_AUTO}=\"0\"\n")
                            end.append("KERNEL==\"sd[a-z][0-9]\", SUBSYSTEMS==\"usb\", ACTION==\"add\", "
                                       "RUN+=\"/bin/sh -c 'echo %E{DEVPATH} > "
                                       f"/usr/share/ubl-udevrules/devpathes/{udev_name[1]}_%k\'\"\n")
                            end.append("KERNEL==\"sd[a-z][0-9]\", SUBSYSTEMS==\"usb\", ACTION==\"add\", "
                                       "RUN+=\"/bin/systemctl start usb-mount@%k.service\"\n")

                            end.append("KERNEL==\"sd[a-z][0-9]\", SUBSYSTEMS==\"usb\", ACTION==\"remove\", "
                                       "RUN+=\"/bin/sh -c 'echo %E{DEVPATH} > "
                                       f"/usr/share/ubl-udevrules/devpathes/{udev_name[1]}_%k\'\"\n")
                            end.append("KERNEL==\"sd[a-z][0-9]\", SUBSYSTEMS==\"usb\", ACTION==\"remove\", "
                                       "RUN+=\"/bin/systemctl stop usb-mount@%k.service\"\n")
                    elif len(udev_name) > 2:
                        end.append("ENV{DRIVER}==\"usb-storage\", ENV{UDISKS_AUTO}=\"0\"\n")
                        end.append("KERNEL==\"sd[a-z][0-9]\", SUBSYSTEMS==\"usb\", ACTION==\"add\", "
                                   "RUN+=\"/bin/sh -c 'echo %E{DEVPATH} > "
                                   f"/usr/share/ubl-udevrules/devpathes/{udev_name[1]}_%k\'\"\n")
                        end.append(f"KERNEL==\"sd[a-z][0-9]\", SUBSYSTEMS==\"usb\", ACTION==\"add\", "
                                   f"RUN+=\"/bin/systemctl start usb-mount{udev_name[2]}@%k.service\"\n")

                        end.append("KERNEL==\"sd[a-z][0-9]\", SUBSYSTEMS==\"usb\", ACTION==\"remove\", "
                                   "RUN+=\"/bin/sh -c 'echo %E{DEVPATH} > "
                                   f"/usr/share/ubl-udevrules/devpathes/{udev_name[1]}_%k\'\"\n")
                        end.append(f"KERNEL==\"sd[a-z][0-9]\", SUBSYSTEMS==\"usb\", ACTION==\"remove\", "
                                   f"RUN+=\"/bin/systemctl stop usb-mount{udev_name[2]}@%k.service\"\n")
                else:
                    users_flag = False
                    for line in end:
                        if "KERNEL==\"sd[a-z][0-9]\"" in line:
                            users_flag = True
                            break
                    if users_flag:
                        end = end[:-5]
                with open(self.udev_path, "w") as f:
                    # with open(self.udev_path.split("/")[-1], "w") as f:
                    for line in start:
                        f.write(line)
                    for item in self.udev_rule_liststore:
                        f.write(f"{item[0]}" + "{" + f"{item[1]}" + "}" + f"{item[2]}\"{item[3]}\", GOTO=\"dont_remove_usb\"\n")
                    f.write("")
                    for line in end:
                        f.write(line)

                if self.user_binding_checkbox.get_active():
                    print("active")
                    os.system('sed -i \'s|ATTR{authorized}="0"|RUN+="/bin/python3 /usr/share/ubl-udevrules/remove_usb.py '
                              '$devpath"|g\' ' + self.udev_path)
                else:
                    os.system('sed -i \'s|RUN+="/bin/python3 /usr/share/ubl-udevrules/remove_usb.py '
                          '$devpath"|ATTR{authorized}="0"|g\' ' + self.udev_path)
                service_text = f"""[Unit]
Description=Mount USB Drive on %i
[Service]
RemainAfterExit=true
Type=oneshot
ExecStart=/usr/bin/python3 /usr/share/ubl-udevrules/usb-mount.py add %i {self.udev_path}
ExecStop=/usr/bin/python3 /usr/share/ubl-udevrules/usb-mount.py remove %i {self.udev_path}
"""
                if len(udev_name) > 2:
                    with open(f"/etc/systemd/system/usb-mount{udev_name[2]}@.service", "w") as f:
                        for line in service_text:
                            f.write(line)
                elif len(udev_name) == 2:
                    with open(f"/etc/systemd/system/usb-mount@.service", "w") as f:
                        for line in service_text:
                            f.write(line)

                os.system("systemctl daemon-reload")
                os.system("udevadm control --reload")
            else:
                win.print_error(_("Some permission attributes are empty"))
    def json_creation(self, json_path, type, values):
        data = {}
        with open(json_path) as json_file:
            data = json.load(json_file)
            udev_name = self.udev_path.split(".rules")[0].split("/")[-1]
            if not data:
                data = {f"{self.udev_path}": f"/usr/share/ubl-udevrules/{type}/{udev_name}.json"}
            else:
                if not f"{self.udev_path}" in data.keys():
                    data[f"{self.udev_path}"] = f"/usr/share/ubl-udevrules/{type}/{udev_name}.json"

        with open(f'/usr/share/ubl-udevrules/{type}/list-udev.json', "w") as json_main_file:
            json.dump(data, json_main_file)

        with open(f'/usr/share/ubl-udevrules/{type}/list-udev.json') as json_main_file:
            data = json.load(json_main_file)
            with open(data[f"{self.udev_path}"], "w") as json_list_file:
                output = {}
                if values.__class__ is not str:
                    for item in values:
                        if item[1]:
                            if item[2] == _("All"):
                                umask = 0
                            elif item[2] == _("Read, Write"):
                                umask = 0
                            elif item[2] == _("Read"):
                                umask = 2
                            elif item[2] == _("No rights"):
                                umask = 7
                            output[item[0]] = umask
                else:
                    if values == _("All"):
                        umask = 0
                    elif values == _("Read, Write"):
                        umask = 0
                    elif values == _("Read"):
                        umask = 2
                    elif values == _("No rights"):
                        umask = 7
                    output["others"] = umask
                json.dump(output, json_list_file)

    def on_add_attr_button_clicked(self, button):
        self.udev_rule_liststore.append(["ATTRS", "", "==", ""])

    def on_remove_attr_button_clicked(self, button):
        try:
            (model, iter) = self.udev_line_selection.get_selected()
            self.udev_rule_liststore.remove(iter)
            self.udev_line_selection.unselect_all()
        except Exception as e:
            print(e)


class InfoClass(Gtk.Window):
    def __init__(self):
        Gtk.Window.__init__(self)
        box = Gtk.Box()
        self.add(box)
        self.liststore = []

    def print_error(self, error):
        dialog = Gtk.MessageDialog(parent=self, flags=0, message_type=Gtk.MessageType.ERROR,
                                   buttons=Gtk.ButtonsType.CANCEL, text="")
        text = _("<b>Error</b>")
        dialog.set_markup(text)
        dialogBox = dialog.get_content_area()
        dialog.set_resizable(True)
        dialog.set_size_request(300, 60)
        dialogBox.set_spacing(10)
        label = Gtk.Label()
        label.set_text(f"   {error}    ")
        dialogBox.pack_start(label, True, True, 0)
        dialog.show_all()
        dialog.run()
        dialog.destroy()

def main():
    win = InfoClass()
    if not os.geteuid() == 0:
        win.print_error(_('Available only for root user'))
    else:
        screen = Gdk.Screen.get_default()
        provider = Gtk.CssProvider()
        provider.load_from_path("/usr/share/ubl-udevrules/ui/style.css")
        #provider.load_from_path("ui/style.css")
        Gtk.StyleContext.add_provider_for_screen(screen, provider, Gtk.STYLE_PROVIDER_PRIORITY_APPLICATION)
        class_win = base()
        class_win.window.connect("destroy", Gtk.main_quit)
        Gtk.main()

if __name__ == "__main__":
    main()