#!/usr/bin/python3
"""
this script is a simple GUI for managing Wireguard Tunnels
"""
import gettext
import locale
import os
import shutil
import subprocess
import sys
import tkinter as tk
import webbrowser
from pathlib import Path
from subprocess import check_call
from tkinter import TclError, filedialog, ttk

from common_tools import (ConfigManager, ThemeManager, Create, GiteaUpdate, Tunnel, Tooltip, LxTools)
from wp_app_config import AppConfig, Msg

LxTools.uos()
Create.dir_and_files()
Create.make_dir()
Create.decrypt()

class Wirepy(tk.Tk):
    """
    Class Wirepy this is the Main Window of wirepy
    """
    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)

        # Hide the window initially
        self.withdraw()
        
        self.my_tool_tip = None
        self.x_width = AppConfig.UI_CONFIG["window_size"][0]
        self.y_height = AppConfig.UI_CONFIG["window_size"][1]
        
        # Set the window size
        self.geometry(f"{self.x_width}x{self.y_height}")
        self.resizable(AppConfig.UI_CONFIG["resizable_window"][0], 
                       AppConfig.UI_CONFIG["resizable_window"][1])
        self.title(AppConfig.UI_CONFIG["window_title"])
        
        self.columnconfigure(0, weight=1)
        self.rowconfigure(0, weight=1)
        self.tk.call("source", f"{AppConfig.SYSTEM_PATHS['tcl_path']}/water.tcl")
        ConfigManager.init(AppConfig.SETTINGS_FILE)
        theme = ConfigManager.get("theme")
        ThemeManager.change_theme(self, theme)

        # Load the image file from the disk
        self.wg_icon = tk.PhotoImage(file=AppConfig.IMAGE_PATHS["icon_vpn"])

        # Set it as the window icon
        self.iconphoto(True, self.wg_icon)

        # Add the widgets
        FrameWidgets(self).grid()
        
        # Center the window on the primary monitor
        LxTools.center_window_cross_platform(self, self.x_width, self.y_height)
        
        # Now show the window after it has been positioned
        self.after(10, self.deiconify)


