from pathlib import Path
from urllib.parse import urlparse
import asyncio
from pyfavicon import Favicon
from gi.repository import Gtk, GLib


def validate_url(url: str):
    url = urlparse(url)
    return all([url.scheme, url.netloc, url.path])


class Window(Gtk.Window):

    def __init__(self):
        Gtk.Window.__init__(self)
        self.set_title("pyfavicon example")
        self.resize(400, 400)
        self.connect("destroy", Gtk.main_quit)

        spinner = Gtk.Spinner()
        image = Gtk.Image.new_from_icon_name("image-missing",
                                             Gtk.IconSize.DIALOG)
        image.set_valign(Gtk.Align.CENTER)
        image.set_halign(Gtk.Align.CENTER)

        stack = Gtk.Stack()
        stack.add_named(spinner, "loading")
        stack.add_named(image, "favicon")
        stack.set_visible_child_name("favicon")

        entry = Gtk.Entry()
        entry.set_valign(Gtk.Align.CENTER)
        entry.set_halign(Gtk.Align.CENTER)
        entry.connect("changed", self.__on_website_changed,
                      image, stack, spinner)
        entry.set_input_purpose(Gtk.InputPurpose.URL)

        container = Gtk.Box(orientation=Gtk.Orientation.VERTICAL)
        container.props.expand = True
        container.pack_start(stack, False, False, 6)
        container.pack_start(entry, False, False, 6)

        self.add(container)

    def __on_website_changed(self, entry, image, stack, spinner):
        website = entry.get_text()
        if not validate_url(website):
            entry.get_style_context().add_class("error")
            return
        entry.get_style_context().remove_class("error")
        spinner.start()
        stack.set_visible_child_name("loading")

        async def set_largest_image(*args):
            favicon = Favicon(download_dir=Path('.'))
            icons = await favicon.from_url(website)
            largest = icons.get_largest()
            assert largest
            await largest.save()
            image.set_from_file(str(largest.path))
            spinner.stop()
            stack.set_visible_child_name("favicon")

        def run(*args):
            try:
                asyncio.run(set_largest_image())
            except AssertionError:
                image.set_from_icon_name("image-missing")
                spinner.stop()
                stack.set_visible_child_name("favicon")
        GLib.idle_add(run, GLib.PRIORITY_DEFAULT_IDLE)


window = Window()
window.show_all()
window.present()
Gtk.main()
