#!/usr/bin/env perl
use strict;
use warnings;

# Use local libraries
use lib map { "$ENV{HOME}/sandbox/$_/lib" } qw( MIDI-Drummer-Tiny MIDI-Util Music-Duration Music-Duration-Partition );

use MIDI::Drummer::Tiny;
use MIDI::Util qw(setup_score set_chan_patch);
use Music::Duration::Partition;
use Music::Scales;
use Music::VoiceGen;

my $max   = shift || 4;
my $bpm   = shift || 90;
my $size  = shift || 3;
my $note  = shift || 'A';
my $scale = shift || 'pminor';

my $top_patch    = 40;
my $bottom_patch = 42;

my $score = setup_score( bpm => $bpm );

$score->synch(
#    \&top,
    \&bottom,
    \&pulse,
);

$score->write_score("$0.mid");

sub top {
    set_chan_patch( $score, 0, $top_patch );
    $score->Volume(80);

    my @scale = get_scale_notes( $note, $scale );
    @scale = map { $_ . 5 } @scale;

    for my $n ( 1 .. $max * 2 ) {
        $score->n( 'wn', $scale[ int rand @scale ] );
    }
}

sub bottom {
    set_chan_patch( $score, 1, $bottom_patch );

    my $mdp1 = Music::Duration::Partition->new(
        size => $size,
        pool => [qw/ qn en sn /],
        #verbose=>1,
    );
    my $motif1 = $mdp1->motif;

    my $mdp2 = Music::Duration::Partition->new(
        size => $size,
        pool => [qw/ qn en /],
        #verbose=>1,
    );
    my $motif2 = $mdp2->motif;

    my @pitches = get_scale_MIDI( $note, 1, $scale );

    my $voice = Music::VoiceGen->new(
        pitches   => \@pitches,
        intervals => [qw/ -4 -3 -2 2 3 4 /],
    );

    my @notes1 = map { $voice->rand } 0 .. @$motif1 - 1;

    for my $x ( 1 .. $max ) {
        my @notes2 = map { $voice->rand } 0 .. @$motif2 - 1;

        $mdp1->add_to_score($score, $motif1, \@notes1);

        $score->r('qn');

        $mdp1->add_to_score($score, $motif2, \@notes2);

        $score->r('qn');
    }

    $score->n( 'wn', $pitches[0] );
}

sub pulse {
    my $d = MIDI::Drummer::Tiny->new( bpm => $bpm, score => $score );

    for my $n ( 1 .. $max ) {
        $d->note( $d->quarter, $d->closed_hh ) for 1 .. 2 * ( $size + 1 );
    }
}
