mod article;
mod edit;
mod file;
mod misc;
mod navigation;
mod spawn_dialog;
mod sync;

pub use article::ArticleActions;
pub use edit::EditActions;
pub use file::FileActions;
pub use gio::SimpleAction;
pub use misc::MiscActions;
pub use navigation::NavigationActions;
pub use news_flash::models::PluginCapabilities;
pub use spawn_dialog::SpawnDialogActions;
pub use sync::SyncActions;

use crate::app::App;
use crate::content_page::{ArticleListColumn, ArticleViewColumn};
use crate::main_window::MainWindow;
use crate::util::constants;
use gtk4::{prelude::*, subclass::prelude::*};

pub struct GlobalActions;

impl GlobalActions {
    pub fn setup() {
        ArticleActions::setup();
        FileActions::setup();
        SpawnDialogActions::setup();
        NavigationActions::setup();
        SyncActions::setup();
        EditActions::setup();
        MiscActions::setup();

        Self::react_to_state();
        Self::static_accels();
        Self::set_accels();
    }

    pub fn set_accels() {
        let keybindings = App::default().settings().keybindings();
        let general = keybindings.general();
        let article_view = keybindings.article_view();
        let article_list = keybindings.article_list();
        let feed_list = keybindings.feed_list();

        Self::set_keybinding("app.sync", general.refresh());
        Self::set_keybinding("win.fullscreen-article", article_view.fullscreen());
        Self::set_keybinding("win.open-selected-article-in-browser", article_list.open());
        Self::set_keybinding("win.focus-search", general.search());
        Self::set_keybinding("win.next-article", article_list.next());
        Self::set_keybinding("win.prev-article", article_list.prev());
        Self::set_keybinding("win.scroll-down", article_view.scroll_down());
        Self::set_keybinding("win.scroll-up", article_view.scroll_up());
        Self::set_keybinding("win.all-articles", general.all_articles());
        Self::set_keybinding("win.only-unread", general.only_unread());
        Self::set_keybinding("win.only-starred", general.only_starred());
        Self::set_keybinding("win.copy-article-url", article_list.copy_url());
        Self::set_keybinding("win.toggle-category-expanded", feed_list.toggle_expanded());
        Self::set_keybinding("win.sidebar-next", feed_list.next());
        Self::set_keybinding("win.sidebar-prev", feed_list.prev());
        Self::set_keybinding("win.scrape-content", article_view.scrap_content());
        Self::set_keybinding("win.tag-popover", article_view.tag());
        Self::set_keybinding("win.toggle-selected-read", article_list.read());
        Self::set_keybinding("win.toggle-selected-marked", article_list.mark());
        Self::set_keybinding("win.close-article", article_view.close());
        Self::set_keybinding("win.mark-sidebar-read", feed_list.read());
    }

    fn set_keybinding(action: &str, keybinding: Option<String>) {
        let keybinding: &str = keybinding.as_deref().unwrap_or("");
        App::default().set_accels_for_action(action, &[keybinding]);
    }

    fn static_accels() {
        let app = App::default();
        app.set_accels_for_action("win.settings", &["<primary>comma"]);
        app.set_accels_for_action("win.shortcut-window", &["<primary>question"]);
        app.set_accels_for_action("app.quit", &["<primary>Q"]);
    }

    fn react_to_state() {
        let app = App::default();
        let main_window = MainWindow::instance();
        let article_list_column = ArticleListColumn::instance();
        let article_view_column = ArticleViewColumn::instance();

        app.connect_features_notify(|_app| Self::update_actions());
        app.connect_is_offline_notify(|_app| Self::update_actions());
        app.connect_is_scraping_content_notify(|_app| Self::update_actions());
        app.connect_is_syncing_notify(|_app| Self::update_actions());
        app.connect_is_marking_all_notify(|_app| Self::update_actions());
        article_view_column.connect_article_notify(|_article_view_column| Self::update_actions());
        article_list_column.connect_search_focused_notify(|_article_list_column| Self::update_actions());
        libadwaita::prelude::AdwApplicationWindowExt::connect_visible_dialog_notify(&main_window, |_main_window| {
            Self::update_actions()
        });
        main_window
            .imp()
            .navigation_view
            .connect_visible_page_notify(|_navigation_view| Self::update_actions());
    }

