# SPDX-FileCopyrightText: 2024 Luca Weiss
# SPDX-License-Identifier: GPL-3.0-only

import threading
from gi.repository import Adw
from gi.repository import GLib
from gi.repository import GObject
from gi.repository import Gtk
import datetime
from .. import esim


@Gtk.Template(resource_path="/eu/lucaweiss/lpa-gtk/pages/esimdownload.ui")
class ESimDownloadPage(Gtk.Box):
    __gtype_name__ = "LpaGtkESimDownload"

    continue_button = Gtk.Template.Child()
    entry_code = Gtk.Template.Child()
    stack = Gtk.Template.Child()
    overlay = Gtk.Template.Child()

    progress_title = Gtk.Template.Child()
    spinner = Gtk.Template.Child()
    details_row = Gtk.Template.Child()

    details_row_children: list[Adw.ActionRow] = []

    def __init__(self, **kwargs):
        super().__init__(**kwargs)

        self.continue_button.connect("clicked", self.continue_clicked)

    def set_active_slot(self, slot: int) -> None:
        self.active_slot = slot

    def set_manager(self, manager: esim.ESimManager) -> None:
        self._manager = manager

    def reset(self) -> None:
        print("Resetting ESimDownloadPage...")
        self.stack.set_visible_child_name("code-input")
        self.set_in_progress(False)
        self.entry_code.set_text("")
        self.progress_title.set_label(_("Downloading..."))
        self.spinner.show()
        self.details_row.set_expanded(True)
        # Seems we need to remove the children manually again
        for i in self.details_row_children:
            self.details_row.remove(i)
        self.details_row_children.clear()

    def show_toast(self, title: str) -> None:
        t = Adw.Toast()
        t.set_title(title)
        self.overlay.add_toast(t)

    def add_detail_row(self, title: str) -> None:
        row = Adw.ActionRow(title=title)
        self.details_row_children.append(row)
        self.details_row.add_row(row)

    _in_progress = False
    @GObject.property(type=bool, default=True)
    def allow_navigate_back(self):
        return not self._in_progress

    def set_in_progress(self, in_progress: bool) -> None:
        self._in_progress = in_progress
        self.notify('allow-navigate-back')

    def add_progress_row(self, time: datetime.timedelta, content: str) -> bool:
        title = f"[{time.seconds}.{int(time.microseconds/10000):02}s] {content}"
        self.add_detail_row(title)
        return False

    def download_done(self) -> bool:
        self.set_in_progress(False)
        self.progress_title.set_label(_("Download complete!"))
        self.spinner.hide()
        return False

    def download_failed(self, e: esim.ESimError) -> bool:
        self.set_in_progress(False)
        self.progress_title.set_label(_("Download failed!"))
        self.spinner.hide()
        self.add_detail_row(str(e))
        return False

    def download_thread(self, code: str) -> None:
        start_time = datetime.datetime.now()
        try:
            for val in self._manager.download_profile_code(self.active_slot, code):
                if isinstance(val, esim.LpacBackend.LpacProgress):
                    print(f"Got progress! {val.message} - {val.data}")
                    GLib.idle_add(self.add_progress_row, datetime.datetime.now() - start_time, val.message)
                elif isinstance(val, esim.LpacBackend.LpacData):
                    print(f"Got final data: {val}")
                    GLib.idle_add(self.add_progress_row, datetime.datetime.now() - start_time, "Done!")
                    GLib.idle_add(self.download_done)
                elif isinstance(val, esim.LpacBackend.LpacMisc):
                    print(f"Got misc data: {val}")
                    GLib.idle_add(self.add_progress_row, datetime.datetime.now() - start_time, val.value)
                else:
                    raise esim.ESimError(f"Unhandled value type {type(val)} - {val}")
        except esim.ESimError as e:
            print(f"ESim download exception: {e}")
            GLib.idle_add(self.download_failed, e)

    def continue_clicked(self, *foo):
        code = self.entry_code.get_text()
        if not code:
            self.show_toast(_("Invalid code input"))
            return

        self.stack.set_visible_child_name("progress")
        self.set_in_progress(True)

        thread = threading.Thread(target=self.download_thread, args=(code,))
        thread.daemon = True
        thread.start()
