use std::sync::Arc;
use winit::window::Window;
use wgpu::{
    Device,
    DeviceDescriptor,
    Queue, 
    Surface, 
    SurfaceConfiguration, 
    SurfaceError,
    Instance,
    InstanceDescriptor,
    SurfaceTexture,
    RequestAdapterOptions,
    PowerPreference,
    PresentMode,
    TextureUsages,
};

/// GPU 리소스 관리자 - wgpu 초기화 및 설정 담당
pub struct GraphicsContext {
    pub surface: Surface<'static>,
    pub device: Device,
    pub queue: Queue,
    pub config: SurfaceConfiguration,
}

impl GraphicsContext {
    /// GPU 컨텍스트 초기화
    pub async fn new(window: Arc<Window>) -> Result<Self, String> {
        // wgpu 인스턴스
        let instance = Instance::new(&InstanceDescriptor::default());
        
        // Surface
        let surface = instance.create_surface(Arc::clone(&window))
            .map_err(|e| format!("Surface creation failed: {}", e))?;
        
        // 어댑터
        let adapter = instance.request_adapter(&RequestAdapterOptions {
            power_preference: PowerPreference::default(),
            compatible_surface: Some(&surface),
            force_fallback_adapter: false,
        })
        .await
        .map_err(|e| format!("No suitable adapter found: {}", e))?;
        
        // 디바이스 & 큐
        let (device, queue) = adapter.request_device(&DeviceDescriptor::default())
            .await
            .map_err(|e| format!("Device creation failed: {}", e))?;
        
        // Surface 설정
        let size = window.inner_size();
        let surface_caps = surface.get_capabilities(&adapter);
        let config = SurfaceConfiguration {
            usage: TextureUsages::RENDER_ATTACHMENT,
            format: surface_caps.formats[0],
            width: size.width,
            height: size.height,
            present_mode: PresentMode::Fifo,
            alpha_mode: surface_caps.alpha_modes[0],
            view_formats: vec![],
            desired_maximum_frame_latency: 2,
        };
        surface.configure(&device, &config);
        
        Ok(Self { surface, device, queue, config })
    }
    
    /// 현재 프레임 텍스처 가져오기
    pub fn get_current_frame(&self) -> Result<SurfaceTexture, SurfaceError> {
        self.surface.get_current_texture()
    }
    
    /// Device 참조 가져오기
    pub fn device(&self) -> &Device {
        &self.device
    }
    
    /// Queue 참조 가져오기
    pub fn queue(&self) -> &Queue {
        &self.queue
    }
    
    /// Surface config 참조 가져오기
    pub fn config(&self) -> &SurfaceConfiguration {
        &self.config
    }
}