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

use MIDI::Simple::Drummer;

# Have a basic aresnal (materials, resources) as bit-masks.
my $kit = {
    rest  => 0x00,
    tick  => 0x01,
    kick  => 0x02,
    snare => 0x04,
    crash => 0x08,
    ride  => 0x10,
};

# Have a repertoire - a skill-set of manouvers, strategies and tactics.
my $pattern = {
    1 => [  $kit->{tick} | $kit->{kick},
            $kit->{tick},
            $kit->{tick} | $kit->{snare},
            $kit->{tick},
            $kit->{tick} | $kit->{kick},
            $kit->{tick},
            $kit->{tick} | $kit->{snare},
            $kit->{tick}
    ],
    2 => [  $kit->{tick} | $kit->{kick},
            $kit->{tick},
            $kit->{tick} | $kit->{snare} | $kit->{kick},
            $kit->{tick},
            $kit->{tick} | $kit->{kick},
            $kit->{tick},
            $kit->{tick} | $kit->{snare} | $kit->{kick},
            $kit->{tick}
    ],
    3 => [  $kit->{tick} | $kit->{kick},
            $kit->{tick},
            $kit->{tick} | $kit->{snare},
            $kit->{tick} | $kit->{kick},
            $kit->{tick} | $kit->{kick},
            $kit->{tick},
            $kit->{tick} | $kit->{snare},
            $kit->{tick} | $kit->{kick}
    ],
    4 => [  $kit->{tick} | $kit->{kick},
            $kit->{tick},
            $kit->{tick} | $kit->{snare},
            $kit->{tick} | $kit->{kick},
            $kit->{tick},
            $kit->{tick} | $kit->{kick},
            $kit->{tick} | $kit->{snare},
            $kit->{tick} | $kit->{kick},
    ],
    9 => [  $kit->{tick} | $kit->{kick},
            $kit->{rest},
            $kit->{tick} | $kit->{snare},
            $kit->{rest},
            $kit->{tick} | $kit->{kick},
            $kit->{rest},
            $kit->{tick} | $kit->{snare},
            $kit->{rest}
    ],
    10 => [ $kit->{tick} | $kit->{kick},
            $kit->{rest},
            $kit->{tick} | $kit->{snare} | $kit->{kick},
            $kit->{rest},
            $kit->{tick} | $kit->{kick},
            $kit->{rest},
            $kit->{tick} | $kit->{snare} | $kit->{kick},
            $kit->{rest}
    ],
    11 => [ $kit->{tick} | $kit->{kick},
            $kit->{rest},
            $kit->{tick} | $kit->{snare},
            $kit->{kick},
            $kit->{tick} | $kit->{kick},
            $kit->{rest},
            $kit->{tick} | $kit->{snare},
            $kit->{kick}
    ],
    12 => [ $kit->{tick} | $kit->{kick},
            $kit->{rest},
            $kit->{tick} | $kit->{snare},
            $kit->{kick},
            $kit->{tick},
            $kit->{kick},
            $kit->{tick} | $kit->{snare},
            $kit->{kick},
    ],
    17 => [ $kit->{kick},
            $kit->{tick},
            $kit->{snare},
            $kit->{tick},
            $kit->{kick},
            $kit->{tick},
            $kit->{snare},
            $kit->{tick}
    ],
    18 => [ $kit->{kick},
            $kit->{tick},
            $kit->{snare} | $kit->{kick},
            $kit->{tick},
            $kit->{kick},
            $kit->{tick},
            $kit->{snare} | $kit->{kick},
            $kit->{tick}
    ],
    19 => [ $kit->{kick},
            $kit->{tick},
            $kit->{snare},
            $kit->{tick} | $kit->{kick},
            $kit->{kick},
            $kit->{tick},
            $kit->{snare},
            $kit->{tick} | $kit->{kick}
    ],
    20 => [ $kit->{kick},
            $kit->{tick},
            $kit->{snare},
            $kit->{tick} | $kit->{kick},
            $kit->{rest},
            $kit->{tick} | $kit->{kick},
            $kit->{snare},
            $kit->{tick} | $kit->{kick},
    ],
    33 => [ $kit->{tick} | $kit->{kick},
            $kit->{tick},
            $kit->{tick} | $kit->{snare},
            $kit->{tick},
            $kit->{tick} | $kit->{kick},
            $kit->{tick},
            $kit->{tick} | $kit->{snare},
            $kit->{tick} | $kit->{snare}
    ],
    34 => [ $kit->{tick} | $kit->{kick},
            $kit->{tick},
            $kit->{tick} | $kit->{snare},
            $kit->{tick},
            $kit->{tick} | $kit->{kick},
            $kit->{tick},
            $kit->{tick} | $kit->{snare} | $kit->{kick},
            $kit->{tick} | $kit->{snare}
    ],
    35 => [ $kit->{tick} | $kit->{kick},
            $kit->{tick},
            $kit->{tick} | $kit->{snare},
            $kit->{tick} | $kit->{kick},
            $kit->{tick} | $kit->{kick},
            $kit->{tick},
            $kit->{tick} | $kit->{snare},
            $kit->{tick} | $kit->{snare} | $kit->{kick}
    ],
    36 => [ $kit->{tick} | $kit->{kick},
            $kit->{tick},
            $kit->{tick} | $kit->{snare},
            $kit->{tick} | $kit->{kick},
            $kit->{tick},
            $kit->{tick} | $kit->{kick},
            $kit->{tick} | $kit->{snare},
            $kit->{tick} | $kit->{snare} | $kit->{kick}
    ],
    49 => [ $kit->{kick},
            $kit->{tick},
            $kit->{snare},
            $kit->{tick},
            $kit->{kick},
            $kit->{tick},
            $kit->{snare},
            $kit->{tick} | $kit->{snare}
    ],
    50 => [ $kit->{kick},
            $kit->{tick},
            $kit->{snare} | $kit->{kick},
            $kit->{tick},
            $kit->{kick},
            $kit->{tick},
            $kit->{snare} | $kit->{kick},
            $kit->{tick} | $kit->{snare}
    ],
    51 => [ $kit->{kick},
            $kit->{tick},
            $kit->{snare},
            $kit->{tick} | $kit->{kick},
            $kit->{kick},
            $kit->{tick},
            $kit->{snare},
            $kit->{tick} | $kit->{snare} | $kit->{kick}
    ],
    52 => [ $kit->{kick},
            $kit->{tick},
            $kit->{snare},
            $kit->{tick} | $kit->{kick},
            $kit->{rest},
            $kit->{tick} | $kit->{kick},
            $kit->{snare},
            $kit->{tick} | $kit->{snare} | $kit->{kick}
    ],
    65 => [ $kit->{tick} | $kit->{kick},
            $kit->{tick},
            $kit->{tick} | $kit->{snare},
            $kit->{tick},
            $kit->{tick} | $kit->{kick},
            $kit->{tick} | $kit->{snare},
            $kit->{tick} | $kit->{snare},
            $kit->{tick}
    ],
    66 => [ $kit->{tick} | $kit->{kick},
            $kit->{tick},
            $kit->{tick} | $kit->{snare} | $kit->{kick},
            $kit->{tick},
            $kit->{tick} | $kit->{kick},
            $kit->{tick} | $kit->{snare},
            $kit->{tick} | $kit->{snare} | $kit->{kick},
            $kit->{tick}
    ],
    67 => [ $kit->{tick} | $kit->{kick},
            $kit->{tick},
            $kit->{tick} | $kit->{snare},
            $kit->{tick} | $kit->{kick},
            $kit->{tick} | $kit->{kick},
            $kit->{tick} | $kit->{snare},
            $kit->{tick} | $kit->{snare},
            $kit->{tick} | $kit->{kick}
    ],
    68 => [ $kit->{tick} | $kit->{kick},
            $kit->{tick},
            $kit->{tick} | $kit->{snare},
            $kit->{tick} | $kit->{kick},
            $kit->{tick},
            $kit->{tick} | $kit->{snare} | $kit->{kick},
            $kit->{tick} | $kit->{snare},
            $kit->{tick} | $kit->{kick}
    ],
    81 => [ $kit->{kick},
            $kit->{tick},
            $kit->{snare},
            $kit->{tick},
            $kit->{kick},
            $kit->{tick} | $kit->{snare},
            $kit->{snare},
            $kit->{tick}
    ],
    82 => [ $kit->{kick},
            $kit->{tick},
            $kit->{snare} | $kit->{kick},
            $kit->{tick},
            $kit->{kick},
            $kit->{tick} | $kit->{snare},
            $kit->{snare} | $kit->{kick},
            $kit->{tick}
    ],
    83 => [ $kit->{kick},
            $kit->{tick},
            $kit->{snare},
            $kit->{tick} | $kit->{kick},
            $kit->{kick},
            $kit->{tick} | $kit->{snare},
            $kit->{snare},
            $kit->{tick} | $kit->{kick}
    ],
    84 => [ $kit->{kick},
            $kit->{tick},
            $kit->{snare},
            $kit->{tick} | $kit->{kick},
            $kit->{rest},
            $kit->{tick} | $kit->{snare} | $kit->{kick},
            $kit->{snare},
            $kit->{tick} | $kit->{kick}
    ],
    97 => [ $kit->{tick} | $kit->{snare} | $kit->{kick},
            $kit->{tick},
            $kit->{tick},
            $kit->{tick} | $kit->{snare},
            $kit->{tick} | $kit->{kick},
            $kit->{tick},
            $kit->{tick} | $kit->{snare},
            $kit->{tick},
            $kit->{tick} | $kit->{kick},
            $kit->{tick},
            $kit->{tick} | $kit->{snare},
            $kit->{tick},
            $kit->{tick} | $kit->{kick},
            $kit->{tick} | $kit->{snare},
            $kit->{tick},
            $kit->{tick}
    ],
    98 => [ $kit->{tick} | $kit->{snare} | $kit->{kick},
            $kit->{tick},
            $kit->{tick} | $kit->{kick},
            $kit->{tick} | $kit->{snare},
            $kit->{tick} | $kit->{kick},
            $kit->{tick},
            $kit->{tick} | $kit->{snare} | $kit->{kick},
            $kit->{tick},
            $kit->{tick} | $kit->{kick},
            $kit->{tick},
            $kit->{tick} | $kit->{snare} | $kit->{kick},
            $kit->{tick},
            $kit->{tick} | $kit->{kick},
            $kit->{tick} | $kit->{snare},
            $kit->{tick} | $kit->{kick},
            $kit->{tick},
    ],
    99 => [ $kit->{tick} | $kit->{snare} | $kit->{kick},
            $kit->{tick},
            $kit->{tick},
            $kit->{tick} | $kit->{snare} | $kit->{kick},
            $kit->{tick} | $kit->{kick},
            $kit->{tick},
            $kit->{tick} | $kit->{snare},
            $kit->{tick} | $kit->{kick},
            $kit->{tick} | $kit->{kick},
            $kit->{tick},
            $kit->{tick} | $kit->{snare},
            $kit->{tick} | $kit->{kick},
            $kit->{tick} | $kit->{kick},
            $kit->{tick} | $kit->{snare},
            $kit->{tick},
            $kit->{tick} | $kit->{kick}
    ],
    100 => [$kit->{tick} | $kit->{snare} | $kit->{kick},
            $kit->{tick},
            $kit->{tick},
            $kit->{tick} | $kit->{snare} | $kit->{kick},
            $kit->{tick},
            $kit->{tick} | $kit->{kick},
            $kit->{tick} | $kit->{snare},
            $kit->{tick},
            $kit->{tick} | $kit->{kick},
            $kit->{tick},
            $kit->{tick} | $kit->{snare},
            $kit->{tick} | $kit->{kick},
            $kit->{tick},
            $kit->{tick} | $kit->{snare} | $kit->{kick},
            $kit->{tick},
            $kit->{tick} | $kit->{kick}
    ],
    113 => [$kit->{snare} | $kit->{kick},
            $kit->{tick},
            $kit->{rest},
            $kit->{tick} | $kit->{snare},
            $kit->{kick},
            $kit->{tick},
            $kit->{snare},
            $kit->{tick},
            $kit->{kick},
            $kit->{tick},
            $kit->{snare},
            $kit->{tick},
            $kit->{kick},
            $kit->{tick} | $kit->{snare},
            $kit->{rest},
            $kit->{tick}
    ],
    114 => [$kit->{snare} | $kit->{kick},
            $kit->{tick},
            $kit->{kick},
            $kit->{tick} | $kit->{snare},
            $kit->{kick},
            $kit->{tick},
            $kit->{snare} | $kit->{kick},
            $kit->{tick},
            $kit->{kick},
            $kit->{tick},
            $kit->{snare} | $kit->{kick},
            $kit->{tick},
            $kit->{kick},
            $kit->{tick} | $kit->{snare},
            $kit->{kick},
            $kit->{tick},
    ],
    115 => [$kit->{snare} | $kit->{kick},
            $kit->{tick},
            $kit->{rest},
            $kit->{tick} | $kit->{snare} | $kit->{kick},
            $kit->{kick},
            $kit->{tick},
            $kit->{snare},
            $kit->{tick} | $kit->{kick},
            $kit->{kick},
            $kit->{tick},
            $kit->{snare},
            $kit->{tick} | $kit->{kick},
            $kit->{kick},
            $kit->{tick} | $kit->{snare},
            $kit->{rest},
            $kit->{tick} | $kit->{kick}
    ],
    116 => [$kit->{snare} | $kit->{kick},
            $kit->{tick},
            $kit->{rest},
            $kit->{tick} | $kit->{snare} | $kit->{kick},
            $kit->{rest},
            $kit->{tick} | $kit->{kick},
            $kit->{snare},
            $kit->{tick} | $kit->{kick},
            $kit->{kick},
            $kit->{tick},
            $kit->{snare},
            $kit->{tick} | $kit->{kick},
            $kit->{rest},
            $kit->{tick} | $kit->{snare} | $kit->{kick},
            $kit->{rest},
            $kit->{tick} | $kit->{kick}
    ],
};

