use archetype_asset::cache::AssetCache;
use archetype_asset::gpu::mock::MockGpu;
use archetype_asset::runtime::TokioSpawner;
use archetype_asset::spatial::preloader::SceneGraph;
use glam::Vec3;
use std::sync::Arc;
use std::time::Duration;

// A simple mock scene graph
struct WorldMap {
    // Position -> Asset Path
    locations: Vec<(Vec3, String)>,
}

impl SceneGraph for WorldMap {
    fn find_assets_near(&self, position: Vec3, radius: f32) -> Vec<String> {
        self.locations
            .iter()
            .filter(|(pos, _)| pos.distance(position) <= radius)
            .map(|(_, path)| path.clone())
            .collect()
    }
}

#[tokio::main]
async fn main() -> anyhow::Result<()> {
    env_logger::init(); // Run with RUST_LOG=info to see logs

    println!("Initializing Open World Demo...");

    // Setup
    let gpu = MockGpu::new();
    let spawner = TokioSpawner::new();
    // 1GB Cache
    let cache = AssetCache::new(gpu, spawner, 1024 * 1024 * 1024);

    // Create a mock world
    let world = Arc::new(WorldMap {
        locations: vec![
            (Vec3::new(0.0, 0.0, 0.0), "paramount_city.glb".to_string()),
            (Vec3::new(100.0, 0.0, 0.0), "desert_outpost.glb".to_string()),
            (
                Vec3::new(200.0, 0.0, 0.0),
                "mountain_fortress.glb".to_string(),
            ),
        ],
    });

    // Link scene graph
    cache.set_scene_graph(world);

    // Simulate Player Movement
    let mut player_pos = Vec3::new(-50.0, 0.0, 0.0);
    let speed = 20.0; // units per second
    let dt = 0.5; // simulation step

    println!("Starting simulation loop...");
    for i in 0..20 {
        // Move player
        player_pos.x += speed * dt;
        println!("[Frame {}] Player at {:?}", i, player_pos);

        // Update cache (triggers preloading)
        // Note: In a real engine, this happens every frame.
        // The cache puts 'found' assets into a load queue.
        cache.frame_update(player_pos).await;

        // In reality, you don't await loading here, it happens in background.
        // We just sleep to simulate frame time.
        tokio::time::sleep(Duration::from_millis(50)).await;

        // Check what's loaded (Mock check conceptually)
        // We can't query "is_loaded" directly on cache easily without side effects
        // but logs would show "Loading..." if we had real file loading logs enabled.
    }

    println!("Simulation finished.");
    Ok(())
}
