use cagire::forth::Value;

use super::harness::{expect_stack, run};

fn ints(vals: &[i64]) -> Vec<Value> {
    vals.iter().map(|&v| Value::Int(v, None)).collect()
}

// Triads

#[test]
fn chord_major() {
    expect_stack("c4 maj", &ints(&[60, 64, 67]));
}

#[test]
fn chord_minor() {
    expect_stack("c4 m", &ints(&[60, 63, 67]));
}

#[test]
fn chord_diminished() {
    expect_stack("c4 dim", &ints(&[60, 63, 66]));
}

#[test]
fn chord_augmented() {
    expect_stack("c4 aug", &ints(&[60, 64, 68]));
}

#[test]
fn chord_sus2() {
    expect_stack("c4 sus2", &ints(&[60, 62, 67]));
}

#[test]
fn chord_sus4() {
    expect_stack("c4 sus4", &ints(&[60, 65, 67]));
}

// Seventh chords

#[test]
fn chord_maj7() {
    expect_stack("c4 maj7", &ints(&[60, 64, 67, 71]));
}

#[test]
fn chord_min7() {
    expect_stack("c4 min7", &ints(&[60, 63, 67, 70]));
}

#[test]
fn chord_dom7() {
    expect_stack("c4 dom7", &ints(&[60, 64, 67, 70]));
}

#[test]
fn chord_dim7() {
    expect_stack("c4 dim7", &ints(&[60, 63, 66, 69]));
}

#[test]
fn chord_half_dim() {
    expect_stack("c4 m7b5", &ints(&[60, 63, 66, 70]));
}

#[test]
fn chord_minmaj7() {
    expect_stack("c4 minmaj7", &ints(&[60, 63, 67, 71]));
}

#[test]
fn chord_aug7() {
    expect_stack("c4 aug7", &ints(&[60, 64, 68, 70]));
}

// Sixth chords

#[test]
fn chord_maj6() {
    expect_stack("c4 maj6", &ints(&[60, 64, 67, 69]));
}

#[test]
fn chord_min6() {
    expect_stack("c4 min6", &ints(&[60, 63, 67, 69]));
}

// Extended chords

#[test]
fn chord_dom9() {
    expect_stack("c4 dom9", &ints(&[60, 64, 67, 70, 74]));
}

#[test]
fn chord_maj9() {
    expect_stack("c4 maj9", &ints(&[60, 64, 67, 71, 74]));
}

#[test]
fn chord_min9() {
    expect_stack("c4 min9", &ints(&[60, 63, 67, 70, 74]));
}

#[test]
fn chord_dom11() {
    expect_stack("c4 dom11", &ints(&[60, 64, 67, 70, 74, 77]));
}

#[test]
fn chord_min11() {
    expect_stack("c4 min11", &ints(&[60, 63, 67, 70, 74, 77]));
}

#[test]
fn chord_dom13() {
    expect_stack("c4 dom13", &ints(&[60, 64, 67, 70, 74, 81]));
}

// Add chords

#[test]
fn chord_add9() {
    expect_stack("c4 add9", &ints(&[60, 64, 67, 74]));
}

#[test]
fn chord_add11() {
    expect_stack("c4 add11", &ints(&[60, 64, 67, 77]));
}

#[test]
fn chord_madd9() {
    expect_stack("c4 madd9", &ints(&[60, 63, 67, 74]));
}

// Altered dominants

#[test]
fn chord_dom7b9() {
    expect_stack("c4 dom7b9", &ints(&[60, 64, 67, 70, 73]));
}

#[test]
fn chord_dom7s9() {
    expect_stack("c4 dom7s9", &ints(&[60, 64, 67, 70, 75]));
}

#[test]
fn chord_dom7b5() {
    expect_stack("c4 dom7b5", &ints(&[60, 64, 66, 70]));
}

#[test]
fn chord_dom7s5() {
    expect_stack("c4 dom7s5", &ints(&[60, 64, 68, 70]));
}

// Power chord

#[test]
fn chord_power() {
    expect_stack("c4 pwr", &ints(&[60, 67]));
}

// Suspended seventh

#[test]
fn chord_7sus4() {
    expect_stack("c4 7sus4", &ints(&[60, 65, 67, 70]));
}

#[test]
fn chord_9sus4() {
    expect_stack("c4 9sus4", &ints(&[60, 65, 67, 70, 74]));
}

// Augmented major

#[test]
fn chord_augmaj7() {
    expect_stack("c4 augmaj7", &ints(&[60, 64, 68, 71]));
}

// 6/9 chords

#[test]
fn chord_maj69() {
    expect_stack("c4 maj69", &ints(&[60, 64, 67, 69, 74]));
}

#[test]
fn chord_min69() {
    expect_stack("c4 min69", &ints(&[60, 63, 67, 69, 74]));
}

// Extended - major

#[test]
fn chord_maj11() {
    expect_stack("c4 maj11", &ints(&[60, 64, 67, 71, 74, 77]));
}

#[test]
fn chord_maj13() {
    expect_stack("c4 maj13", &ints(&[60, 64, 67, 71, 74, 81]));
}

#[test]
fn chord_min13() {
    expect_stack("c4 min13", &ints(&[60, 63, 67, 70, 74, 81]));
}

// Altered - lydian dominant

#[test]
fn chord_dom7s11() {
    expect_stack("c4 dom7s11", &ints(&[60, 64, 67, 70, 78]));
}

// Different roots

#[test]
fn chord_a3_min7() {
    expect_stack("a3 min7", &ints(&[57, 60, 64, 67]));
}

#[test]
fn chord_e4_dom7s9() {
    expect_stack("e4 dom7s9", &ints(&[64, 68, 71, 74, 79]));
}

#[test]
fn chord_with_integer_root() {
    let f = run("60 maj");
    let stack = f.stack();
    assert_eq!(stack, ints(&[60, 64, 67]));
}
