/*
SPDX-License-Identifier: GPL-3.0-or-later
Copyright © 2024 Mike Robeson [dijksterhuis]
*/

mod helpers;

use helpers::*;
use ot_tools_io::slices::Slice;
use ot_tools_io::{CalculateChecksum, MarkersFile, OctatrackFileIO};
use std::env::temp_dir;
use std::fs::create_dir_all;

const SAMPLE_LEN: u32 = 2679;

fn test_helper(fname: &str) -> MarkersFile {
    let fpath = get_markers_dirpath().join(fname);
    let r = MarkersFile::from_data_file(&fpath);
    println!("result: {r:?}");
    assert!(r.is_ok());
    r.unwrap()
}

fn assert_helper(m: MarkersFile, mut v: MarkersFile) {
    v.checksum = v.calculate_checksum().unwrap();
    println!("header");
    assert_eq!(m.header, v.header);
    println!("datatype version");
    assert_eq!(m.datatype_version, v.datatype_version);
    println!("flex slots");
    assert_eq!(m.flex_slots, v.flex_slots);
    println!("static slots");
    assert_eq!(m.static_slots, v.static_slots);
    println!("checksum slots");
    assert_eq!(m.checksum, v.checksum);
}

#[test]
fn flex_slot_1_noedit() {
    let m = test_helper("flex-slot-1-noedit.work");
    let mut valid = MarkersFile::default();
    valid.flex_slots[0].trim_end = SAMPLE_LEN;
    assert_helper(m, valid);
}

#[test]
fn flex_slot_128_noedit() {
    let m = test_helper("flex-slot-128-noedit.work");
    let mut valid = MarkersFile::default();
    valid.flex_slots[127].trim_end = SAMPLE_LEN;
    assert_helper(m, valid);
}

#[test]
fn static_slot_1_noedit() {
    let m = test_helper("static-slot-1-noedit.work");
    let mut valid = MarkersFile::default();
    // FIXME: I edited the recorder slot, then cleared the sample association
    //        and moved onto statics... but this didn't ACTUALLY CLEAR the
    //        recording slot data -- recording slots persist!
    valid.flex_slots[128].trim_end = SAMPLE_LEN;
    valid.static_slots[0].trim_end = SAMPLE_LEN;
    assert_helper(m, valid);
}

#[test]
fn static_slot_128_noedit() {
    let m = test_helper("static-slot-128-noedit.work");
    let mut valid = MarkersFile::default();
    // FIXME: I edited the recorder slot, then cleared the sample association
    //        and moved onto statics... but this didn't ACTUALLY CLEAR the
    //        recording slot data -- recording slots persist!
    valid.flex_slots[128].trim_end = SAMPLE_LEN;
    valid.static_slots[127].trim_end = SAMPLE_LEN;
    assert_helper(m, valid);
}

#[test]
fn recorder_slot_1_noedit() {
    let m = test_helper("recorder-slot-1-noedit.work");
    let mut valid = MarkersFile::default();
    valid.flex_slots[128].trim_end = SAMPLE_LEN;
    assert_helper(m, valid);
}

#[test]
fn flex_slot_1_loop_edit() {
    let m = test_helper("flex-slot-1-loop-edit.work");
    let mut valid = MarkersFile::default();
    valid.flex_slots[0].trim_end = SAMPLE_LEN;
    valid.flex_slots[0].loop_point = 1456;
    assert_helper(m, valid);
}

#[test]
fn flex_slot_1_start_edit() {
    let m = test_helper("flex-slot-1-start-edit.work");
    let mut valid = MarkersFile::default();
    valid.flex_slots[0].trim_end = SAMPLE_LEN;
    valid.flex_slots[0].trim_offset = 1456;
    // TODO: Huh?
    valid.flex_slots[0].loop_point = 1456;
    assert_helper(m, valid);
}

// didn't get this one?
#[ignore]
#[test]
fn flex_slot_1_end_edit() {
    let m = test_helper("flex-slot-1-start-edit.work");
    let mut valid = MarkersFile::default();
    valid.flex_slots[0].trim_end = SAMPLE_LEN;
    assert_helper(m, valid);
}

#[test]
fn flex_slot_1_slice_1_noloop() {
    let m = test_helper("flex-slot-1-slice-1-noloop.work");
    let mut valid = MarkersFile::default();
    valid.flex_slots[0].trim_end = SAMPLE_LEN;
    valid.flex_slots[0].slice_count = 1;
    valid.flex_slots[0].slices[0] = Slice {
        trim_start: 0,
        trim_end: 416,
        loop_start: 0xFFFFFFFF,
    };
    assert_helper(m, valid);
}

#[test]
fn flex_slot_1_slice_1_looped() {
    let m = test_helper("flex-slot-1-slice-1-looped.work");
    let mut valid = MarkersFile::default();
    valid.flex_slots[0].trim_end = SAMPLE_LEN;
    valid.flex_slots[0].slice_count = 1;
    valid.flex_slots[0].slices[0] = Slice {
        trim_start: 0,
        trim_end: 416,
        loop_start: 202,
    };
    assert_helper(m, valid);
}

// initial linear slice grid
#[test]
fn flex_slot_1_slice_4_noloop() {
    let m = test_helper("flex-slot-1-slice-4-noloop.work");
    let mut valid = MarkersFile::default();
    valid.flex_slots[0].trim_end = SAMPLE_LEN;
    valid.flex_slots[0].slice_count = 4;
    valid.flex_slots[0].slices[0] = Slice {
        trim_start: 0,
        trim_end: 668,
        loop_start: 0xFFFFFFFF,
    };
    valid.flex_slots[0].slices[1] = Slice {
        trim_start: 668,
        trim_end: 1338,
        loop_start: 0xFFFFFFFF,
    };
    valid.flex_slots[0].slices[2] = Slice {
        trim_start: 1338,
        trim_end: 2008,
        loop_start: 0xFFFFFFFF,
    };
    valid.flex_slots[0].slices[3] = Slice {
        trim_start: 2008,
        trim_end: SAMPLE_LEN,
        loop_start: 0xFFFFFFFF,
    };
    assert_helper(m, valid);
}

#[test]
fn write_default_then_read() -> RBoxErr<()> {
    let path = temp_dir()
        .join(CRATE_NAME)
        .join("read_markers_files")
        .join("write_read_default.work");
    let dirpath = path.parent().unwrap();
    if !dirpath.exists() {
        create_dir_all(dirpath)?;
    }
    MarkersFile::default().to_data_file(&path)?;
    assert_eq!(MarkersFile::default(), MarkersFile::from_data_file(&path)?);

    Ok(())
}
