use anyhow::anyhow;
use std::collections::HashMap;
use std::io::Read;
use std::path::Path;
use std::process::Command;

use anyhow::Result;

use super::Previewable;

pub struct VideoPath<'a>(pub &'a Path);

impl<'a> Previewable for VideoPath<'a> {
    fn get_thumbnail(&self, options: HashMap<String, String>) -> Result<Option<Vec<u8>>> {
        let duration_cmd = Command::new("ffprobe")
            .args(["-threads", "1"])
            .args(["-v", "error"])
            .args(["-show_entries", "format=duration"])
            .args(["-of", "default=noprint_wrappers=1:nokey=1"])
            .arg(self.0)
            .output()?;
        if !duration_cmd.status.success() {
            return Err(anyhow!(
                "Failed to retrieve file duration: {:?}",
                String::from_utf8_lossy(&duration_cmd.stderr)
            ));
        }

        let duration = String::from_utf8_lossy(&duration_cmd.stdout)
            .trim()
            .parse::<f64>()?;
        let position = {
            if let Some(str_position) = options.get("position") {
                str_position.parse()?
            } else {
                90.0f64
            }
        };

        let outfile = tempfile::Builder::new().suffix(".webp").tempfile()?;
        let thumbnail_cmd = Command::new("ffmpeg")
            .args(["-threads", "1"])
            .args(["-discard", "nokey"])
            .args(["-noaccurate_seek"])
            .args(["-ss", &(position.min(duration / 2.0)).to_string()])
            .args(["-i", &self.0.to_string_lossy()])
            .args(["-vframes", "1"])
            .args(["-vsync", "passthrough"])
            .arg(&*outfile.path().to_string_lossy())
            .arg("-y")
            .output()?;

        if !thumbnail_cmd.status.success() {
            return Err(anyhow!(
                "Failed to render thumbnail: {:?}",
                String::from_utf8_lossy(&thumbnail_cmd.stderr)
            ));
        }

        let mut buffer = Vec::new();
        outfile.as_file().read_to_end(&mut buffer)?;
        Ok(Some(buffer))
    }
}
