use std::fmt::Debug;
use std::{error::Error, fmt::Display};
use crate::platform::platform_impl::{ImplAudioCaptureConfig, ImplCaptureAccessToken, ImplCaptureConfig, ImplCaptureStream};
use crate::capturable_content::Capturable;
use crate::prelude::{AudioChannelCount, AudioFrame, AudioSampleRate, CapturableDisplay, CapturableWindow, VideoFrame};
use crate::util::Size;
#[derive(Debug)]
pub enum StreamEvent {
    Audio(AudioFrame),
    Video(VideoFrame),
    Idle,
    End,
}
#[derive(Debug, Clone)]
pub enum StreamError {
    Other(String),
}
impl Display for StreamError {
    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
        match self {
            Self::Other(message) => f.write_fmt(format_args!("StreamError::Other(\"{}\")", message))
        }
    }
}
impl Error for StreamError {
    fn source(&self) -> Option<&(dyn Error + 'static)> {
        None
    }
    fn description(&self) -> &str {
        "description() is deprecated; use Display"
    }
    fn cause(&self) -> Option<&dyn Error> {
        self.source()
    }
}
#[derive(Debug, Clone)]
pub enum StreamCreateError {
    Other(String),
    UnsupportedPixelFormat,
    UnauthorizedFeature(String),
}
unsafe impl Send for StreamCreateError {}
unsafe impl Sync for StreamCreateError {}
impl Display for StreamCreateError {
    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
        match self {
            Self::Other(message) => f.write_fmt(format_args!("StreamCreateError::Other(\"{}\")", message)),
            Self::UnsupportedPixelFormat => f.write_fmt(format_args!("StreamCreateError::UnsupportedPixelFormat")),
            Self::UnauthorizedFeature(feature) => f.write_fmt(format_args!("StreamCreateError::UnauthorizedFeature({})", feature)),
        }
    }
}
impl Error for StreamCreateError {
    fn source(&self) -> Option<&(dyn Error + 'static)> {
        None
    }
    fn description(&self) -> &str {
        "description() is deprecated; use Display"
    }
    fn cause(&self) -> Option<&dyn Error> {
        self.source()
    }
}
#[derive(Debug)]
pub enum StreamStopError {
    Other(String),
    AlreadyStopped,
    }
