using Gtk;

[GtkTemplate (ui = "/org/gnome/Boxes/ui/assistant/pages/index-page.ui")]
private class Boxes.AssistantIndexPage : AssistantPage {
    GLib.ListStore source_model = new GLib.ListStore (typeof (InstallerMedia));
    GLib.ListStore featured_model = new GLib.ListStore (typeof (Osinfo.Media));

    private VMAssistant dialog;

    private GLib.List<InstallerMedia> installer_medias;

    private const int MAX_MEDIA_ENTRIES = 3;

    [GtkChild]
    private Stack stack;
    [GtkChild]
    private AssistantDownloadsPage recommended_downloads_page;
    [GtkChild]
    private ScrolledWindow home_page;

    [GtkChild]
    private Box detected_sources_section;
    [GtkChild]
    private ListBox source_medias;
    [GtkChild]
    private ListBox featured_medias;
    [GtkChild]
    private Button expand_detected_sources_list_button;

    private GLib.Cancellable cancellable = new GLib.Cancellable ();

    construct {
        populate_media_lists.begin ();

        source_medias.bind_model (source_model, add_media_entry);
        featured_medias.bind_model (featured_model, add_featured_media_entry);

        source_medias.set_header_func (use_list_box_separator);
        featured_medias.set_header_func (use_list_box_separator);
    }

    public void setup (VMAssistant dialog) {
        this.dialog = dialog;
    }

    public void go_back () {
        if (stack.visible_child == home_page) {
            dialog.shutdown ();

            return;
        }

        stack.visible_child = home_page;
        update_topbar ();
    }

    private async void populate_media_lists () {
        var media_manager = MediaManager.get_instance ();

        installer_medias = yield media_manager.list_installer_medias ();
        populate_detected_sources_list (MAX_MEDIA_ENTRIES);

        var recommended_downloads = yield get_recommended_downloads ();
        for (var i = 0; i < MAX_MEDIA_ENTRIES; i++)
            featured_model.append (recommended_downloads.nth (i).data);
    }

    private void populate_detected_sources_list (int? number_of_items = null) {
	var number_of_available_medias = installer_medias.length ();
        detected_sources_section.visible = (number_of_available_medias > 0);
        source_model.remove_all ();

        if (number_of_available_medias == 0)
            return;

	expand_detected_sources_list_button.visible = (number_of_available_medias > MAX_MEDIA_ENTRIES);

        foreach (var media in installer_medias) {
            source_model.append (media);

            if (number_of_items != null && ((number_of_items -= 1) == 0))
                return;
        }
    }

    private Gtk.Widget add_media_entry (GLib.Object object) {
        return new WizardMediaEntry (object as InstallerMedia);
    }

    private Gtk.Widget add_featured_media_entry (GLib.Object object) {
        return new WizardDownloadableEntry (object as Osinfo.Media);
    }

    [GtkCallback]
    private void update_topbar () {
        dialog.previous_button.label = _("Cancel");

        var titlebar = dialog.get_titlebar () as Gtk.HeaderBar;
        if (stack.visible_child == recommended_downloads_page) {
            titlebar.set_custom_title (recommended_downloads_page.search_entry);
        } else {
            titlebar.set_custom_title (null);
        }
    }

    [GtkCallback]
    private void on_expand_detected_sources_list () {
        populate_detected_sources_list ();

        expand_detected_sources_list_button.hide ();
    }

    [GtkCallback]
    private void on_source_media_selected (Gtk.ListBoxRow row) {
        var entry = row as WizardMediaEntry;

        if (entry.media != null)
            done (entry.media);
    }

    [GtkCallback]
    private void on_featured_media_selected (Gtk.ListBoxRow row) {
        var entry = row as WizardDownloadableEntry;

        if (entry.os != null && entry.os.id.has_prefix ("http://redhat.com/rhel/")) {
            (new RHELDownloadDialog (dialog, entry).run ());
        } else {
            DownloadsHub.get_instance ().add_item (entry);
        }

        dialog.shutdown ();
    }

    public override void cleanup () {
        cancellable.cancel ();
    }

    [GtkCallback]
    private async void on_select_file_button_clicked () {
        var file_chooser = new Gtk.FileChooserNative (_("Select a device or ISO file"),
                                                      App.app.main_window,
                                                      Gtk.FileChooserAction.OPEN,
                                                      _("Open"), _("Cancel"));
        file_chooser.bind_property ("visible", dialog, "visible", BindingFlags.INVERT_BOOLEAN);
        if (file_chooser.run () == Gtk.ResponseType.ACCEPT) {
            var media_manager = MediaManager.get_instance ();
            var media = yield media_manager.create_installer_media_for_path (file_chooser.get_filename (),
                                                                             cancellable);
            done (media);
        }
    }

    [GtkCallback]
    private void on_download_an_os_button_clicked () {
        stack.set_visible_child (recommended_downloads_page);

        dialog.previous_button.label = _("Previous");
    }
}
