//! Coordinator configuration.

/// Buffering mode for frame-pipelined uploads.
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum BufferingMode {
    /// Single buffer - CPU waits for GPU each frame.
    Single,
    /// Double buffering - overlap CPU/GPU work.
    Double,
    /// Triple buffering - maximum throughput, more latency.
    Triple,
}

impl Default for BufferingMode {
    fn default() -> Self {
        Self::Double
    }
}

impl BufferingMode {
    /// Get the number of buffers for this mode.
    pub fn buffer_count(&self) -> usize {
        match self {
            BufferingMode::Single => 1,
            BufferingMode::Double => 2,
            BufferingMode::Triple => 3,
        }
    }
}

/// Configuration for the coordinator.
#[derive(Debug, Clone)]
pub struct CoordinatorConfig {
    /// Size of the per-frame CPU arena in bytes.
    pub frame_arena_size: usize,
    
    /// Maximum number of staging buffers in the pool.
    pub staging_pool_size: usize,
    
    /// Default size for staging buffers in bytes.
    pub staging_buffer_size: usize,
    
    /// Buffering mode for frame pipeline.
    pub buffering: BufferingMode,
    
    /// Maximum pending transfers before auto-flush.
    pub max_pending_transfers: usize,
    
    /// Whether to automatically flush transfers at end of frame.
    pub auto_flush_on_frame_end: bool,
}

impl Default for CoordinatorConfig {
    fn default() -> Self {
        Self {
            frame_arena_size: 16 * 1024 * 1024, // 16 MB
            staging_pool_size: 32,
            staging_buffer_size: 64 * 1024, // 64 KB
            buffering: BufferingMode::Double,
            max_pending_transfers: 64,
            auto_flush_on_frame_end: true,
        }
    }
}

impl CoordinatorConfig {
    /// Create a config optimized for small data transfers.
    pub fn small() -> Self {
        Self {
            frame_arena_size: 1 * 1024 * 1024, // 1 MB
            staging_pool_size: 8,
            staging_buffer_size: 16 * 1024, // 16 KB
            buffering: BufferingMode::Double,
            max_pending_transfers: 16,
            auto_flush_on_frame_end: true,
        }
    }
    
    /// Create a config optimized for large data transfers.
    pub fn large() -> Self {
        Self {
            frame_arena_size: 64 * 1024 * 1024, // 64 MB
            staging_pool_size: 64,
            staging_buffer_size: 256 * 1024, // 256 KB
            buffering: BufferingMode::Triple,
            max_pending_transfers: 128,
            auto_flush_on_frame_end: true,
        }
    }
    
    /// Set frame arena size.
    pub fn with_frame_arena_size(mut self, size: usize) -> Self {
        self.frame_arena_size = size;
        self
    }
    
    /// Set buffering mode.
    pub fn with_buffering(mut self, mode: BufferingMode) -> Self {
        self.buffering = mode;
        self
    }
    
    /// Set staging pool size.
    pub fn with_staging_pool(mut self, pool_size: usize, buffer_size: usize) -> Self {
        self.staging_pool_size = pool_size;
        self.staging_buffer_size = buffer_size;
        self
    }
}
