use std::ffi::{CString, c_char};

unsafe extern "C" {
    fn ds4_media_open(url: *const c_char, title: *const c_char, video: bool) -> bool;
}

pub(crate) fn open(url: &str, title: &str, video: bool) -> Result<(), String> {
    let url = playable_url(url)?;
    let url = CString::new(url.as_str()).map_err(|error| error.to_string())?;
    let title = CString::new(title).map_err(|error| error.to_string())?;
    // SAFETY: Both C strings live for the duration of the call; Objective-C copies them.
    if unsafe { ds4_media_open(url.as_ptr(), title.as_ptr(), video) } {
        Ok(())
    } else {
        Err("AVKit could not create the media player".into())
    }
}

fn playable_url(value: &str) -> Result<url::Url, String> {
    let url = url::Url::parse(value).map_err(|error| format!("invalid media URL: {error}"))?;
    if matches!(url.scheme(), "http" | "https") {
        Ok(url)
    } else {
        Err("media URLs must use HTTP(S)".into())
    }
}

#[cfg(test)]
mod tests {
    use super::*;

    #[test]
    fn media_player_only_accepts_remote_http_urls() {
        assert!(playable_url("https://example.com/video.mp4").is_ok());
        assert!(playable_url("http://example.com/audio.mp3").is_ok());
        assert!(playable_url("file:///tmp/private.mov").is_err());
        assert!(playable_url("javascript:alert(1)").is_err());
    }
}
