// This file is part of GNOME Boxes. License: LGPLv2+

public enum WizardDownloadsPageView {
    RECOMMENDED,
    SEARCH_RESULTS,
    NO_RESULTS,
}

public delegate void Boxes.DownloadChosenFunc (Boxes.WizardDownloadableEntry entry);

[GtkTemplate (ui = "/org/gnome/Boxes/ui/wizard-downloads-page.ui")]
public class Boxes.WizardDownloadsPage : Gtk.Stack {
    private OSDatabase os_db = new OSDatabase ();
    public DownloadsSearch search { private set; get; }

    public DownloadChosenFunc download_chosen_func;

    [GtkChild]
    private Gtk.ListBox listbox;
    [GtkChild]
    private Gtk.ListBox recommended_listbox;

    private GLib.ListStore recommended_model;

    /* These are OSes listed in the recommended section of the
     * "Download an OS" page.
     *
     * This list is powered by libosinfo, therefore the URLs are
     * unique identifiers for each OS in osinfo-db.
     *
     * Downstreams are encouraged to tweak the list as they wish.
     * Sorting is also available.
     */
    private string[] recommended_downloads = {
        "http://redhat.com/rhel/7.6",
        "http://redhat.com/rhel/8.0",
        "http://fedoraproject.org/fedora/29",
        "http://fedoraproject.org/silverblue/29",
        "http://ubuntu.com/ubuntu/18.10",
        "http://opensuse.org/opensuse/42.3",
        "http://debian.org/debian/9",
    };

    private WizardDownloadsPageView _page;
    public WizardDownloadsPageView page {
        get { return _page; }
        set {
            _page = value;

            switch (_page) {
                case WizardDownloadsPageView.SEARCH_RESULTS:
                    visible_child_name = "search-results";
                    break;
                case WizardDownloadsPageView.NO_RESULTS:
                    visible_child_name = "no-results";
                    break;
                case WizardDownloadsPageView.RECOMMENDED:
                default:
                    visible_child_name = "recommended";
                    break;
            }
        }
    }

    construct {
        os_db.load.begin ();

        search = new DownloadsSearch ();

        recommended_model = new GLib.ListStore (typeof (Osinfo.Media));
        recommended_listbox.bind_model (recommended_model, create_downloads_entry);
        populate_recommended_list.begin ();

        listbox.bind_model (search.model, create_downloads_entry);

        search.search_changed.connect (set_visible_view);
    }

    private void set_visible_view () {
        if (search.text.length == 0) {
            page = WizardDownloadsPageView.RECOMMENDED;
        } else if (search.model.get_n_items () == 0) {
            page = WizardDownloadsPageView.NO_RESULTS;
        } else {
            page = WizardDownloadsPageView.SEARCH_RESULTS;
        }
    }

    private async void populate_recommended_list () {
        foreach (var os_id in recommended_downloads) {
            try {
                var os = yield os_db.get_os_by_id (os_id);
                var media = os.get_media_list ().get_nth (0) as Osinfo.Media;

                recommended_model.append (media);
            } catch (OSDatabaseError error) {
                warning ("Failed to find OS with id: '%s': %s", os_id, error.message);
            }
        }
    }

    private Gtk.Widget create_downloads_entry (Object item) {
        var media = item as Osinfo.Media;

        return new WizardDownloadableEntry (media);
    }

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

        download_chosen_func (entry);
    }

    [GtkCallback]
    private void on_show_more_button_clicked () {
        search.show_all ();

        page = WizardDownloadsPageView.SEARCH_RESULTS;
    }
}
