// i was gonna do a "filename hack" and name this file "adopte.rs" as in "adopters" but i would need to type
// adopte::adopt which is odd so i didn't

use std::{
    fs::{create_dir_all, write},
    io::{Read, Write},
    path::Path,
    process::Command,
    time::{SystemTime, UNIX_EPOCH},
};

use crate::{import, musicbrainz::get_disc_info, tagging};

// adopt = rip a disc but ripping sounds like destroying so i'm not using it
pub fn adopt(timbre_dir: &Path) {
    let disc = get_disc_info("http://catgpt-server:5000");
    let release = &disc.releases[0];
    println!("{}", release.id);
    let tmp_dir = timbre_dir.join(format!(
        ".tmp/{}",
        SystemTime::now()
            .duration_since(UNIX_EPOCH)
            .expect("time went backwards?? ¯\\_(ツ)_/¯\nquit trying to make me timber!\n")
            .as_secs()
    ));
    create_dir_all(&tmp_dir).expect("i couldn't make my workspace :(\n");
    write(tmp_dir.join("README.txt"), "I'M DOING IT CHILLAX BRO\n")
        .expect("couldn't even write my chillax note :( bro fix ur pc\n");
    // as of writing this line here i just donated $2.75 + transaction fees to Wikipedia!

    println!("adopting...");

    let tracks = &release.media[0].tracks;
    let tracks_len = tracks.len();

    for track_num in 1..=tracks_len {
        let file_name = format!("track{track_num:02}.wav");
        let current_track = &tracks[track_num - 1];

        let (mut pty, pts) = pty_process::blocking::open().expect("couldn't open a pty :(\n");
        pty.resize(pty_process::Size::new(24, 80))
            .expect("couldn't size the pty :(\n");

        let cmd = pty_process::blocking::Command::new("cdparanoia")
            .arg("-e")
            .arg(track_num.to_string())
            .arg(&tmp_dir.join(&file_name));

        let mut child = cmd.spawn(pts).expect("cdparanoia wouldn't start :(\n");

        let mut buf = [0u8; 512];
        let mut acc = String::new();
        loop {
            let n = pty.read(&mut buf).unwrap_or(0);
            if n == 0 {
                // done
                println!();
                break;
            }
            acc.push_str(&String::from_utf8_lossy(&buf[..n]));

            while let Some(pos) = acc.find('\r') {
                let chunk: String = acc.drain(..=pos).collect();
                if chunk.contains("PROGRESS") {
                    let bar = chunk
                        .split_once("== PROGRESS == [")
                        .unwrap()
                        .1
                        .split_once("|")
                        .unwrap()
                        .0;
                    print!(
                        "\r[{}] {track_num}/{} {}",
                        bar, tracks_len, current_track.title
                    );
                    std::io::stdout().flush().unwrap();
                }
            }
        }
        child.wait().expect("cdparanoia didn't finish cleanly :(\n");

        Command::new("flac")
            .arg("--best") // max compression, lossless
            .arg(&tmp_dir.join(&file_name)) // input WAV
            .output()
            .expect("flac wouldn't encode :( is it installed?\n");

        tagging::write_tags(
            Path::new(&tmp_dir.join(format!("track{track_num:02}.flac"))),
            &current_track.title,
            &current_track.artist_credit[0].name,
            &release.title,
            track_num as u32,
        );

        import::import_file(
            Path::new(&tmp_dir.join(format!("track{track_num:02}.flac"))),
            &timbre_dir,
        );
    }

    println!("done!");
}
