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

# Plot a network graph of the chords of a given song.

use GraphViz2;
#use lib map { "$ENV{HOME}/sandbox/$_/lib" } qw(Music-BachChoralHarmony); # local author libs
use Music::BachChoralHarmony;

my $id = shift || '000106b_'; # -1 selects a random song
my $thresh = shift || 1;

#my $data_file = 'share/jsbach_chorals_harmony.data'; # local author files
#my $key_title = 'share/jsbach_BWV_keys_titles.txt';  # "
my $bach = Music::BachChoralHarmony->new(
#    data_file => $data_file,
#    key_title => $key_title,
);
my $progression = $bach->parse;

if ($id eq -1) {
    my @ids = keys %$progression;
    $id = $ids[ int rand @ids ];
}

# Redefine the progression for the given id:
$progression = $progression->{$id};

my %score;
my $last;

for my $struct ( @{ $progression->{events} } ) {
    my $chord = $struct->{chord};

    $score{ $last . ' ' . $chord }++ if $last;

    $last = $chord;
}
#use Data::Dumper;warn Dumper [map {"$_ => $score{$_}"} sort {$score{$a} <=> $score{$b}} keys %score];exit;

my $g = GraphViz2->new(
    global => { directed => 1 },
    node   => { shape => 'oval' },
    edge   => { color => 'grey' },
);

my %nodes;
my %edges;

my $key = $progression->{key};

for my $bigram ( keys %score ) {
    next unless $score{$bigram} >= $thresh;

    my ( $i, $j ) = split ' ', $bigram;

    my $color = $i eq $key ? 'red' : 'black';

    $g->add_node( name => $i, color => $color )
        unless $nodes{$i}++;

    $color = $j eq $key ? 'red' : 'black';

    $g->add_node( name => $j, color => $color )
        unless $nodes{$j}++;

    $g->add_edge( from => $i, to => $j, label => $score{$bigram} )
        unless $edges{$bigram}++;
}

$g->run( format => 'png', output_file => "$0-$id.png" );