unsafe impl Send for StreamStopError {}
unsafe impl Sync for StreamStopError {}
impl Display for StreamStopError {
    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
        match self {
            Self::Other(message) => f.write_fmt(format_args!("StreamStopError::Other(\"{}\")", message)),
            Self::AlreadyStopped => f.write_fmt(format_args!("StreamStopError::AlreadyStopped")),
        }
    }
}
impl Error for StreamStopError {
    fn source(&self) -> Option<&(dyn Error + 'static)> {
        None
    }
    fn description(&self) -> &str {
        "description() is deprecated; use Display"
    }
    fn cause(&self) -> Option<&dyn Error> {
        self.source()
    }
}
#[derive(Clone, Debug)]
#[allow(unused)]
pub struct AudioCaptureConfig {
    pub(crate) sample_rate: AudioSampleRate, 
    pub(crate) channel_count: AudioChannelCount,
    pub(crate) impl_capture_audio_config: ImplAudioCaptureConfig,
}
impl AudioCaptureConfig {
    pub fn new() -> Self {
        Self {
            sample_rate: AudioSampleRate::Hz24000,
            channel_count: AudioChannelCount::Mono,
            impl_capture_audio_config: ImplAudioCaptureConfig::new()
        }
    }
}
#[derive(Copy, Clone, Debug, PartialEq, Eq)]
#[non_exhaustive]
pub enum CapturePixelFormat {
    Bgra8888,
    Argb2101010,
    V420,
    F420,
}
#[derive(Clone, Debug)]
pub struct CaptureConfig {
    pub(crate) target: Capturable,
    pub(crate) output_size: Size,
    pub(crate) show_cursor: bool,
    pub(crate) pixel_format: CapturePixelFormat,
    pub(crate) capture_audio: Option<AudioCaptureConfig>,
    pub(crate) impl_capture_config: ImplCaptureConfig,
    pub(crate) buffer_count: usize,
}
#[derive(Debug, Clone)]
pub enum CaptureConfigError {
    UnsupportedPixelFormat,
    InvalidBufferCount,
}
unsafe impl Send for CaptureConfigError {}
unsafe impl Sync for CaptureConfigError {}
impl Display for CaptureConfigError {
    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
        match self {
            Self::UnsupportedPixelFormat => f.write_fmt(format_args!("CaptureConfigError::UnsupportedPixelFormat")),
            Self::InvalidBufferCount => f.write_fmt(format_args!("CaptureConfigError::InvalidBufferCount")),
        }
    }
}
impl Error for CaptureConfigError {
    fn source(&self) -> Option<&(dyn Error + 'static)> {
        None
    }
    fn description(&self) -> &str {
        "description() is deprecated; use Display"
    }
    fn cause(&self) -> Option<&dyn Error> {
        self.source()
    }
}
impl CaptureConfig {
    pub fn with_window(window: CapturableWindow, pixel_format: CapturePixelFormat) -> Result<CaptureConfig, CaptureConfigError> {
        let rect = window.rect();
        Ok(CaptureConfig {
            target: Capturable::Window(window),
            pixel_format,
            output_size: rect.size,
            show_cursor: false,
            impl_capture_config: ImplCaptureConfig::new(),
            capture_audio: None,
            buffer_count: 3,
        })
    }
    pub fn with_display(display: CapturableDisplay, pixel_format: CapturePixelFormat) -> CaptureConfig {
        let rect = display.rect();
        CaptureConfig {
            target: Capturable::Display(display),
            pixel_format,
            output_size: rect.size,
            show_cursor: false,
            impl_capture_config: ImplCaptureConfig::new(),
            capture_audio: None,
            buffer_count: 3,
        }
    }
    pub fn with_buffer_count(self, buffer_count: usize) -> Self {
        Self {
            buffer_count,
            ..self
        }
    }
    pub fn with_show_cursor(self, show_cursor: bool) -> Self {
        Self {
            show_cursor,
            ..self
        }
    }
    pub fn with_output_size(self, output_size: Size) -> Self {
        Self {
            output_size,
            ..self
        }
    }
}
pub struct CaptureStream {
    pub(crate) impl_capture_stream: ImplCaptureStream,
}
unsafe impl Send for CaptureStream {}
#[derive(Clone, Copy, Debug)]
pub struct CaptureAccessToken {
    pub(crate) impl_capture_access_token: ImplCaptureAccessToken
}
unsafe impl Send for CaptureAccessToken {}
unsafe impl Sync for CaptureAccessToken {}
impl CaptureAccessToken {
    pub fn allows_borderless(&self) -> bool {
        self.impl_capture_access_token.allows_borderless()
    }
}
impl CaptureStream {
    pub fn test_access(borderless: bool) -> Option<CaptureAccessToken> {
        ImplCaptureStream::check_access(borderless).map(|impl_capture_access_token|
            CaptureAccessToken {
                impl_capture_access_token
            }
        )
    }
    pub async fn request_access(borderless: bool) -> Option<CaptureAccessToken> {
        ImplCaptureStream::request_access(borderless).await.map(|impl_capture_access_token|
            CaptureAccessToken {
                impl_capture_access_token
            }
        )
    }
    pub fn supported_pixel_formats() -> &'static [CapturePixelFormat] {
        ImplCaptureStream::supported_pixel_formats()
    }
    pub fn new(token: CaptureAccessToken, config: CaptureConfig, callback: impl FnMut(Result<StreamEvent, StreamError>) + Send + 'static) -> Result<Self, StreamCreateError> {
        let boxed_callback = Box::new(callback);
        Ok(Self {
            impl_capture_stream: ImplCaptureStream::new(token.impl_capture_access_token, config, boxed_callback)?
        })
    }
    pub fn stop(&mut self) -> Result<(), StreamStopError> {
        self.impl_capture_stream.stop()
    }
}