class FrameWidgets(ttk.Frame):
    """
    ttk frame class for better structure
    """
    def __init__(self, container, **kwargs):
        super().__init__(container, **kwargs)
        
        self.lb_tunnel = None
        self.btn_stst = None
        self.endpoint = None
        self.dns = None
        self.address = None
        self.auto_con = None
        self.style = ttk.Style()
        self.wg_vpn_start = tk.PhotoImage(file=AppConfig.IMAGE_PATHS["icon_start"])
        self.wg_vpn_stop = tk.PhotoImage(file=AppConfig.IMAGE_PATHS["icon_stop"])
        self.imp_pic = tk.PhotoImage(file=AppConfig.IMAGE_PATHS["icon_import"])
        self.tr_pic = tk.PhotoImage(file=AppConfig.IMAGE_PATHS["icon_trash"])
        self.exp_pic = tk.PhotoImage(file=AppConfig.IMAGE_PATHS["icon_export"])
        self.warning_pic = tk.PhotoImage(file=AppConfig.IMAGE_PATHS["icon_error"])

        # StringVar-Variables initialization
        self.tooltip_state = tk.BooleanVar()
        # Get value from configuration
        state = ConfigManager.get("tooltips")
        # NOTE: ConfigManager.get("tooltips") can return either a boolean value or a string,
        # depending on whether the value was loaded from the file (bool) or the default value is used (string).
        # The expression 'lines[5].strip() == "True"' in ConfigManager.load() converts the string to a boolean.
        # Convert to boolean and set
        if isinstance(state, bool):
            # If it's already a boolean, use directly
            self.tooltip_state.set(state)
        else:
            # If it's a string or something else
            self.tooltip_state.set(str(state) == "True")
            
        self.tooltip_label = tk.StringVar() # StringVar-Variable for tooltip label for view Disabled/Enabled
        self.tooltip_update_label()
        self.update_label = tk.StringVar() # StringVar-Variable for update label
        self.update_tooltip = tk.StringVar() # StringVar-Variable for update tooltip please not remove!
        self.update_foreground = tk.StringVar(value="red")


        # Frame for Menu
        self.menu_frame = ttk.Frame(self)
        self.menu_frame.configure(relief="flat")
        self.menu_frame.grid(column=0, row=0, columnspan=4, sticky="w")

        # App Menu
        self.version_lb = ttk.Label(self.menu_frame, text=AppConfig.VERSION)
        self.version_lb.config(font=("Ubuntu", 11), foreground="#00c4ff")
        self.version_lb.grid(column=0, row=0, rowspan=4, padx=10)

        Tooltip(self.version_lb, f"Version: {AppConfig.VERSION[2:]}", self.tooltip_state) 

        self.options_btn = ttk.Menubutton(self.menu_frame, text=_("Options"))
        self.options_btn.grid(column=1, columnspan=1, row=0)

        Tooltip(self.options_btn, _("Click for Settings"), self.tooltip_state)

        self.set_update = tk.IntVar()
        self.settings = tk.Menu(self, relief="flat")
        self.options_btn.configure(menu=self.settings, style="Toolbutton")
        self.settings.add_checkbutton(label=_("Disable Updates"),
                                      command=lambda: self.update_setting(self.set_update.get()), variable=self.set_update)

        self.updates_lb = ttk.Label(self.menu_frame, textvariable=self.update_label)
        self.updates_lb.grid(column=4, columnspan=3, row=0, padx=10)
        self.updates_lb.grid_remove()
        self.update_label.trace_add("write", self.update_label_display)
        self.update_foreground.trace_add("write", self.update_label_display)
        res = GiteaUpdate.api_down(AppConfig.UPDATE_URL, AppConfig.VERSION, ConfigManager.get("updates"))
        self.update_ui_for_update(res)

        # Tooltip Menu
        self.settings.add_command(label=self.tooltip_label.get(), command=self.tooltips_toggle)
        # Label show dark or light  
        self.theme_label = tk.StringVar()
        self.update_theme_label()                           
        self.settings.add_command(label=self.theme_label.get(), command=self.on_theme_toggle)

        # About BTN Menu / Label
        self.about_btn = ttk.Button(
        self.menu_frame, text=_("About"), style="Toolbutton", command=self.about)
        self.about_btn.grid(column=2, columnspan=2, row=0)
        self.readme = tk.Menu(self)

        self.a = Tunnel.active()

        # Label Frame 1
        self.lb_frame_btn_lbox = ttk.Frame(self)
        self.lb_frame_btn_lbox.configure(relief="flat")
        self.lb_frame_btn_lbox.grid(column=0, rowspan=3, row=1)

        # Label Frame 2
        self.lb_frame = ttk.Frame(self)
        self.lb_frame.configure(relief="solid")
        self.lb_frame.grid(column=2, row=2, sticky="snew", padx=20, pady=5)

        # Label Frame 3
        self.lb_frame2 = ttk.Frame(self)
        self.lb_frame2.configure(relief="solid")
        self.lb_frame2.grid(column=2, row=3, sticky="snew", padx=20, pady=5)

        # Bottom Frame 4
        self.lb_frame3 = ttk.Frame(self)
        self.lb_frame3.configure(relief="flat")
        self.lb_frame3.grid(column=0, row=5, columnspan=4, sticky="snew", padx=2, pady=2)

        # Bottom Frame 5
        self.lb_frame4 = ttk.Frame(self)
        self.lb_frame4.configure(relief="flat")
        self.lb_frame4.grid(column=2, row=5, columnspan=3, sticky="e", padx=15)

        # Show active Label
        self.select_tunnel = None
        self.lb = ttk.Label(self, text=_("Active: "))
        self.lb.config(font=("Ubuntu", 11, "bold"))
        self.lb.grid(column=2, row=1, padx=15, pady=4, sticky="w")

        # Label to Show active Tunnel
        self.str_var = tk.StringVar(value=self.a)
        self.color_label()

        # Interface Label
        self.interface = ttk.Label(self.lb_frame, text=_("Interface"))
        self.interface.grid(column=0, row=3, sticky="we", padx=120)
        self.interface.config(font=("Ubuntu", 9))

        # Peer Label
        self.peer = ttk.Label(self.lb_frame2, text=_("Peer"))
        self.peer.config(font=("Ubuntu", 9))
        self.peer.grid(column=0, row=4, sticky="we", padx=130)

        # Listbox with Scrollbar
        self.l_box = tk.Listbox(self.lb_frame_btn_lbox, selectmode="single")
        self.l_box.config(relief="ridge", font=("Ubuntu", 12, "bold"))
        self.l_box.grid(column=1, rowspan=4, row=0, sticky="ns")
        self.l_box.event_add("<<ClickEvent>>", "<Button-1>")
        self.l_box.bind("<<ClickEvent>>", self.enable_check_box)
        self.scrollbar = ttk.Scrollbar(self.lb_frame_btn_lbox, orient="vertical", command=self.l_box.yview)
        self.scrollbar.grid(column=1, rowspan=4, row=0, sticky="nse")
        self.l_box.configure(yscrollcommand=self.scrollbar.set)

        # Tunnel List
        self.tl = LxTools.get_file_name(AppConfig.TEMP_DIR)
        for tunnels in self.tl:
            self.l_box.insert("end", tunnels)
            self.l_box.update()

        # Button Vpn
        if self.a != "":
            self.stop()
            data = self.handle_tunnel_data(self.a)
        else:
            self.start()

            # Address Label
            self.add = tk.StringVar()
            self.DNS = tk.StringVar()
            self.enp = tk.StringVar()
            self.reset_fields()
            self.show_data()

        # Button Import
        self.btn_i = ttk.Button(self.lb_frame_btn_lbox, image=self.imp_pic, command=self.import_sl, padding=0)
        self.btn_i.grid(column=0, row=1, padx=15, pady=8)

        Tooltip(self.btn_i, _("Click to import a Wireguard Tunnel"), self.tooltip_state)

        # Button Trash
        self.btn_tr = ttk.Button(self.lb_frame_btn_lbox, image=self.tr_pic, command=self.delete, padding=0,
                                 style="CButton.TButton")
        self.btn_tr.grid(column=0, row=2, padx=15, pady=8)

        if self.l_box.size() == 0:
            Tooltip(self.btn_tr, _("No tunnels to delete in the list"), self.tooltip_state)
        else:
            Tooltip(self.btn_tr, _("Click to delete a Wireguard Tunnel\nSelect from the list!"), self.tooltip_state)

        # Button Export
        self.btn_exp = ttk.Button(self.lb_frame_btn_lbox, image=self.exp_pic,
                                  command=lambda: Tunnel.export(AppConfig.IMAGE_PATHS["icon_info"], 
                                  AppConfig.IMAGE_PATHS["icon_vpn"], AppConfig.IMAGE_PATHS["icon_error"], 
                                  AppConfig.IMAGE_PATHS["icon_msg"],
                                  Msg.STR["sel_tl"], Msg.STR["tl_first"]), padding=0)
                                  
        self.btn_exp.grid(column=0, row=3, padx=15, pady=8)

        if self.l_box.size() == 0:
            Tooltip(self.btn_exp, _("No Tunnels in List for Export"), self.tooltip_state)
        else:
            Tooltip(self.btn_exp, _("Click to export all\nWireguard Tunnel to Zipfile"), self.tooltip_state)

        # Label Entry
        self.lb_rename = ttk.Entry(self.lb_frame4, width=20)
        self.lb_rename.grid(column=2, row=0, padx=8, pady=10, sticky="ne")
        self.lb_rename.insert(0, _("Max. 12 characters!"))
        self.lb_rename.config(state="disable")

        if self.l_box.size() != 0:
            Tooltip(self.lb_rename, _("To rename a tunnel, you need to\nselect a tunnel from the list"), self.tooltip_state)
        else:
            Tooltip(self.lb_rename, _("To rename a tunnel, at least one must be in the list"), self.tooltip_state)

        # Button Rename
        self.btn_rename = ttk.Button(self.lb_frame4, text=_("Rename"), state="disable", command=self.tl_rename,
                                     padding=4, style="RnButton.TButton")
        self.btn_rename.grid(column=3, row=0, padx=5, pady=10, sticky="ne")

        # Check Buttons
        self.selected_option = tk.IntVar()
        self.autoconnect_var = tk.StringVar()
        self.autoconnect_var.set(f"{self.auto_con}")

        # Frame for Labels, Entry and Button
        self.autoconnect = ttk.Label(self.lb_frame3, textvariable=self.autoconnect_var, width=15)
        self.autoconnect.config(font=("Ubuntu", 11))
        self.autoconnect.grid(column=1, row=0, sticky="e", pady=19)
        self.wg_autostart = ttk.Checkbutton(self.lb_frame3, text=_("Autoconnect on:"), variable=self.selected_option,
                                            command=self.box_set)
        self.wg_autostart.grid(column=0, row=0, pady=15, padx=15, sticky="nw")

        if self.l_box.size() >= 1 and len(self.l_box.curselection()) >= 1:
            Tooltip(self.wg_autostart, Msg.TTIP["autostart"], self.tooltip_state)

        if self.l_box.size() == 0:
            Tooltip(self.wg_autostart, Msg.TTIP["autostart_info"], self.tooltip_state)

        else:

            Tooltip(self.wg_autostart, Msg.TTIP["autostart"], self.tooltip_state)

        self.on_off()

    # Method that is called when the variable changes
    def update_label_display(self, *args):
        # Set the foreground color
        self.updates_lb.configure(foreground=self.update_foreground.get())

        # Show or hide the label based on whether it contains text
        if self.update_label.get():
            # Make sure the label is in the correct position every time it's shown
            self.updates_lb.grid(column=4, columnspan=3, row=0, padx=10)
        else:
            self.updates_lb.grid_remove()

    # Update the labels based on the result
    def update_ui_for_update(self, res):
        """Update UI elements based on update check result"""
        # First, remove the update button if it exists to avoid conflicts
        if hasattr(self, 'update_btn'):
            self.update_btn.grid_forget()
            delattr(self, 'update_btn')
        
        if res == "False":
            self.set_update.set(value=1)
            self.update_label.set(_("Update search off"))
            self.update_tooltip.set(_("Updates you have disabled"))
            # Clear the foreground color as requested
            self.update_foreground.set("")
            
        elif res == "No Internet Connection!":
            self.update_label.set(_("No Server Connection!"))
            self.update_foreground.set("red")
            
        elif res == "No Updates":
            self.update_label.set(_("No Updates"))
            self.update_tooltip.set(_("Congratulations! Wire-Py is up to date"))
            self.update_foreground.set("")
            
        else:
            self.set_update.set(value=0)
            update_text = f"Update {res} {_('available!')}"

            # Clear the label text since we'll show the button instead
            self.update_label.set("")
            
            # Create the update button
            self.update_btn = ttk.Menubutton(self.menu_frame, text=update_text)
            self.update_btn.grid(column=4, columnspan=3, row=0, padx=0)
            Tooltip(self.update_btn, _("Click to download new version"), self.tooltip_state)
            
            self.download = tk.Menu(self, relief="flat")
            self.update_btn.configure(menu=self.download, style="Toolbutton")
            self.download.add_command(
                label=_("Download"),
                command=lambda: GiteaUpdate.download(
                    f"{AppConfig.DOWNLOAD_URL}/{res}.zip",
                    res, 
                    AppConfig.IMAGE_PATHS["icon_info"],
                    AppConfig.IMAGE_PATHS["icon_vpn"],
                    AppConfig.IMAGE_PATHS["icon_error"],
                    AppConfig.IMAGE_PATHS["icon_msg"]
                )
            )

    @staticmethod
    def about() -> None:
        """
        a tk.Toplevel window
        """
        def link_btn() -> str | None:
            webbrowser.open("https://git.ilunix.de/punix/Wire-Py")

        msg_t = _("Wire-Py a simple Wireguard Gui for Linux systems.\n\n"
                "Wire-Py is open source software written in Python.\n\n"
                "Email: polunga40@unity-mail.de also likes for donation.\n\n"
                "Use without warranty!\n")

        LxTools.msg_window(AppConfig.IMAGE_PATHS["icon_vpn"], AppConfig.IMAGE_PATHS["icon_vpn"], _("Info"), msg_t, _("Go to Wire-Py git"), link_btn)
    def update_setting(self, update_res) -> None:
        """write off or on in file
        Args:
            update_res (int): argument that is passed contains 0 or 1
        """
        if update_res == 1:
            # Disable updates
            ConfigManager.set("updates", "off")
            # When updates are disabled, we know the result should be "False"
            self.update_ui_for_update("False")
        else:
            # Enable updates
            ConfigManager.set("updates", "on")
            # When enabling updates, we need to actually check for updates
            try:
                # Force a fresh check by passing "on" as the update setting
                res = GiteaUpdate.api_down(AppConfig.UPDATE_URL, AppConfig.VERSION, "on")
                
                # Make sure UI is updated regardless of previous state
                if hasattr(self, 'update_btn'):
                    self.update_btn.grid_forget()
                if hasattr(self, 'updates_lb'):
                    self.updates_lb.grid_forget()
                    
                # Now update the UI with the fresh result
                self.update_ui_for_update(res)
            except Exception as e:
                print(f"Error checking for updates: {e}")
                # Fallback to a default message if there's an error
                self.update_ui_for_update("No Internet Connection!")

    def tooltip_update_label(self) -> None:
        """Updates the tooltip menu label based on the current tooltip status"""
        # Set the menu text based on the current status
        if self.tooltip_state.get():
            # If tooltips are enabled, the menu option should be to disable them
            self.tooltip_label.set(_("Disable Tooltips"))
        else:
            # If tooltips are disabled, the menu option should be to enable them
            self.tooltip_label.set(_("Enable Tooltips"))

    def tooltips_toggle(self):
        """Toggles tooltips on/off and updates the menu label"""
        # Toggle the boolean state
        new_bool_state = not self.tooltip_state.get()
        # Save the converted value in the configuration
        ConfigManager.set("tooltips", str(new_bool_state))
        # Update the tooltip_state variable for immediate effect
        self.tooltip_state.set(new_bool_state)
        
        # Update the menu label
        self.tooltip_update_label()
        
        # Update the menu entry - find the correct index
        # This assumes it's the third item (index 2) in your menu
        self.settings.entryconfigure(1, label=self.tooltip_label.get())

    def update_theme_label(self) -> str:
        """Update the theme label based on current theme"""
        current_theme = ConfigManager.get("theme")
        if current_theme == "light":
            self.theme_label.set(_("Dark"))
        else:
            self.theme_label.set(_("Light"))

    def on_theme_toggle(self) -> None:
        """Toggle between light and dark theme"""
        current_theme = ConfigManager.get("theme")
        new_theme = "dark" if current_theme == "light" else "light"
        ThemeManager.change_theme(self, new_theme, new_theme)
        self.color_label()
        self.update_theme_label()  # Update the theme label
        # Update Menulfield
        self.settings.entryconfigure(2, label=self.theme_label.get())

    def start(self) -> None:
        """
        Start Button
        """
        self.btn_stst = ttk.Button(self.lb_frame_btn_lbox, image=self.wg_vpn_start, 
                                   command=lambda: self.wg_switch("start"), padding=0)
        self.btn_stst.grid(column=0, row=0, padx=5, pady=8)

        tl = LxTools.get_file_name(AppConfig.TEMP_DIR)
        if len(self.tl) == 0:
            Tooltip(self.btn_stst, Msg.TTIP["empty_list"], self.tooltip_state)
        else:
            Tooltip(self.btn_stst, Msg.TTIP["start_tl"], self.tooltip_state)

    def handle_tunnel_data(self, tunnel_name: str) -> tuple[str, str, str, str | None]:
        """_summary_

        Args:
            tunnel_name (str): name of a tunnel

        Returns:
            tuple[str, str]: tuple with tunnel data
        """
        wg_read = f"/tmp/tlecdcwg/{tunnel_name}.conf"
        with open(wg_read, "r", encoding="utf-8") as file:
            data = Tunnel.con_to_dict(file)
            self.init_and_report(data)
            self.show_data()
            return data

    def color_label(self) -> None:
        """
        View activ Tunnel in the color green or yellow
        """
        if  ConfigManager.get("theme") == "light":
            
            self.lb_tunnel = ttk.Label(self, textvariable=self.str_var, foreground="green")

        else:
            self.lb_tunnel = ttk.Label(self, textvariable=self.str_var, foreground="yellow")

        self.lb_tunnel.config(font=("Ubuntu", 11, "bold"))
        self.lb_tunnel.grid(column=2, padx=10, row=1)

    def stop(self) -> None:
        """
        Stop Button
        """
        self.btn_stst = ttk.Button(self.lb_frame_btn_lbox, image=self.wg_vpn_stop, 
                                   command=lambda: self.wg_switch("stop"), padding=0)
        self.btn_stst.grid(column=0, row=0, padx=5, pady=8)

        Tooltip(self.btn_stst, Msg.TTIP["stop_tl"], self.tooltip_state)

    def reset_fields(self) -> None:
        """
        reset data from labels
        """
        fields = [self.add, self.DNS, self.enp]
        for field in fields:
            field.set("")

    def import_sl(self) -> None:
        """validity check of wireguard config files"""

        Create.dir_and_files()
        try:
            filepath = filedialog.askopenfilename(
                initialdir=f"{Path.home()}", 
                title=_("Select Wireguard config File"),
                filetypes=[(_("WG config files"), "*.conf")]
            )
            
            # Überprüfe, ob der Benutzer den Dialog abgebrochen hat
            if not filepath:
                print("File import: abort by user...")
                return
                
            with open(filepath, "r", encoding="utf-8") as file:
                read = file.read()
            
            path_split = filepath.split("/")
            path_split1 = path_split[-1]
            
            if "PrivateKey = " in read and "PublicKey = " in read and "Endpoint =" in read:
                with open(filepath, "r", encoding="utf-8") as file:
                    key = Tunnel.con_to_dict(file)
                pre_key = key[3]
                
                if len(pre_key) != 0:
                    p_key = AppConfig.KEYS_FILE.read_text(encoding="utf-8")
                    
                    if pre_key in p_key or f"{pre_key}\n" in p_key:
                        LxTools.msg_window(AppConfig.IMAGE_PATHS["icon_error"], AppConfig.IMAGE_PATHS["icon_msg"], Msg.STR["imp_err"], Msg.STR["tl_exist"])
                    else:
                        with open(AppConfig.KEYS_FILE, "a", encoding="utf-8") as keyfile:
                            keyfile.write(f"{pre_key}\r")
                        
                        if len(path_split1) > 17:
                            p1 = shutil.copy(filepath, AppConfig.TEMP_DIR)
                            path_split = path_split1[len(path_split1) - 17:]
                            os.rename(p1, f"{AppConfig.TEMP_DIR}/{path_split}")
                            new_conf = f"{AppConfig.TEMP_DIR}/{path_split}"
                            
                            if self.a != "":
                                check_call(["nmcli", "connection", "down", self.a])
                                self.reset_fields()
                            
                            subprocess.check_output(["nmcli", "connection", "import", "type", "wireguard", "file", new_conf], text=True)
                            Create.encrypt()
                        else:
                            shutil.copy(filepath, f"{AppConfig.TEMP_DIR}/")
                            
                            if self.a != "":
                                check_call(["nmcli", "connection", "down", self.a])
                                self.reset_fields()
                            
                            subprocess.check_output(["nmcli", "connection", "import", "type", "wireguard", "file", filepath], text=True)
                            Create.encrypt()
                        
                        self.str_var.set("")
                        self.a = Tunnel.active()
                        self.l_box.insert(0, self.a)
                        self.wg_autostart.configure(state="normal")
                        self.l_box.selection_clear(0, tk.END)
                        self.l_box.update()
                        self.l_box.selection_set(0)
                        
                        Tooltip(self.wg_autostart, Msg.TTIP["autostart"], self.tooltip_state)
                        Tooltip(self.btn_tr, Msg.TTIP["trash_tl"], self.tooltip_state)
                        Tooltip(self.btn_exp, Msg.TTIP["export_tl"], self.tooltip_state)
                        Tooltip(self.btn_rename, Msg.TTIP["rename_tl"], self.tooltip_state)
                        
                        self.lb_rename.insert(0, "Max. 12 characters!")
                        self.str_var = tk.StringVar()
                        self.str_var.set(self.a)
                        self.color_label()
                        self.stop()
                        data = self.handle_tunnel_data(self.a)
                        check_call(["nmcli", "con", "mod", self.a, "connection.autoconnect", "no"])
            elif ("PrivateKey = " in read) and ("Endpoint = " in read):
                pass
            else:
                LxTools.msg_window(AppConfig.IMAGE_PATHS["icon_error"], AppConfig.IMAGE_PATHS["icon_msg"], Msg.STR["imp_err"], Msg.STR["no_valid_file"])

        except EOFError as e:
            print(e)
        except TypeError:
            print("File import: abort by user...")
        except FileNotFoundError:
            print("File import: abort by user...")
        except subprocess.CalledProcessError:
            print("Tunnel exist!")

    def delete(self) -> None:
        """
        delete Wireguard Tunnel
        """
        try:
            self.select_tunnel = self.l_box.curselection()
            select_tl = self.l_box.get(self.select_tunnel[0])
            with open(f"/tmp/tlecdcwg/{select_tl}.conf", "r+", encoding="utf-8") as file2:
                key = Tunnel.con_to_dict(file2)
                pre_key = key[3]
            check_call(["nmcli", "connection", "delete", select_tl])
            self.l_box.delete(self.select_tunnel[0])
            with open(AppConfig.SETTINGS_FILE, "r", encoding="utf-8") as set_f6:
                lines6 = set_f6.readlines()
                if (select_tl == lines6[7].strip()
                    and "off\n" not in lines6[7].strip()):
                    lines6[7] = "off\n"
                    with open(AppConfig.SETTINGS_FILE, "w", encoding="utf-8") as set_f7:
                        set_f7.writelines(lines6)
                    self.selected_option.set(0)
                    self.autoconnect_var.set(_("no Autoconnect"))
            is_encrypt = Path.home() / f".config/wire_py/{select_tl}.dat"
            if is_encrypt.is_file():
                Path.unlink(f"{Path.home()}/.config/wire_py/{select_tl}.dat")
            Path.unlink(f"/tmp/tlecdcwg/{select_tl}.conf")
            with open(AppConfig.KEYS_FILE, "r", encoding="utf-8") as readfile:
                with open(f"{Path.home()}/.config/wire_py/keys2", "w", encoding="utf-8") as writefile:
                    for line in readfile:
                        if pre_key not in line.strip("\n"):
                            writefile.write(line)
            file_one = Path(f"{Path.home()}/.config/wire_py/keys2")
            file_two = file_one.with_name("keys")
            file_one.replace(file_two)
            self.wg_autostart.configure(state="disabled")

            # for disabling checkbox when Listbox empty
            if self.l_box.size() == 0:
                self.wg_autostart.configure(state="disabled")
                self.lb_rename.configure(state="disabled")
                Tooltip(self.wg_autostart, _("You must have at least one\ntunnel in the list,to use the autostart")
                        , self.tooltip_state)

                Tooltip(self.btn_exp, _("No Tunnels in List for Export"), self.tooltip_state)
                Tooltip(self.btn_stst, _("No tunnels to start in the list"), self.tooltip_state)
                Tooltip(self.lb_rename, _("To rename a tunnel, at least one must be in the list"), self.tooltip_state)
                self.lb_rename.insert(0, _("Max. 12 characters!"))

            if self.a != "" and self.a == select_tl:
                self.str_var.set(value="")
                self.start()
                self.l_box.update()
                self.reset_fields()

        except IndexError:

            if self.l_box.size() != 0:

                LxTools.msg_window(AppConfig.IMAGE_PATHS["icon_info"], AppConfig.IMAGE_PATHS["icon_msg"], Msg.STR["sel_tl"], Msg.STR["sel_list"])

            else:

                LxTools.msg_window(AppConfig.IMAGE_PATHS["icon_info"], AppConfig.IMAGE_PATHS["icon_msg"], Msg.STR["sel_tl"], Msg.STR["tl_first"])

    def enable_check_box(self, _) -> None:
        """
        checkbox for enable autostart Tunnel
        """
        Create.files_for_autostart()
        if self.l_box.size() != 0:
            self.wg_autostart.configure(state="normal")
            self.lb_rename.config(state="normal")
            self.lb_rename.delete(0, tk.END)
            self.btn_rename.config(state="normal")

    def on_off(self) -> None:
        """
        Here it is checked whether the path to the file is there, if not, it is created.
        Set (on), the selected tunnel is displayed in the label.
        At (off) the label is first emptied then filled with No Autoconnect
        """
        lines = Path(AppConfig.SETTINGS_FILE).read_text(encoding="utf-8").splitlines(keepends=True)

        if lines[7] != "off\n":
            print(f"{lines[7]} starts automatically when the system starts.")
            self.selected_option.set(1)
            self.autoconnect_var.set("")
            self.auto_con = lines[7]

        else:
            self.selected_option.set(0)
            self.auto_con = _("no Autoconnect")
            print("Autostart disabled.")
        self.autoconnect_var.set("")
        self.autoconnect_var = tk.StringVar()
        self.autoconnect_var.set(self.auto_con)

        self.autoconnect = ttk.Label(self.lb_frame3, textvariable=self.autoconnect_var, foreground="#0071ff", width=15)
        self.autoconnect.config(font=("Ubuntu", 11))
        self.autoconnect.grid(column=1, row=0, sticky="e", pady=19)

    def box_set(self) -> None:
        """
        Configures the autostart for a selected tunnel.

        This method is called when the user changes the autostart checkbox.
        It saves the selected tunnel in the configuration file so that it
        will be automatically connected at system startup.

        If the checkbox is deactivated, 'off' is written to the configuration file
        to disable the autostart.
        """
        try:
            select_tunnel = self.l_box.curselection()
            select_tl = self.l_box.get(select_tunnel[0])

            if self.selected_option.get() == 0:
                lines = Path(AppConfig.SETTINGS_FILE).read_text(encoding="utf-8").splitlines(keepends=True)
                lines[7] = 'off\n' 
                Path(AppConfig.SETTINGS_FILE).write_text(''.join(lines), encoding="utf-8")

                tl = LxTools.get_file_name(AppConfig.TEMP_DIR)

                if len(tl) == 0:
                    self.wg_autostart.configure(state="disabled")

            if self.selected_option.get() >= 1:
                lines = Path(AppConfig.SETTINGS_FILE).read_text(encoding="utf-8").splitlines(keepends=True)
                lines[7] = select_tl
                Path(AppConfig.SETTINGS_FILE).write_text(''.join(lines), encoding="utf-8")

        except IndexError:
            self.selected_option.set(1)

        self.on_off()

    def tl_rename(self) -> None:
        """
        method to rename a tunnel
        """
        name_of_file = LxTools.get_file_name(AppConfig.TEMP_DIR)
        special_characters = ["\\", "/", "{", "}", " "]

        if len(self.lb_rename.get()) > 12:

            LxTools.msg_window(AppConfig.IMAGE_PATHS["icon_info"], AppConfig.IMAGE_PATHS["icon_msg"], Msg.STR["ren_err"], Msg.STR["sign_len"])

        elif len(self.lb_rename.get()) == 0:

            LxTools.msg_window(AppConfig.IMAGE_PATHS["icon_info"], AppConfig.IMAGE_PATHS["icon_msg"], Msg.STR["ren_err"], Msg.STR["zero_signs"])

        elif any(ch in special_characters for ch in self.lb_rename.get()):

            LxTools.msg_window(AppConfig.IMAGE_PATHS["icon_info"], AppConfig.IMAGE_PATHS["icon_msg"], Msg.STR["ren_err"], Msg.STR["false_signs"])

        elif self.lb_rename.get() in name_of_file:

            LxTools.msg_window(AppConfig.IMAGE_PATHS["icon_info"], AppConfig.IMAGE_PATHS["icon_msg"], Msg.STR["ren_err"], Msg.STR["is_in_use"])

        else:

            try:
                self.select_tunnel = self.l_box.curselection()
                select_tl = self.l_box.get(self.select_tunnel[0])

                # nmcli connection modify old connection.id iphone
                subprocess.check_output(["nmcli", "connection", "modify", select_tl, "connection.id", self.lb_rename.get()], text=True)
                source = Path(f"/tmp/tlecdcwg/{select_tl}.conf")
                destination = source.with_name(f"{self.lb_rename.get()}.conf")
                source.replace(destination)
                Path.unlink(f"{Path.home()}/.config/wire_py/{select_tl}.dat")

                self.l_box.delete(self.select_tunnel[0])
                self.l_box.insert("end", self.lb_rename.get())
                self.l_box.update()
                new_a_connect = self.lb_rename.get()
                self.lb_rename.delete(0, tk.END)
               
                with open(AppConfig.SETTINGS_FILE, "r", encoding="utf-8") as set_f5:
                    lines5 = set_f5.readlines()
                if select_tl == lines5[7].strip() and "off\n" not in lines5[7].strip():
                    lines5[7] = new_a_connect
                    with open(AppConfig.SETTINGS_FILE, "w", encoding="utf-8") as theme_set5:
                        theme_set5.writelines(lines5)
                    self.autoconnect_var.set(value=new_a_connect)
                self.update_connection_display()
                Create.encrypt()

            except IndexError:

                LxTools.msg_window(AppConfig.IMAGE_PATHS["icon_info"], AppConfig.IMAGE_PATHS["icon_msg"], Msg.STR["ren_err"], Msg.STR["sel_list"])

            except subprocess.CalledProcessError:
                pass

            except EOFError as e:
                print(e)
                  
    def init_and_report(self, data=None) -> None:
        """
        Displays the value address, DNS and peer in the labels
        or empty it again
        """
        # Address Label
        self.add = tk.StringVar()
        self.add.set(f"{_("Address:    ")}{data[0]}")
        self.DNS = tk.StringVar()
        self.DNS.set(f"       DNS:   {data[1]}")
        self.enp = tk.StringVar()
        self.enp.set(f"{_("Endpoint:    ")}{data[2]}")

    def show_data(self) -> None:
        """
        shows data in the label
        """
        # Address Label
        self.address = ttk.Label(self.lb_frame, textvariable=self.add, foreground="#0071ff")
        self.address.grid(column=0, row=5, sticky="w", padx=10, pady=6)
        self.address.config(font=("Ubuntu", 9))

        # DNS Label
        self.dns = ttk.Label(self.lb_frame, textvariable=self.DNS, foreground="#0071ff")
        self.dns.grid(column=0, row=7, sticky="w", padx=10, pady=6)
        self.dns.config(font=("Ubuntu", 9))

        # Endpoint Label
        self.endpoint = ttk.Label(self.lb_frame2, textvariable=self.enp, foreground="#0071ff")
        self.endpoint.grid(column=0, row=8, sticky="w", padx=10, pady=20)
        self.endpoint.config(font=("Ubuntu", 9))

    def wg_switch(self, event=None) -> None:
        """
        Deals with switching the VPN connection
        """
        try:
            if self.a == "":
                self.select_tunnel = self.l_box.curselection()
                select_tl = self.l_box.get(self.select_tunnel[0])
                self.handle_connection_state("start", select_tl)

            else:
                
                data = self.handle_tunnel_data(self.a)
                if data:

                    self.handle_connection_state("stop")

        except IndexError:

            if self.l_box.size() != 0:

                LxTools.msg_window(AppConfig.IMAGE_PATHS["icon_info"], AppConfig.IMAGE_PATHS["icon_msg"], Msg.STR["sel_tl"], Msg.STR["sel_list"])

            else:

                LxTools.msg_window(AppConfig.IMAGE_PATHS["icon_info"], AppConfig.IMAGE_PATHS["icon_msg"], Msg.STR["sel_tl"], Msg.STR["tl_first"])

    def handle_connection_state(self, action: str, tunnel_name: str = None) -> None:
        """
        central management for connection states

        Args:
            action (str): "start", "stop" or "toggle"
            tunnel_name (str, optional): name of a tunnel for a start-option. defaults to None.
        """
        if action == "stop":
            if self.a:
                check_call(["nmcli", "connection", "down", self.a])
                self.update_connection_display()
                self.reset_fields()
                self.start()

        elif action == "start":
            if tunnel_name or self.a:
                target_tunnel = tunnel_name or self.a
                check_call(["nmcli", "connection", "up", target_tunnel])
                self.update_connection_display()
                data = self.handle_tunnel_data(self.a)
                self.init_and_report(data)
                self.show_data()
                self.color_label()
                self.stop()

        elif action == "toggle":
            if self.a:
                self.handle_connection_state("stop")
            else:
                self.handle_connection_state("start")

    def update_connection_display(self) -> None:
        """
        Updated the display after connection changes
        """
        self.a = Tunnel.active()
        if not hasattr(self, "str_var"):
            self.str_var = tk.StringVar()
        self.str_var.set(self.a)
        self.color_label()
        self.show_data()


if __name__ == "__main__":

    _ = AppConfig.setup_translations()
    LxTools.sigi(AppConfig.TEMP_DIR, AppConfig.USER_FILE)
    window = Wirepy()
    """
    the hidden files are hidden in Filedialog
    """
    try:
        window.tk.call("tk_getOpenFile", "-foobarbaz")
    except TclError:
        pass
    window.tk.call("set", "::tk::dialog::file::showHiddenBtn", "0")
    window.tk.call("set", "::tk::dialog::file::showHiddenVar", "0")
    window.mainloop()

LxTools.clean_files(AppConfig.TEMP_DIR, AppConfig.USER_FILE)
sys.exit(0)