# Collect user input and set defaults.
my $repeat   = @ARGV ? shift : 1;   # Play the phrase once by default.
my @patterns = @ARGV ? @ARGV : (1); # Play the first known pattern by default.
# $rules      = { TODO? };

# Enter: The Drummer.
my $d = MIDI::Simple::Drummer->new(-bpm => 100);

# o/` How many more times?
for (1 .. $repeat) {
    # Play each given pattern.
    for my $p (@patterns) {
        # Show status (A.K.A. "debugging" output).
        printf  '%3s (%2d): ', $p, scalar(@{ $pattern->{$p} });
        # Loop over each beat ("note") of the pattern.
        for my $beat (@{ $pattern->{$p} }) {
            # Show the beat number.
            printf '%x ', $beat;
            # Accumulate the simultaneous note-on messages for each kit note ("pad").
            my @note_list = ();
            for my $pad (keys %$kit) {
                # Add a note-on if the the kit pad is included in this beat.
                push @note_list, $d->$pad() if $beat & $kit->{$pad};
            }
            # XXX Friends don't let friends hardcode (duration).
            $d->note($d->EIGHTH, @note_list);
        }
        # "Close" status with a newline.
        print "\n";
    }
}

# Output the MIDI file as "program.mid"
$d->write("$0.mid");