    fn update_actions() {
        fn set_win_enabled(name: &str, enabled: bool) {
            if let Some(action) = MainWindow::instance()
                .lookup_action(name)
                .and_downcast::<SimpleAction>()
            {
                action.set_enabled(enabled);
            }
        }

        fn set_app_enabled(action_name: &str, enabled: bool) {
            if let Some(action) = App::default().lookup_action(action_name).and_downcast::<SimpleAction>() {
                action.set_enabled(enabled);
            }
        }

        let app = App::default();
        let main_window = MainWindow::instance();
        let article_list_column = ArticleListColumn::instance();
        let article_view_column = ArticleViewColumn::instance();

        let offline = app.is_offline();
        let is_syncing = app.is_syncing();
        let is_scraping_content = app.is_scraping_content();
        let features = app.features();
        let plugin_id = app.plugin_id();

        let support_mutation = features.as_ref().support_mutation();
        let tags = features.as_ref().contains(PluginCapabilities::SUPPORT_TAGS);

        let content_page_visible = main_window.is_page_visible(constants::CONTENT_PAGE);
        let dialog_open = libadwaita::prelude::AdwApplicationWindowExt::visible_dialog(&main_window).is_some();

        let is_article_open = article_view_column.article().is_some();
        let search_focused = article_list_column.search_focused();
        let is_local_rss = plugin_id.map(|id| id.as_str() == "local_rss").unwrap_or(false);

        let block_shortcuts = !content_page_visible || search_focused || dialog_open;

        set_win_enabled("add-feed-dialog", support_mutation);
        set_win_enabled("add-category-dialog", support_mutation);
        set_win_enabled("add-tag-dialog", tags);

        set_app_enabled(
            "sync",
            !offline && !block_shortcuts && !is_syncing && !is_scraping_content,
        );
        set_app_enabled("quit", !block_shortcuts);
        set_app_enabled("update-login", !is_local_rss);
        set_app_enabled("import-opml", !offline && !block_shortcuts && support_mutation);

        set_win_enabled("mark-sidebar-read", !offline && !block_shortcuts);
        set_win_enabled("discover", !offline && !block_shortcuts && support_mutation);

        set_win_enabled("close-article", is_article_open && !block_shortcuts);
        set_win_enabled("export-article", is_article_open && !block_shortcuts);
        set_win_enabled("open-selected-article-in-browser", is_article_open && !block_shortcuts);

        set_win_enabled("fullscreen-article", !block_shortcuts);
        set_win_enabled("focus-search", !block_shortcuts);
        set_win_enabled("next-article", !block_shortcuts);
        set_win_enabled("prev-article", !block_shortcuts);
        set_win_enabled("scroll-down", !block_shortcuts);
        set_win_enabled("scroll-up", !block_shortcuts);
        set_win_enabled("all-articles", !block_shortcuts);
        set_win_enabled("only-unread", !block_shortcuts);
        set_win_enabled("only-starred", !block_shortcuts);
        set_win_enabled("copy-article-url", !block_shortcuts);
        set_win_enabled("toggle-category-expanded", !block_shortcuts);
        set_win_enabled("sidebar-set-read", !block_shortcuts);
        set_win_enabled("sidebar-next", !block_shortcuts);
        set_win_enabled("sidebar-prev", !block_shortcuts);
        set_win_enabled(
            "scrape-content",
            !block_shortcuts && !is_syncing && !is_scraping_content,
        );
        set_win_enabled("tag-popover", !block_shortcuts);
        set_win_enabled("toggle-selected-marked", !block_shortcuts);
        set_win_enabled("toggle-selected-read", !block_shortcuts);
        set_win_enabled("close-article", !block_shortcuts);
        set_win_enabled("edit-feed-dialog", !is_syncing);
        set_win_enabled("enqueue-delete-feed", !is_syncing && support_mutation);
        set_win_enabled("edit-category-dialog", !is_syncing && support_mutation);
        set_win_enabled("enqueue-delete-category", !is_syncing && support_mutation);
        set_win_enabled("edit-tag-dialog", !is_syncing && support_mutation);
        set_win_enabled("enqueue-delete-tag", !is_syncing && support_mutation);
        set_win_enabled("show-article-view", !block_shortcuts);
    }
}
