from gi.repository import Adw, Gtk, GLib, Gio
from src.host_info import HostInfo
from src.gtk.error_toast import ErrorToast
import subprocess
import gettext

_ = gettext.gettext


@Gtk.Template(resource_path="/io/github/flattool/Warehouse/remotes_page/remote_row.ui")
class RemoteRow(Adw.ActionRow):
	__gtype_name__ = "RemoteRow"
	gtc = Gtk.Template.Child

	suffix_label = gtc()
	filter_button = gtc()
	menu_pop = gtc()
	menu_listbox = gtc()

	copy_title = gtc()
	copy_name = gtc()
	enable_remote = gtc()
	disable_remote = gtc()
	remove = gtc()

	def enable_remote_handler(self, *args):
		if not self.remote.disabled:
			self.parent_page.toast_overlay.add_toast(ErrorToast(_("Could not enable remote"), _("Remote is already enabled")).toast)
			return

		has_error = []

		def thread(*args):
			cmd = ["flatpak", "remote-modify", "--enable", self.remote.name]
			if self.installation == "user" or self.installation == "system":
				cmd.append(f"--{self.installation}")
			else:
				cmd.append(f"--installation={self.installation}")

			try:
				subprocess.run(cmd, check=True, capture_output=True, text=True)
			except subprocess.CalledProcessError as cpe:
				has_error.append(str(cpe.stderr))
			except Exception as e:
				has_error.append(str(e))

		def callback(*args):
			if len(has_error) > 0:
				GLib.idle_add(lambda *args, cpe=cpe: self.parent_page.toast_overlay.add_toast(ErrorToast(_("Could not enable remote"), has_error[0]).toast))
				return

			self.remove_css_class("warning")
			self.set_icon_name("")
			self.set_tooltip_text("")
			self.remote.disabled = False
			self.parent_page.toast_overlay.add_toast(Adw.Toast(title=_("Enabled remote")))
			self.menu_listbox.get_row_at_index(2).set_visible(False)
			self.menu_listbox.get_row_at_index(3).set_visible(True)
			self.parent_page.total_disabled -= 1
			install_page = HostInfo.main_window.pages[HostInfo.main_window.install_row]
			install_page.start_loading()
			install_page.end_loading()
			filters_page = HostInfo.main_window.pages[HostInfo.main_window.packages_row].filters_page
			filters_page.generate_filters()
			if self.parent_page.total_disabled == 0:
				self.parent_page.show_disabled_button.set_active(False)
				self.parent_page.show_disabled_button.set_visible(False)

		Gio.Task.new(None, None, callback).run_in_thread(thread)

	def disable_remote_handler(self, *args):
		error = [None]

		def callback(*args):
			if error[0]:
				return

			self.add_css_class("warning")
			self.set_icon_name("warehouse:error-symbolic")
			self.set_tooltip_text(_("Remote is Disabled"))
			self.remote.disabled = True
			self.parent_page.toast_overlay.add_toast(Adw.Toast(title=_("Disabled remote")))
			self.menu_listbox.get_row_at_index(2).set_visible(True)
			self.menu_listbox.get_row_at_index(3).set_visible(False)
			self.set_visible(self.parent_page.show_disabled_button.get_active())
			self.parent_page.show_disabled_button.set_visible(True)
			self.parent_page.total_disabled += 1
			self.parent_page.none_visible_handler()
			install_page = HostInfo.main_window.pages[HostInfo.main_window.install_row]
			install_page.start_loading()
			install_page.end_loading()
			filters_page = HostInfo.main_window.pages[HostInfo.main_window.packages_row].filters_page
			filters_page.settings.reset("remotes-list")
			filters_page.all_remotes_switch.set_active(False)
			filters_page.generate_filters()
			filters_page.packages_page.apply_filters()

		def thread(*args):
			if self.remote.disabled:
				self.parent_page.toast_overlay.add_toast(ErrorToast(_("Could not disable remote"), _("Remote is already disabled")).toast)
				return

			cmd = ["flatpak", "remote-modify", "--disable", self.remote.name]
			if self.installation == "user" or self.installation == "system":
				cmd.append(f"--{self.installation}")
			else:
				cmd.append(f"--installation={self.installation}")

			try:
				subprocess.run(cmd, check=True, capture_output=True, text=True)
			except subprocess.CalledProcessError as cpe:
				GLib.idle_add(lambda *args, cpe=cpe: self.parent_page.toast_overlay.add_toast(ErrorToast(_("Could not disable remote"), str(cpe.stderr)).toast))
				error[0] = cpe
				return
			except Exception as e:
				GLib.idle_add(lambda *args, e=e: self.parent_page.toast_overlay.add_toast(ErrorToast(_("Could not disable remote"), str(e)).toast))
				error[0] = e
				return

		def on_response(_, response):
			if response != "continue":
				return

			Gio.Task.new(None, None, callback).run_in_thread(thread)

		dialog = Adw.AlertDialog(
			heading=_("Disable {}?").format(self.remote.title), body=_("Any installed apps from {} will stop receiving updates").format(self.remote.name)
		)
		dialog.add_response("cancel", _("Cancel"))
		dialog.add_response("continue", _("Disable"))
		dialog.set_response_appearance("continue", Adw.ResponseAppearance.DESTRUCTIVE)
		dialog.connect("response", on_response)
		dialog.present(self.parent_page.main_window)

	def on_menu_action(self, listbox, row):
		row = row.get_child()
		match row:
			case self.copy_title:
				HostInfo.clipboard.set(self.remote.title)
				self.parent_page.toast_overlay.add_toast(Adw.Toast(title=_("Copied title")))
			case self.copy_name:
				HostInfo.clipboard.set(self.remote.name)
				self.parent_page.toast_overlay.add_toast(Adw.Toast(title=_("Copied name")))
			case self.enable_remote:
				self.enable_remote_handler()
			case self.disable_remote:
				self.disable_remote_handler()
			case self.remove:
				self.parent_page.remove_remote(self)

		self.menu_pop.popdown()

	def idle_stuff(self):
		self.set_title(self.remote.title)
		self.set_subtitle(_("Installation: {}").format(self.installation))
		self.suffix_label.set_label(self.remote.name)
		if self.remote.disabled:
			self.set_icon_name("warehouse:error-symbolic")
			self.add_css_class("warning")
			self.set_tooltip_text(_("Remote is Disabled"))

	def __init__(self, parent_page, installation, remote, **kwargs):
		super().__init__(**kwargs)

		# Extra Object Creation
		self.parent_page = parent_page
		self.remote = remote
		self.installation = installation

		# Apply
		GLib.idle_add(lambda *_: self.idle_stuff())

		## Show / Hide the Enable / Disable actions depending on remote status
		self.menu_listbox.get_row_at_index(2).set_visible(remote.disabled)
		self.menu_listbox.get_row_at_index(3).set_visible(not remote.disabled)

		# Connections
		self.menu_listbox.connect("row-activated", self.on_menu_action)
		self.filter_button.connect("clicked", lambda *_: parent_page.filter_remote(self))
