//! Central plugin that groups all gameplay plugins.
//!
//! Register [`CoreGamePlugin`] once in the app instead of the individual
//! plugins. Plugin registration lives here rather than directly in the app
//! entry point.

use std::sync::Mutex;

use bevy::prelude::*;

use crate::platform::{
    ClipboardBackendResource, StorageBackendResource, default_clipboard_backend,
    default_storage_backend,
};
use crate::{
    AchievementPlugin, AnimationPlugin, AssetSourcesPlugin, AutoCompletePlugin,
    CardAnimationPlugin, CardPlugin, ChallengePlugin, CursorPlugin, DailyChallengePlugin,
    DiagnosticsHudPlugin, DifficultyPlugin, FeedbackAnimPlugin, FontPlugin, GamePlugin, HelpPlugin,
    HomePlugin, HudPlugin, InputPlugin, OnboardingPlugin, PausePlugin, PlayBySeedPlugin,
    ProfilePlugin, ProgressPlugin, RadialMenuPlugin, ReplayOverlayPlugin, ReplayPlaybackPlugin,
    SafeAreaInsetsPlugin, SelectionPlugin, SettingsPlugin, SplashPlugin, StatsPlugin, SyncProvider,
    TablePlugin, ThemePlugin, ThemeRegistryPlugin, TimeAttackPlugin, TouchSelectionPlugin,
    UiFocusPlugin, UiModalPlugin, UiTooltipPlugin, WeeklyGoalsPlugin, WinSummaryPlugin,
};
#[cfg(not(target_arch = "wasm32"))]
use crate::{
    AnalyticsPlugin, AudioPlugin, AvatarPlugin, LeaderboardPlugin, SyncPlugin, SyncSetupPlugin,
};

/// Groups all Ferrous Solitaire gameplay plugins.
pub struct CoreGamePlugin {
    sync_provider: Mutex<Option<Box<dyn SyncProvider + Send + Sync>>>,
}

impl CoreGamePlugin {
    /// Create a new [`CoreGamePlugin`] with the sync provider used by [`SyncPlugin`].
    pub fn new(sync_provider: Box<dyn SyncProvider + Send + Sync>) -> Self {
        Self {
            sync_provider: Mutex::new(Some(sync_provider)),
        }
    }
}

impl Plugin for CoreGamePlugin {
    fn build(&self, app: &mut App) {
        let mut sync_provider = match self.sync_provider.lock() {
            Ok(guard) => guard,
            Err(poisoned) => poisoned.into_inner(),
        };
        #[cfg_attr(target_arch = "wasm32", allow(unused_variables))]
        let sync_provider = sync_provider
            .take()
            .expect("CoreGamePlugin::build called twice");

        match default_storage_backend() {
            Ok(storage) => {
                app.insert_resource(StorageBackendResource(storage));
            }
            Err(err) => {
                warn!("storage: failed to initialize platform backend: {err}");
            }
        }
        match default_clipboard_backend() {
            Ok(clipboard) => {
                app.insert_resource(ClipboardBackendResource(clipboard));
            }
            Err(err) => {
                warn!("clipboard: failed to initialize platform backend: {err}");
            }
        }

        app.add_plugins(AssetSourcesPlugin)
            .add_plugins(ThemePlugin)
            .add_plugins(ThemeRegistryPlugin)
            .add_plugins(FontPlugin)
            .add_plugins(GamePlugin)
            .add_plugins(TablePlugin)
            .add_plugins(CardPlugin)
            // Cursor-icon feedback is desktop-only; Android has no pointer cursor.
            // The drop-target highlight systems (update_drop_highlights,
            // update_drop_target_overlays) live in CursorPlugin but ARE useful
            // on Android — they've been left running because their Bevy system
            // params compile and function on Android; only the CursorIcon insert
            // is inert. Gate the whole plugin if the cursor APIs ever cause
            // Android linker issues; for now it's harmless to leave it registered.
            .add_plugins(CursorPlugin)
            .add_plugins(InputPlugin)
            .add_plugins(RadialMenuPlugin)
            .add_plugins(SelectionPlugin)
            .add_plugins(TouchSelectionPlugin)
            .add_plugins(AnimationPlugin)
            .add_plugins(FeedbackAnimPlugin)
            .add_plugins(CardAnimationPlugin)
            .add_plugins(AutoCompletePlugin)
            .add_plugins(ReplayPlaybackPlugin)
            .add_plugins(ReplayOverlayPlugin)
            .add_plugins(StatsPlugin::default())
            .add_plugins(ProgressPlugin::default())
            .add_plugins(AchievementPlugin::default())
            .add_plugins(DailyChallengePlugin)
            .add_plugins(WeeklyGoalsPlugin)
            .add_plugins(ChallengePlugin)
            .add_plugins(PlayBySeedPlugin)
            .add_plugins(DifficultyPlugin)
            .add_plugins(TimeAttackPlugin)
            .add_plugins(SafeAreaInsetsPlugin)
            .add_plugins(HudPlugin)
            .add_plugins(HelpPlugin)
            .add_plugins(HomePlugin::default())
            .add_plugins(ProfilePlugin)
            .add_plugins(PausePlugin)
            .add_plugins(SettingsPlugin::default())
            .add_plugins(OnboardingPlugin)
            .add_plugins(WinSummaryPlugin)
            .add_plugins(UiModalPlugin)
            .add_plugins(UiFocusPlugin)
            .add_plugins(UiTooltipPlugin)
            .add_plugins(SplashPlugin)
            .add_plugins(DiagnosticsHudPlugin);

        // Plugins that use kira/cpal audio or multi-threaded Tokio are not
        // compatible with the single-threaded wasm32 runtime.  Gate them out
        // so the browser build boots silently and without a sync backend.
        #[cfg(not(target_arch = "wasm32"))]
        app.add_plugins(AvatarPlugin)
            .add_plugins(AudioPlugin)
            .add_plugins(SyncPlugin::new(sync_provider))
            .add_plugins(SyncSetupPlugin)
            .add_plugins(AnalyticsPlugin)
            .add_plugins(LeaderboardPlugin);
    }
}
