use strict;
use warnings;

use Test::More;

use_ok 'Music::Dice';

subtest defaults => sub {
    no warnings 'qw';
    my $obj = new_ok 'Music::Dice';
    is $obj->flats, 1, 'flats';
    is $obj->beats, 4, 'beats';
    is $obj->semitones, 12, 'semitones';
    is_deeply $obj->phrase_pool, [qw(wn dhn hn dqn qn den en)], 'phrase_pool';
    is_deeply $obj->phrase_weights, [(1) x @{$obj->phrase_pool } ], 'phrase_weights';
    is_deeply $obj->phrase_groups, [(1) x @{$obj->phrase_pool } ], 'phrase_groups';
    is_deeply $obj->octaves, [2 .. 6], 'octaves';
    is_deeply $obj->notes, [qw(C Db D Eb E F Gb G Ab A Bb B)], 'notes';
    is $obj->identity, 0, 'identity';
    is_deeply $obj->intervals, [ (1) x $obj->semitones ], 'intervals';
    is_deeply $obj->chord_triads, [qw(major minor diminished augmented custom)], 'chord_triads';
    is_deeply $obj->chord_triad_weights, [qw(2 2 1 1 1)], 'chord_triad_weights';
    is_deeply $obj->chord_qualities_major, [qw(add2 sus2 add4 sus4 -5 -6 6 M7 7 add9)], 'chord_qualities_major';
    is_deeply $obj->chord_qualities_major_7, [qw|7sus4 7b5 7#5 69 M79 7b9 9 7#9 7(b9,13) 7(9,13) 9b5 M11 11 7#11 M13 13 7#13|], 'chord_qualities_major_7';
    is_deeply $obj->chord_qualities_minor, [qw(madd4 m6 m7)], 'chord_qualities_minor';
    is_deeply $obj->chord_qualities_minor_7, [qw|m7b5 m7#5 m9 m7(9,11) m11 m13|], 'chord_qualities_minor_7';
    is_deeply $obj->chord_qualities_diminished, [qw(dim6 dim7)], 'chord_qualities_diminished';
    is_deeply $obj->chord_qualities_augmented, [qw(augM7 aug7)], 'chord_qualities_augmented';
    is_deeply $obj->chord_qualities_augmented_7, [qw(aug9)], 'chord_qualities_augmented_7';
    is_deeply $obj->modes, [qw(ionian dorian phrygian lydian mixolydian aeolian locrian)], 'modes';
    is_deeply $obj->tonnetzen, [qw(P R L N S H)], 'tonnetzen';
    is_deeply $obj->tonnetzen_7, [qw(S23 S32 S34 S43 S56 S65 C32 C34 C65)], 'tonnetzen_7';
    is_deeply $obj->rhythmic_phrase_constraints, [3,4,5], 'rhythmic_phrase_constraints';
    $obj = new_ok 'Music::Dice' => [ identity => 1 ];
    is $obj->identity, 1, 'identity';
    is_deeply $obj->intervals, [ 0, ((1) x $obj->semitones), $obj->semitones ], 'intervals';
    $obj = new_ok 'Music::Dice' => [ phrase_pool => 'all' ];
    is @{ $obj->phrase_pool }, 32, 'all phrase_pool';
};

subtest scales => sub {
    no warnings 'qw';
    my $maj = [qw(2 2 1 2 2 2 1)];
    my $obj = new_ok 'Music::Dice' => [ scale_name => 'major' ];
    is_deeply $obj->notes, [qw(C D E F G A B)], 'C major notes';
    is_deeply $obj->intervals, $maj, 'C major intervals';
    $obj = new_ok 'Music::Dice' => [ scale_note => 'C#', scale_name => 'major' ];
    is_deeply $obj->notes, [qw(C# D# E# F# G# A# B#)], 'C# major notes';
    is_deeply $obj->intervals, $maj, 'C# major intervals';
    $obj = new_ok 'Music::Dice' => [ scale_note => 'Db', scale_name => 'major' ];
    is_deeply $obj->notes, [qw(Db Eb F Gb Ab Bb C)], 'Db major notes';
    is_deeply $obj->intervals, $maj, 'Db major intervals';
    $obj = new_ok 'Music::Dice' => [ scale_note => 'A', scale_name => 'minor' ];
    is_deeply $obj->notes, [qw(A B C D E F G)], 'A minor notes';
    is_deeply $obj->intervals, [2, 1, 2, 2, 1, 2, 2], 'A minor intervals';
    $obj = new_ok 'Music::Dice' => [ scale_name => 'chromatic', flats => 0 ];
    is_deeply $obj->notes, [qw(C C# D D# E F F# G G# A A# B)], 'C chromatic notes';
    is_deeply $obj->intervals, [ (1) x 12 ], 'C chromatic intervals';
    $obj = new_ok 'Music::Dice' => [ notes => [qw(C F)], intervals => [5] ];
    is_deeply $obj->notes, [qw(C F)], 'C-F only notes';
    is_deeply $obj->intervals, [5], 'C-F only interval';
    $obj = new_ok 'Music::Dice' => [ notes => [qw(60 62 64 65 67 69 71)] ];
    is_deeply $obj->notes, [qw(60 62 64 65 67 69 71)], 'midinum notes';
    $obj = new_ok 'Music::Dice' => [ identity => 1, scale_name => 'major' ];
    is_deeply $obj->intervals, [ 0, @$maj, $obj->semitones ], 'major identity intervals';
};

subtest rolls => sub {
    my $obj = new_ok 'Music::Dice' => [ rhythmic_phrase_constraints => [4] ];
    my $got = $obj->octave->roll;
    ok defined $got, "octave: $got";
    $got = $obj->note->roll;
    ok defined $got, "note: $got";
    $got = $obj->interval->roll;
    ok defined $got, "interval $got";
    $got = $obj->note_chromatic->roll;
    ok defined $got, "note_chromatic: $got";
    $got = $obj->interval_chromatic->roll;
    ok defined $got, "interval_chromatic $got";
    $got = $obj->note_major->roll;
    ok defined $got, "note_major: $got";
    $got = $obj->interval_major->roll;
    ok defined $got, "interval_major $got";
    $got = $obj->note_minor->roll;
    ok defined $got, "note_minor: $got";
    $got = $obj->interval_minor->roll;
    ok defined $got, "interval_minor: $got";
    $got = $obj->chord_triad->roll;
    ok defined $got, "chord_triad: $got";
    $got = $obj->chord_quality_major->roll;
    ok defined $got, "chord_quality_major: $got";
    $got = $obj->chord_quality_major_7->roll;
    ok defined $got, "chord_quality_major_7: $got";
    $got = $obj->chord_quality_minor->roll;
    ok defined $got, "chord_quality_minor: $got";
    $got = $obj->chord_quality_minor_7->roll;
    ok defined $got, "chord_quality_minor_7: $got";
    $got = $obj->chord_quality_diminished->roll;
    ok defined $got, "chord_quality_diminished: $got";
    $got = $obj->chord_quality_augmented->roll;
    ok defined $got, "chord_quality_augmented: $got";
    $got = $obj->chord_quality_augmented_7->roll;
    ok defined $got, "chord_quality_augmented_7: $got";
    $got = $obj->mode->roll;
    ok defined $got, "mode: $got";
    $got = $obj->ionian->roll;
    ok defined $got, "ionian: $got";
    $got = $obj->dorian->roll;
    ok defined $got, "dorian: $got";
    $got = $obj->phrygian->roll;
    ok defined $got, "phrygian: $got";
    $got = $obj->lydian->roll;
    ok defined $got, "lydian: $got";
    $got = $obj->mixolydian->roll;
    ok defined $got, "mixolydian: $got";
    $got = $obj->aeolian->roll;
    ok defined $got, "aeolian: $got";
    $got = $obj->locrian->roll;
    ok defined $got, "locrian: $got";
    my ($degree, $triad) = $obj->mode_degree_triad_roll('ionian');
    ok defined $degree, 'mode_degree_triad_roll';
    ok defined $triad, 'mode_degree_triad_roll';
    $got = $obj->tonnetz->roll;
    ok defined $got, "tonnetz: $got";
    $got = $obj->tonnetz_7->roll;
    ok defined $got, "tonnetz_7: $got";
    $got = $obj->rhythmic_value->roll;
    ok defined $got, "rhythmic_value: $got";
    $got = $obj->rhythmic_phrase->roll;
    ok defined $got, "rhythmic_phrase: @$got";
    ok @$got > 0, 'rhythmic_phrase: > 0';
    $got = $obj->rhythmic_phrase_constrained->roll;
    ok defined $got, "rhythmic_phrase_constrained: @$got";
    is @$got, 4, 'rhythmic_phrase_constrained: 4';
};

subtest utility => sub {
    my $obj = new_ok 'Music::Dice';
    my $got = $obj->unique_item(['C']);
    isnt $got, 'C', 'unique_item';
};

done_testing();
