import sys, gettext, gi

gi.require_version('Gtk', '3.0')

from gi.repository import GLib, Gio, Gtk, Gdk
from DomainjoinGUI.dbus_client import get_domain_controller
from DomainjoinGUI.utils import get_ui_file_path, create_builder, show_error_dialog
from DomainjoinGUI.widgets import DomainListBoxRow, DomainDetailsBox, AddUserDialog, AddDomainDialog

from dbus.mainloop.glib import DBusGMainLoop
_ = gettext.gettext


class DomainjoinWindow(Gtk.ApplicationWindow):
    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)

        self.set_default_icon_from_file(get_ui_file_path('domain-join.png'))
        
        style_provider = Gtk.CssProvider()
        style_provider.load_from_path(get_ui_file_path("app.css"))

        Gtk.StyleContext.add_provider_for_screen(
            Gdk.Screen.get_default(),
            style_provider,
            Gtk.STYLE_PROVIDER_PRIORITY_APPLICATION
        )

        self.controller = get_domain_controller()
        self.builder = create_builder(get_ui_file_path('app.ui'))

        self._overlay = self.builder.get_object('_overlay')
        self._overlay_widget = self.builder.get_object('_overlay_widget')
        self._spinner = self.builder.get_object('_spinner')
        self._stack = self.builder.get_object('_stack')
        self.add(self._overlay)
        self._stack.connect('notify::visible-child', self._on_stack_page_changed)

        self._domain_listbox = self.builder.get_object('_domain_listbox')
        self._main_box = self.builder.get_object('_main_box')
        self._domain_details_box = self.builder.get_object('_domain_details_box')
        self._domain_image = self.builder.get_object('_domain_image')
        self._domain_image.set_from_file(get_ui_file_path('domain.png'))
        
        self._back_box = self.builder.get_object('_back_box')
        self._back_button = self.builder.get_object('_back_button')
        self._join_domain_button = self.builder.get_object('_join_domain_button')
        self._back_button.connect('clicked', self._on_back_button_clicked)
        self._join_domain_button.connect('clicked', self._on_join_domain_button_clicked)
        
        self._header_bar = self.builder.get_object('_header_bar')
        self._app_title_label = self.builder.get_object('_app_title_label')
        self._app_title_label.set_text(_('Domain management'))
        self.set_titlebar(self._header_bar)

        self._details_box = DomainDetailsBox(self)
        self.builder.get_object('_domain_details_holder').add(self._details_box)

        self.set_resizable(False)
        self.set_default_size(300, 450)

        self.load()

    def show_main_page(self):
        self._stack.set_visible_child(self._main_box)
        self._details_box.unload()
        self._app_title_label.set_text(_('Domain management'))
        self.load()

    def load(self):
        self.controller.load_domains()
        domains = self.controller.get_all_domains()
        self._domain_listbox.foreach(lambda x: self._domain_listbox.remove(x))
        for i in domains:
            row = DomainListBoxRow(i)
            self._domain_listbox.add(row)
            row.connect('show-domain-details', self._on_show_domain_details)
            row.show()

    def _on_show_domain_details(self, row, domain):
        self._details_box.load(domain)
        self._stack.set_visible_child(self._domain_details_box)
        self._app_title_label.set_text(domain.domain_name)

    def _on_stack_page_changed(self, widget, property):
        main_page = self._stack.get_visible_child() == self._main_box
        self._back_box.set_visible(not main_page)
        self._join_domain_button.set_visible(main_page)


    def _on_back_button_clicked(self, button):
        self.show_main_page()

    def show_loading_indicator(self):
        self._overlay.add_overlay(self._overlay_widget)
        self._spinner.start()

    def hide_loading_indicator(self):
        self._overlay.remove(self._overlay_widget)
        self._spinner.stop()

    def _on_join_domain_button_clicked(self, button):
        dialog = AddDomainDialog(self)
        response = dialog.run()

        if response == Gtk.ResponseType.OK:
            domain = dialog.domain_name_entry.get_text()
            user = dialog.domain_user_entry.get_text()
            password = dialog.password_entry.get_text()

            dialog.destroy()
            
            self.show_loading_indicator()
            def on_success():
                self.load()
                self.hide_loading_indicator()
                
            def on_error(error): 
                self.hide_loading_indicator()
                show_error_dialog(error)

            self.controller.join_domain_async(domain, user, password, on_success=on_success, on_error=on_error)

    def start(self):
        self.set_position(Gtk.WindowPosition.CENTER)
        self.present()
        self.show_all()

        self._back_box.set_visible(self._stack.get_visible_child() != self._main_box)


class DomainjoinApplication(Gtk.Application):
    def __init__(self, *args, **kwargs):
        super().__init__(
            *args,
            application_id="cu.nova.domainjoin.gui",
            flags=Gio.ApplicationFlags.FLAGS_NONE,
            **kwargs
        )
        self.window = None

    def do_startup(self):
        Gtk.Application.do_startup(self)

    def do_activate(self):
        # We only allow a single window and raise any existing ones
        if not self.window:
            # Windows are associated with the application
            # when the last one is closed the application shuts down
            self.window = DomainjoinWindow(application=self)
        self.window.start()

    def on_quit(self, action, param):
        self.quit()

