using Adw;
using Gtk;

public class ConversationListView : Adw.Bin
{
    public ConversationListModel conversation_model { get; private set; }
    public signal void conversation_selected(Conversation conversation);
    public signal void conversation_activated(Conversation conversation);

    private Adw.ToolbarView container;
    private ListBox list_box;
    private ScrolledWindow scrolled_window;
    private Adw.HeaderBar header_bar;

    private string? selected_conversation_guid = null;
    private bool selection_update_queued = false;
    private bool suppress_row_selected = false;

    public ConversationListView () {
        container = new Adw.ToolbarView ();
        set_child (container);

        scrolled_window = new ScrolledWindow ();
        container.set_content (scrolled_window);

        list_box = new ListBox ();
        list_box.add_css_class ("boxed-list");
        list_box.set_selection_mode (SelectionMode.SINGLE);
        list_box.activate_on_single_click = false; 
        scrolled_window.set_child (list_box);

        list_box.row_selected.connect ((row) => {
            if (suppress_row_selected) {
                return;
            }

            var conversation_row = (ConversationRow?) row;
            if (conversation_row != null) {
                selected_conversation_guid = conversation_row.conversation.guid;

                Conversation conversation = conversation_model.get_conversation(selected_conversation_guid);
                conversation_selected(conversation);
            }
        });

        list_box.row_activated.connect((row) => {
            var conversation_row = (ConversationRow?) row;
            if (conversation_row != null) {
                Conversation conversation = conversation_row.conversation;
                conversation_activated(conversation);
            }
        });

        header_bar = new Adw.HeaderBar ();
        header_bar.set_title_widget (new Label ("Kordophone"));
        container.add_top_bar (header_bar);

        // Setup application menu
        var app_menu = new Menu ();

        var section = new Menu ();
        section.append ("Manual Sync", "list.refresh");
        section.append ("Settings...", "win.settings");
        app_menu.append_section (null, section);

        section = new Menu ();
        section.append ("Quit", "app.quit");
        app_menu.append_section (null, section);

        var refresh_action = new SimpleAction("refresh", null);
        refresh_action.activate.connect (() => {
            try {
                Repository.get_instance().sync_conversation_list();
            } catch (GLib.Error e) {
                warning("Failed to sync conversation list: %s", e.message);
            }
        });

        var action_group = new SimpleActionGroup ();
        action_group.add_action(refresh_action);
        insert_action_group ("list", action_group);
        
        var menu_button = new Gtk.MenuButton ();
        menu_button.menu_model = app_menu;
        menu_button.primary = true;
        menu_button.icon_name = "open-menu-symbolic";
        header_bar.pack_end (menu_button);

        // Set up model and bind to list
        conversation_model = new ConversationListModel ();
        conversation_model.items_changed.connect (on_items_changed);
        list_box.bind_model (conversation_model, create_conversation_row);
    }
    
    private void on_items_changed (uint position, uint removed, uint added) {
        enqueue_selection_update();
    }

    private void enqueue_selection_update() {
        if (selection_update_queued) {
            return;
        }

        selection_update_queued = true;
        GLib.Idle.add(() => {
            update_selection();
            selection_update_queued = false;
            return false;
        }, GLib.Priority.HIGH);
    }
    
    private void update_selection() {
        // Re-select selected_conversation_guid, if it has changed. 
        if (selected_conversation_guid != null) {
            for (uint i = 0; i < conversation_model.get_n_items(); i++) {
                var conversation = (Conversation) conversation_model.get_item(i);
                if (conversation.guid == selected_conversation_guid) {
                    var row = list_box.get_row_at_index((int)i);
                    if (row != null) {
                        suppress_row_selected = true;
                        list_box.select_row(row);
                        suppress_row_selected = false;
                    }
                }
            }
        }
    }
    
    private Widget create_conversation_row (Object item) {
        Conversation conversation = (Conversation) item;
        return new ConversationRow (conversation);
    }
}
