#!/usr/bin/perl -w

use strict;
use utf8;
use Encode;

binmode(STDIN , ":encoding(UTF-8)");
binmode(STDOUT, ":encoding(UTF-8)");
binmode(STDERR, ":encoding(UTF-8)");


my $ext_a = ".instr_ily";
my $ext_b = ".staff_ily";
my $pre = 0; # if pre: sopStaff else staffSop
my $with = 1; # with staff names
my $klingande = 1; # transposed instruments, 0: as written or 1: transposed to c

my %clef = (
    f  => "french",
    g  => "treble",
    s  => "soprano",
    m  => "mezzosoprano",
    a  => "alto",
    B  => "baritone",
    vb => "varbaritone",
    t  => "tenor",
    T  => "treble_8",
    b  => "bass",
);

########################################

sub rd($$) {
    my @arr;
    my $file = shift;
    my $fh = shift;
    while (<$fh>) {
	next if (m/^#/);
	if (m/^%/) {
	    push @arr, [ $_ ];
	    next;
	}
	tr/ \t\r\n/ /s;
	s/^ //;
	s/ $//;
	my @fld = split(/ ?\/ ?/);
	next if (@fld < 4);
	push @arr, \@fld;
    }

    @arr;
}

sub mkstr(@) {
    my $A = "
pitchTranspose = c
midiTempo = { }
BS = { }
PS = { }
";
    my $B;

    for my $r (@_) {
	if (@$r == 1) {
	    $A .= $$r[0];
	    $B .= $$r[0];
	    next;
	}
	my ($abbr, $pitch, $clef, $lname, $sname, $mname, $mpan) = @$r;
	#print join(" | ", ($abbr, $pitch, $clef, $lname, $sname, $mname, $mpan)), "\n";
	if (defined($clef{$clef})) {
	    $clef = $clef{$clef};
	}
	my $Init   = "init${abbr}";
	my $Pitch  = "pitch${abbr}";
	my $Clef   = "clef${abbr}";
	my $Name   = "name${abbr}";
	my $Midi   = "midi${abbr}";
	my $Mus    = "mus${abbr}";
	my $Voice  = "voice${abbr}";
	my $kVoice = "kvoice${abbr}";
	my $Staff  = "staff${abbr}";
	my $kStaff = "kstaff${abbr}";
	my $mStaff = "mstaff${abbr}";

	if ($pre) {
	    $Init   = "${abbr}Init";
	    $Pitch  = "${abbr}Pitch";
	    $Clef   = "${abbr}Clef";
	    $Name   = "${abbr}Name";
	    $Midi   = "${abbr}Midi";
	    $Mus    = "${abbr}Mus";
	    $Voice  = "${abbr}Voice";
	    $kVoice = "${abbr}Kvoice";
	    $Staff  = "${abbr}Staff";
	    $kStaff = "${abbr}Kstaff";
	    $mStaff = "${abbr}Mstaff";
	}

	my $Klingande = "";
	if ($klingande) {
	    $Klingande = "\\transpose c \\$Pitch ";
	}

	my $With = "";
	if ($with) {
	    $With = "\\with \\$Name "
	}

	$A .= "
$Mus = \\relative f {
}
$Init = { }
$Pitch = $pitch
$Clef = { \\clef \"$clef\" }
$Name = {
  \\set Staff.instrumentName = #\"$lname \"
  \\set Staff.shortInstrumentName = #\"$sname \"
}
$Midi = {
  \\set Staff.midiInstrument = #\"$mname\"
  \\set Staff.midiPanPosition = #$mpan
}
";

	# \BS = Bar structure, where to place bar lines
	# \PS = Page structrue, where to place \breaks and such
	$B .= "
$Voice  = \\context Voice = $Voice { \\$Init \\$Mus }
$kVoice = ${Klingande}\\$Voice
$Staff  = \\transpose c \\pitchTranspose \\new Staff ${With}<< \\PS        \\BS \\$Clef \\$Voice  >>
$kStaff = \\transpose c \\pitchTranspose \\new Staff ${With}<< \\PS        \\BS \\$Clef \\$kVoice >>
$mStaff = \\transpose c \\pitchTranspose \\new Staff        << \\midiTempo \\BS \\$Midi \\$kVoice >>
";
    }

    ( $A, $B );
}

sub main() {
    if (@ARGV == 0) {
	my $file = "";
	my $fi = \*STDIN;
	my $fa = \*STDOUT;
	my $fb = \*STDOUT;
	my @arr = rd($file,$fi);
	my ($A, $B) = mkstr(@arr);
	print $fa $A;
	print $fb $B;
    } else {
	for my $file (@ARGV) {
	    my $stem = $file;
	    $stem =~ s/\.[^\.]*$//;

	    my $fi;
	    if (!open($fi, "<", $file)) {
		warn("cannot open \"$file\"");
		next;
	    }

	    my $fa;
	    my $file_a = $stem . $ext_a;
	    if (!open($fa, ">", $file_a)) {
		warn("cannot open \"$file_a\"");
		close($fi);
		next;
	    }

	    my $fb;
	    my $file_b = $stem . $ext_b;
	    if (!open($fb, ">", $file_b)) {
		warn("cannot open \"$file_b\"");
		close($fi);
		close($fa);
		next;
	    }

	    my @arr = rd($file, $fi);
	    my ($A, $B) = mkstr(@arr);

	    print $fa $A;
	    print $fb $B;

	    close($fi);
	    close($fa);
	    close($fb);
	}
    }
}

main();

__END__
# example input file data
# abbr / instr pitch / def.clef / name / name / midi instr / midi pan
Coa / g / g / Corno I  / CoI  / flute / 0
Cob / g / g / Corno II / CoII / flute / 0
Trx / d / g / Tromba / Tr / / 0

Oba / c / g / Oboe I   / ObI  / oboe  / 0
Oba / c / g / Oboe I   / ObI  / oboe  / 0
Obb / c / g / Oboe II  / ObII / oboe  / 0
Oca / c / a / Oboe da caccia / OC / oboe / 0
Oaa / c / a / Oboe d'amore / OA / oboe / 0

Sop / c / s / Soprano / Sop / voice oohs / 0
Alt / c / a / Alto / Alt / voice oohs / 0
Ten / c / t / Tenore / Ten / voice oohs / 0
Bas / c / b / Basso / Bas / voice oohs / 0

Con / c / b / Continue / BC / organ / 0

Vpx / ? / g / Violino piccolo / Vp / string / 0
Via / c / g / Violino I / ViI / string / 0
Vib / c / g / Violino II / ViII / string / 0
Vax / c / a / Viola / Va / string / 0
