use crate::engine_editor::EditorContext;
#[cfg(not(target_arch = "wasm32"))]
use crate::mosaic::ToastKind;
use crate::widgets::AssetCategory;

pub struct PrefabMetadata {
    pub prefab: nightshade::ecs::prefab::Prefab,
    pub animations: Vec<nightshade::ecs::animation::components::AnimationClip>,
    pub source_path: Option<String>,
}

#[derive(Default)]
pub struct UiVisibility {
    pub left_panel: bool,
    pub right_panel: bool,
    pub assets_panel: bool,
    pub animations_panel: bool,
    pub visual_effects_panel: bool,
}

#[derive(Default)]
pub struct PopupState {
    pub add_primitive: Option<nightshade::prelude::Vec2>,
    pub entity_context_menu: Option<nightshade::prelude::Vec2>,
    pub add_node_open: bool,
    pub add_node_search: String,
    pub quit_confirmation: bool,
}

pub struct SceneInfo {
    pub name: String,
    pub entity_count: usize,
    pub is_active: bool,
}

#[derive(Default)]
pub struct SceneBrowserContext {
    pub scenes: Vec<SceneInfo>,
    pub has_project: bool,
}

pub struct AssetKey {
    pub scene_name: String,
    pub asset_name: String,
}

impl AssetKey {
    #[cfg(not(target_arch = "wasm32"))]
    pub fn new(scene_name: impl Into<String>, asset_name: impl Into<String>) -> Self {
        Self {
            scene_name: scene_name.into(),
            asset_name: asset_name.into(),
        }
    }
}

impl std::fmt::Display for AssetKey {
    fn fmt(&self, formatter: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
        write!(formatter, "{}:{}", self.scene_name, self.asset_name)
    }
}

impl std::str::FromStr for AssetKey {
    type Err = String;

    fn from_str(source: &str) -> Result<Self, Self::Err> {
        let (scene, asset) = source
            .split_once(':')
            .ok_or_else(|| format!("Invalid asset key: {}", source))?;
        Ok(Self {
            scene_name: scene.to_string(),
            asset_name: asset.to_string(),
        })
    }
}

#[derive(Default)]
pub struct DragDropState {
    pub hovered_file_path: Option<std::path::PathBuf>,
    pub file_category: Option<AssetCategory>,
    pub pending_asset_update: Option<(AssetKey, String)>,
}

#[derive(Default)]
pub struct ProjectEditState {
    pub current_path: Option<std::path::PathBuf>,
    pub current_name: Option<String>,
    pub hdr_skybox_path: Option<std::path::PathBuf>,
    pub editing_name: bool,
    pub name_edit_buffer: String,
}

#[derive(Default)]
pub struct UiState {
    pub visibility: UiVisibility,
    pub popup: PopupState,
    pub tree_dirty: bool,
    #[cfg(not(target_arch = "wasm32"))]
    pub web_widget_rects: Vec<(String, String, nightshade::prelude::egui::Rect)>,
}

#[derive(Default)]
pub struct AssetState {
    pub prefabs: Vec<PrefabMetadata>,
    pub grayscale_enabled: bool,
    pub inspector_actions: Vec<crate::engine_editor::InspectorAction>,
}

#[derive(Default)]
pub struct AppContext {
    pub editor: EditorContext,
    pub ui: UiState,
    pub assets: AssetState,
    #[cfg(not(target_arch = "wasm32"))]
    pub notifications: Vec<(ToastKind, String)>,
    pub scene_browser: SceneBrowserContext,
    pub project_edit: ProjectEditState,
    pub drag_drop: DragDropState,
    pub pending_file_load: Option<nightshade::filesystem::PendingFileLoad>,
    #[cfg(not(target_arch = "wasm32"))]
    pub claude_command_sender: Option<std::sync::mpsc::Sender<nightshade::claude::CliCommand>>,
    #[cfg(not(target_arch = "wasm32"))]
    pub claude_event_receiver: Option<std::sync::mpsc::Receiver<nightshade::claude::CliEvent>>,
}
