from gi.repository import Gtk, Adw, GLib, Gdk, Gio
from .common import myUtils
import subprocess
import os
import pathlib


@Gtk.Template(resource_path="/io/github/flattool/Warehouse/../data/ui/properties.ui")
class PropertiesWindow(Adw.Dialog):
    __gtype_name__ = "PropertiesWindow"

    new_env = dict(os.environ)
    new_env["LC_ALL"] = "C"
    host_home = str(pathlib.Path.home())
    user_data_path = host_home + "/.var/app/"

    toast_overlay = Gtk.Template.Child()
    upper = Gtk.Template.Child()
    app_icon = Gtk.Template.Child()
    data_row = Gtk.Template.Child()
    open_data = Gtk.Template.Child()
    trash_data = Gtk.Template.Child()
    spinner = Gtk.Template.Child()
    details = Gtk.Template.Child()
    view_apps = Gtk.Template.Child()
    runtime = Gtk.Template.Child()
    runtime_properties = Gtk.Template.Child()
    runtime_copy = Gtk.Template.Child()
    lower = Gtk.Template.Child()
    eol_app_banner = Gtk.Template.Child()
    eol_runtime_banner = Gtk.Template.Child()
    mask_banner = Gtk.Template.Child()
    name = Gtk.Template.Child()
    description = Gtk.Template.Child()
    description_button = Gtk.Template.Child()
    
    def copy_item(self, to_copy, to_toast=None):
        self.get_clipboard().set(to_copy)
        if to_toast:
            self.toast_overlay.add_toast(Adw.Toast.new(_("Copied {}").format(to_toast)))

    def open_button_handler(self, widget):
        try:
            Gio.AppInfo.launch_default_for_uri(f"file://{self.user_data_path}", None)
        except GLib.GError:
            self.toast_overlay.add_toast(Adw.Toast.new(_("Could not open folder")))

    def show_details(self, widget):
        try:
            Gio.AppInfo.launch_default_for_uri(f"appstream://{self.app_id}", None)
        except GLib.GError:
            self.toast_overlay.add_toast(Adw.Toast.new(_("Could not show details")))

    def get_size_callback(self, *args):
        self.open_data.set_visible(True)
        self.open_data.connect("clicked", self.open_button_handler)
        self.trash_data.set_visible(True)
        self.data_row.set_title(_("User Data"))
        self.data_row.set_subtitle(f"~{self.size}")
        self.spinner.set_visible(False)

    def get_size_thread(self, *args):
        self.size = self.my_utils.get_size_with_format(self.user_data_path)

    def generate_upper(self):
        self.description_button.connect(
            "clicked",
            lambda *_a: self.copy_item(
                self.description.get_label(), _("Description")
            )
        )
        image = self.my_utils.find_app_icon(self.app_id)
        self.runtime.set_subtitle(self.current_flatpak[13])
        if image.get_paintable() == None:
            self.app_icon.set_from_icon_name(image.get_icon_name())
        else:
            self.app_icon.set_from_paintable(image.get_paintable())

        if os.path.exists(self.user_data_path):
            task = Gio.Task.new(None, None, self.get_size_callback)
            task.run_in_thread(self.get_size_thread)
        else:
            self.data_row.set_title("")
            self.data_row.set_subtitle(_("No User Data"))
            self.spinner.set_visible(False)

        if "runtime" in self.current_flatpak[12]:
            # Pak is a runtime
            self.runtime.set_visible(False)
            if self.app_ref in self.parent_window.dependent_runtimes:
                self.view_apps.set_visible(True)

    def generate_lower(self):
        info = self.my_utils.get_flatpak_info(self.app_ref, self.install_type)
        name_desc = info["name"].split(" - ")
        self.name.set_label((name_desc[0]))
        try:
            self.description.set_label((name_desc[1]))
        except:
            pass
        for key in info.keys():
            if key == "name":
                continue
            row = Adw.ActionRow(
                title=GLib.markup_escape_text(key),
                subtitle=GLib.markup_escape_text(info[key]),
                activatable=True,
            )
            row.add_suffix(Gtk.Image.new_from_icon_name("edit-copy-symbolic"))
            row.add_css_class("property")
            row.connect(
                "activated",
                lambda *_a, row=row: self.copy_item(
                    row.get_subtitle(), row.get_title()
                ),
            )
            self.lower.add(row)

    def view_apps_handler(self, widget):
        settings = Gio.Settings.new("io.github.flattool.Warehouse.filter")
        for key in settings.list_keys():
            settings.reset(key)
        settings.set_string("runtimes-list", f"{self.app_ref},")
        self.parent_window.apply_filter()
        self.close()

    def show_properties_handler(self):
        runtime = self.current_flatpak[13]
        for i in range(len(self.host_flatpaks)):
            # open the properties when the flatpak matches the runtime *and* installation type
            if runtime in self.host_flatpaks[i][8] and self.install_type in self.host_flatpaks[i][12]:
                PropertiesWindow(i, self.host_flatpaks, self.parent_window)
                self.close()
                return
        self.toast_overlay.add_toast(Adw.Toast.new(_("Could not show properties")))

    def trash_data_handler(self):
        def on_response(_none, response, widget):
            if response == "cancel":
                return

            if self.my_utils.trash_folder(self.user_data_path) == 0:
                self.toast_overlay.add_toast(Adw.Toast.new(_("Trashed user data")))
                self.data_row.set_title(_("No User Data"))
                self.data_row.set_subtitle("")
                self.open_data.set_visible(False)
                self.trash_data.set_visible(False)
            else:
                self.toast_overlay.add_toast(
                    Adw.Toast.new(_("Could not trash user data"))
                )

        dialog = Adw.AlertDialog.new(
            _("Send {}'s User Data to the Trash?").format(self.app_name)
        )
        dialog.add_response("cancel", _("Cancel"))
        dialog.set_close_response("cancel")
        dialog.add_response("continue", _("Trash Data"))
        dialog.set_response_appearance("continue", Adw.ResponseAppearance.DESTRUCTIVE)
        dialog.connect("response", on_response, dialog.choose_finish)
        dialog.present(self)

    def __init__(self, flatpak_index, host_flatpaks, parent_window, **kwargs):
        super().__init__(**kwargs)
        self.my_utils = myUtils(self)
        self.current_flatpak = host_flatpaks[flatpak_index]
        self.parent_window = parent_window
        self.host_flatpaks = host_flatpaks
        self.flatpak_index = flatpak_index

        self.app_name = self.current_flatpak[0]
        self.app_id = self.current_flatpak[2]
        self.origin_remote = self.current_flatpak[6]
        self.install_type = self.current_flatpak[7]
        self.app_ref = self.current_flatpak[8]
        self.user_data_path += self.app_id

        self.details.connect("activated", self.show_details)
        self.runtime_copy.connect(
            "clicked",
            lambda *_: self.copy_item(
                self.runtime.get_subtitle(), self.runtime.get_title()
            ),
        )
        self.runtime_properties.connect(
            "clicked", lambda *_: self.show_properties_handler()
        )
        self.view_apps.connect("activated", self.view_apps_handler)
        self.trash_data.connect("clicked", lambda *_: self.trash_data_handler())

        if "eol" in self.current_flatpak[12]:
            self.eol_app_banner.set_revealed(True)
            self.eol_app_banner.set_title(
                _(
                    "{} has reached its End of Life and will not receive any security updates"
                ).format(self.app_name)
            )

        if self.current_flatpak[13] in parent_window.eol_list:
            self.eol_runtime_banner.set_revealed(True)
            self.eol_runtime_banner.set_title(
                _(
                    "{}'s runtime has reached its End of Life and will not receive any security updates"
                ).format(self.app_name)
            )

        if self.app_id in self.my_utils.get_host_masks(
            "system"
        ) or self.app_id in self.my_utils.get_host_masks("user"):
            self.mask_banner.set_revealed(True)
            self.mask_banner.set_title(
                _("{} is masked and will not be updated").format(self.app_name)
            )

        self.generate_upper()
        self.generate_lower()
        self.present(parent_window)
