#!/usr/bin/perl -w

use strict;
use Data::Dumper;

my $voice_sep = '[]{}/\\';
sub Usage() {
    print
"Usage:
	mknew.pl <dir> <name> <no. of parts> <voice and instrument names  $voice_sep>
Where:
	<... names> = name1 name2 ...
Example:
	Mknew.pl stabat_mater stabat_mater 9 '{ Oba Obb } { Via Vib Va } [ Can Alt Ten Bas ] { Vc Fag BC }'
	Mknew.pl missa missa_a3_la_minore 4 '[ Can Alt Bas ]'
	Mknew.pl tomorrow tomorrow 1 \[ s a t b \]
";
    exit 0;
}
my @num = split(//, "abcdefghjk");
my %num;
for (my $ix = 0; $ix < @num; $ix++) { $num{$num[$ix]} = $ix; }

sub alfaNum($) {
    my $alfa = shift;
    my @alfa = split(//,$alfa);
    my @num  = map { $num{$_} } @alfa;
    join("", @num);
}
sub numAlfa($) {
    my $num = shift;
    my $str = sprintf("%02d", $num);
    my @arr = split(//, $str);
    my @alfa = map { $num[$_] } @arr;
    join("", @alfa);
}

sub System(@) {
    my @arg = @_;
    system(@arg) == 0
	or die "system @arg failed: $?";
}
sub writing($$;$) {
    my $org_file = shift;
    my $str = shift;
    my $mode = shift // ">";

    my $file;
    if ($mode eq ">" && -r $org_file) {
	$file = "tt";
    } else {
	$file = $org_file;
    }
    if ($mode eq "!") { $mode = ">"; } # i.e. same as ">" but overwrite any old file

    open(FH, $mode, $file);
    print FH $str;
    close(FH);

    if ($file ne $org_file) {
	my $diff = `diff $org_file $file`;
	if ($diff ne "") {
	    print "diff $org_file $file: neq\n";
	    System("emacs", $org_file, $file); "-nw"
	}
    } elsif ($mode eq ">") {
	print "created $file\n";
    } elsif ($mode eq ">>") {
	print "appended to $file\n";
    } else {
	print "writing with \$mode = \"$mode\"\n";
    }
}

my $version = "\\version \"2.25.1\"\n";
sub mk_header($$) {
    my $name = shift;
    my $parts = shift // 1;

    my $str = $version;
    $str =
'
\include "../include/a4p.ly"

\header {
  title = ""
  dedication = ""
  subtitle = ""
  subsubtitle = ""

  composer = ""
  poet = ""
  arranger = ""

  instrument = ""
  meter = ""
}
\paper {
  %#(set-paper-size "a4")
  %left-margin = 10 \mm
  %line-width = 190 \mm
  %bottom-margin = 20 \mm
  %ragged-right = ##t
  %page-breaking = #ly:minimal-breaking
  %page-count = 2
}

%#(set-global-staff-size 16)

';
    for (my $ix = 1; $ix <= $parts; $ix++) {
	my $alfa = numAlfa(sprintf("%02d", $ix));
	$str .= "hdr$alfa = \"No. $ix\"\n";
    }
    writing("${name}_header_full.ily", $str);

    $str = $version .
'
\include "lilypond-book-preamble.ly"
\include "../include/choirbook.ly"

\paper {
  %#(set-paper-size "a4")
  %left-margin = 10 \mm
  %line-width = 190 \mm
  %bottom-margin = 20 \mm
  %ragged-right = ##t
  %page-breaking = #ly:minimal-breaking
  %page-count = 2
}

%#(set-global-staff-size 16)

';
    for (my $ix = 1; $ix <= $parts; $ix++) {
	my $alfa = numAlfa(sprintf("%02d", $ix));
	$str .= "hdr$alfa = { }\n";
    }
    writing("${name}_header_none.ily", $str);
}

sub mk_instr($@) {
    my $name = shift;
    my $str = "# variable name / transp. / clef / long name / short name / midi instr. / midi pan\n";
    for (@_) {
	next unless (m/[a-zA-Z]/);
	$str .= sprintf "%-5s / c / g / long / short / electric guitar (jazz) /  0\n", $_;
    }
    writing("${name}.instrument", $str);
}

sub mk_ily($$@) {
    my $name = shift;
    my $parts = shift;
    my @voice = @_;

    my $str = $version . '

% Primary source:
%
% others:
%

midiTempo = \relative f {
  \tempo 4 = 80
}
BS = \relative f {
}
PS = \relative f {
}

lorig = \lyricmode {
}

';
    my $lyr = 0;
    for (@voice) {
	if (m/^[][{}||]$/) {
	    if ($_ eq '[') {
		$lyr = 1;
	    } elsif ($_ eq ']') {
		$lyr = 0;
	    }
	    next;
	}
	next unless ($lyr);
	$str .= "
lyr$_ = \\context Lyrics = lyr$_ \\lyricmode {\n  a\n}\n"
    }
    for (@voice) {
	if (m/^[][{}||]$/) {
	    next;
	}
	$str .= "
mus$_ = \\relative f {
  \\key c \\major
  \\time 4/4

  f1 |
}
";
    }

    for (my $ix = 1; $ix <= $parts; $ix++) {
	my $num = sprintf("%02d", $ix);
	writing("${name}_$num.ily", $str);
    }
}

sub mk_ly($$@) {
    my $name = shift;
    my $parts = shift;
    my @voice = @_;

    my $pre = $version .
'
\include "score_glb.ily"
';
    my $tot = $pre;

    my $lyr = 0;
    my $voice_str = "";
    my %voice = ();
    my $cnt = 0;
    my $spc = "    ";
    my %str = ();
    for (@voice) {
	if (m/^[][{}||]$/) {
	    if ($_ eq '[') {
		$lyr = 1;
		$voice_str .= "$spc\\new ChoirStaff <<\n";
		$cnt++;
	    } elsif ($_ eq ']') {
		$lyr = 0;
		$voice_str .= "$spc>>\n";
		$cnt--;
	    } elsif ($_ eq '{') {
		$voice_str .= "$spc\\new GrandStaff <<\n";
		$cnt++;
	    } elsif ($_ eq '}') {
		$voice_str .= "$spc>>\n";
		$cnt--;
	    } elsif ($_ eq '/') {
		$voice_str .= "$spc\\new StaffGroup <<\n";
		$cnt++;
	    } elsif ($_ eq '\\') {
		$voice_str .= "$spc>>\n";
		$cnt--;
	    }
	    next;
	}
	my $str = "      \\staff$_\n";
	if ($lyr) {
	    $str .= "      \\lyricsto voice$_ \\lyr$_\n";
	}
	$voice{$_} = $str;
	$voice_str .= $str;
	$str{$_} = $pre;
    }

    for (my $ix = 1; $ix <= $parts; $ix++) {
	my $inc_file = sprintf("%s_%02d.ily", $name, $ix);
	my $alfa = numAlfa($ix);

	my $strbeg = "
%%%%%%%%%%

\\include \"$name.instr_ily\"

";
	my $stra =
"%pitchTranspose = bes,
%clef = { \\clef  }
% \"french\" \"treble\" \"soprano\" \"mezzosoprano\" \"alto\" \"baritone\" \"varbaritone\" \"tenor\" \"treble_8\" \"bass\"

\\include \"$inc_file\"
\\include \"$name.staff_ily\"

\\score {
  \\header { piece = \\hdr${alfa} }
  <<
    \\scorePre
    \\scoreTimeSig
";
	my $strc =
'  >>
  \layout {
    \context {
      \Score
      %\override SpacingSpanner.base-shortest-duration = #(ly:make-moment 2/1)
    }
    \context {
      \Staff
      \RemoveEmptyStaves
      %\override VerticalAxisGroup.remove-first = ##t % this does not work with Ambitus_engraver
      \consists "Ambitus_engraver"
    }
    \context {
      \Voice
      %\consists "Ambitus_engraver"
    }
  }
}
';

	my $str = $strbeg . $stra . $voice_str . $strc;
	for (@voice) {
	    next unless (m/[a-zA-Z]/);
	    $str{$_} .= $strbeg;
	    $str{$_} .= "\\header { instrument = \\instrument$_ }
name$_ = { }

";
	    $str{$_} .= $stra . $voice{$_} . $strc;
	}
	$tot .= $str; # skip midi in the total file
	if (@voice > 1) {
	    $str .= '
\score {
  \unfoldRepeats
  <<
';
	    for (@voice) {
		next unless (m/[a-zA-Z]/);
		$str .= "      \\mstaff$_\n";
	    }
	    $str .=
'  >>
  \midi { }
}
';
	    writing(sprintf("%s_%02d.ly",$name,$ix), $pre . $str);
	}
    }
    if (@voice > 1) {
	writing("${name}.ly", $tot);
	for (@voice) {
	    next unless (m/[a-zA-Z]/);
	    writing("${name}_$_.ly", $str{$_});
	}
    } else {
	writing("${name}_$voice[0].ly", $tot);
    }
}

sub mk_tex($$) {
    my $name = shift;
    my $parts = shift;

    for (my $ix = 1; $ix <= $parts; $ix++) {
	my $pfx = sprintf("%s_%02d", $name, $ix);
	my $Name = $name;
	$Name =~ s/_/\\_/i;
	my $str =
"\\newpage
\\pagestyle{fancy}
%\\Ha{}
\\Hb{$Name}

Text av xx, musik av xx, i arrangemang av xx.

Texten...

\\vspace{1ex}
%\\def\\betweenLilyPondSystem#1{\\ifnum#1=6\\newpage\\noindent\\else\\\\[5mm]\\fi}
\\LYIND%
\\input{${pfx}-systems}
%\\renewcommand{\\betweenLilyPondSystem}[1]{\\\\[5mm]}
";

	writing($pfx . ".tex", $str);
    }

    my $str =
'\documentclass[a4paper,twoside,openany,10pt,swedish]{book}
%\documentclass[a4paper,twoside,openany,10pt,swedish,draft]{book}

\usepackage[swedish]{babel}
\usepackage[utf8]{inputenc}
\selectlanguage{swedish}
%\usepackage{bookman}
\usepackage{graphicx}
\usepackage{verbatim}
%\usepackage[T1]{tipa}
\usepackage{array}
%\usepackage{mathabx}
%\usepackage{dvgloss}
\usepackage{relsize}
\usepackage{yfonts}
\usepackage{url}
\usepackage{ifthen}
\usepackage{multicol}
\setlength{\columnseprule}{0.2pt}

%\newcommand{\betweenLilyPondSystem}[1]{\\\\[5mm]}
%\newcommand{\TI}[0]{\textprimstress}
%\newcommand{\TB}[0]{\begin{tabular}{@{}p{43mm}p{52mm}p{51mm}@{}}}

\usepackage{fancyhdr}
%\renewcommand{\sectionmark}[1]{\markboth{#1}}
\rhead[\leftmark]{\rightmark}
\chead[\thepage]{\thepage}
\lhead[\rightmark]{\leftmark}
\lfoot[]{}
\cfoot[]{}
\rfoot[]{}
\renewcommand{\headrulewidth}{0pt}
\raggedbottom
%\fancypagestyle{plain}{\fancyhead{}} % get rid of headers on plain pages

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% final page size after cutting is 270mm x 190mm
% a4 is 297 x 210, so I will:
%  run psbook and psnup to make a3 pages
%  staple them in the spine and fold it, which gives me a a4 booklet
%  cut ~10mm at the top and bottom of page to get correct page heigth
%  cut alond longside to get ~190mm page width

% I have decided to make smaller margins, 15mm inside and bottom, 10mm outsize and top

% horizontal dimensions
\setlength{\hoffset}{-25.4mm}
\setlength{\marginparwidth}{30mm} % margin notes not used, just to make diagram look nice
\setlength{\marginparsep}{2mm} % margin notes not used
\setlength{\oddsidemargin}{10mm}
\setlength{\evensidemargin}{35mm}
\setlength{\textwidth}{165mm}

% vertical dimensions
\setlength{\voffset}{-15.4mm}
\setlength{\topmargin}{10mm}
\setlength{\headheight}{4.5mm}
\setlength{\headsep}{5.5mm}
\setlength{\textheight}{235mm} % = 270 - 10 - 4.5 - 5.5 - 15 (bottom margin)
%\setlength{\footskip}{8.8mm} % Footer not used

\setlength{\unitlength}{1mm}

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

\newcommand{\antiqua}[1]{{\fontencoding{T1}\fontfamily{DayRoman}\selectfont #1}}

\newcommand{\person}[1]{\textbf{#1}}
\newcommand{\LYIND}{\noindent}
\newcommand{\NEWP}{\pagestyle{plain}\makebox[1mm]{}\newpage\pagestyle{fancy}}
%\newcommand{\LYIND}{\hspace{10mm}}
\newcommand{\ind}{\makebox[3mm]{}}
\newcommand{\I}{\makebox[1ex]{}}
\newcommand{\AST}{\raisebox{.2ex}{$\ast$}}
\newcommand{\life}[2]{(#1---#2)}
\newcommand{\Life}[2]{(\AST #1, \dag #2)}
\newcommand{\Exp}[1]{\raisebox{.7ex}{\relsize{-2}#1}}

%\newcommand{\hdr}{Rubriktext}
%\newcommand{\composer}{kompositoer}
%\newcommand{\writer}{foerfattare}
%\newcommand{\piece}[2]{% song title, composer / text writer
%  \thispagestyle{plain}
%  \section*{#1\markboth{#1}{#2}}%
%  \addcontentsline{toc}{section}{#1 (#2)}%
%}
\newcommand{\Ha}[1]{%
%  \markboth{\bf #1}{}%
%  \addtocontents{toc}{{\bf #1}}%
%}
%\newcommand{\Haa}[1]{%
%  \thispagestyle{plain}
  \section*{#1\markboth{{\bf #1}}{}}%
  \addcontentsline{toc}{chapter}{#1}%
}
\newcommand{\Hb}[1]{
%  \thispagestyle{plain}
  \section*{#1\markright{#1}}%
  \addcontentsline{toc}{section}{#1}%
}

%\def\everyglb{\relsize{-2}}
%\newcommand{\LatSv}[3]{
%  \hspace{2.5mm}
%  \makebox[73mm][t]{\gl{#1}{#2}}
%  \hspace{2.5mm}
%  \makebox[73mm][t]{\itshape #3}
%}

% 155 >= 4 + 73 + 2.5 + 73
\newcommand{\VersNo}[1]{\makebox[0mm][r]{\makebox[4mm][l]{#1}}}
\newcommand{\TwoCol}[2]{{
  \relsize{-1}\hspace{4mm}
  \parbox[t]{73mm}{\antiqua{#1}}
  \hspace{2.5mm}
  \parbox[t]{73mm}{\itshape #2}
}}
\newcommand{\NL}{\\\\[1.5ex]}
%\newcommand{\La}[1]{#1\\\\[0.0ex]}
%\newcommand{\Lb}[1]{\makebox[0.6em]{}#1\NL}

\newcommand{\citat}[1]{
\begin{quote}
  \begin{multicols}{2}
    \relsize{-1}
    #1
  \end{multicols}
\end{quote}
}
\newcommand{\rtext}[2]{
  \noindent%
  #1:\\\\[0.3ex]
  \makebox[1em]{ }
  \begin{minipage}[t]{150mm}
    #2
  \end{minipage}
  \vspace{-1ex}
}

%%%%%%%%%%%%%%%%%
\begin{document}
%\testpagelayout

\pagestyle{empty}
\vfill
\begin{centering}
  \vspace{25mm}
  \bf
  \Huge
  Requiem\\\\[0.5ex]
  Mozart\\\\

  \vspace{20mm}
  \large
  KV 626\\\\
  Körpartitur\\\\
\end{centering}
\vfill
\normalsize

%%%%%%%%%%%%%%%%%
\newpage

\makebox[1mm]{}
\vfill

\subsection*{Källor, produktion och copyright}

\rtext{Latinsk text}{
  från den katolska dödsmässan \antiqua{Missa pro defunctis}\\\\
}

\rtext{Översättningar}{
  Karl Hammar\\\\
  \url{http://dev.kln.nu/musik/latinska-sangtexter-i-oversattning/}\\\\
  m.fl.\\\\
}

%\urldef{\imspl}\url{http://imslp.org/wiki/Requiem_in_D_minor,_K.626_%28Mozart,_Wolfgang_Amadeus%29}
%\urldef{\cpdl}\url{http://www2.cpdl.org/wiki/index.php/Requiem,_KV_626_%28Wolfgang_Amadeus_Mozart%29}
\urldef{\imspl}\url{http://imslp.org/wiki/Requiem_in_D_minor,_K.626_(Mozart,_Wolfgang_Amadeus)}
\urldef{\cpdl}\url{http://www2.cpdl.org/wiki/index.php/Requiem,_KV_626_(Wolfgang_Amadeus_Mozart)}
\rtext{Musik}{\footnotesize
  \url{http://www2.cpdl.org/wiki/images/sound/moz-6261.mid} {\dots} \url{moz-626c.mid}\\\\
  \url{http://imslp.org/images/c/c8/PMLP02751-Mozart_Requiem_score.pdf}\\\\
  \url{http://www2.cpdl.org/wiki/images/f/fb/K626_Requiem_Urtext_PML.pdf}\\\\
  \imspl\\\\
  \cpdl\\\\
}

\rtext{Omslagsbild}{
  Alunda kyrka mot öster med morgondimma
}

\rtext{Kod och andra filer för att generera dessa noter}{
  \url{git://turkos.aspodata.se/musik.git}\\\\
  \copyright Karl Hammar, 2014\\\\
  Förutom musiken som är allmängods och citat och översättningar gjorda av andra.\\\\

  \footnotesize
  Dessa filer är fritt tillgängliga och du kan förmedla och/eller förändra dem
  enl. villkoren för GNU General Public License så som denna licens är publicerad
  av ``Free Software Foundation.
  Ni är fri att använda version 2 eller en senare version av dessa villkor.
  För licenstexten, se \url{http://www.gnu.org/licenses/}\\\\
}

\rtext{Använda program}{
  Noter: \url{htt://www.lilypond.org/}\\\\
  Text: \url{http://tug.org/texlive/}\\\\
  Bilder: \url{ftp://ftp.gimp.org/pub/gimp/}\\\\
  m.fl.\\\\
}

\rtext{Sättning och tryck}{
\person{Aspö Data}\\\\
Lilla Aspö 148\\\\
742 94 Östhammar\\\\
}

%%%%%%%%%%%%%%%%%
\newpage
\tableofcontents
%%%%%%%%%%%%%%%%%
\newpage
\Ha{Introduktion}


%%%%%%%%%%%%%%%%%
';

    for (my $ix = 1; $ix <= $parts; $ix++) {
	my $pfx = sprintf("%s_%02d", $name, $ix);
	$str .= "\\include{$pfx}\n";
    }

    $str .=
'%%%%%%%%%%%%%%%%%
\newpage
\pagestyle{empty}
\ind

\end{document}
';

    writing($name . "_bk.tex", $str);
}

sub main() {
    my $cmdline = "$0 '" . join("' '", @ARGV) . "'\n";
    my $dir   = shift @ARGV;
    my $name  = shift @ARGV;
    my $parts = shift @ARGV;
    #my @voice = @ARGV;

    my @voice;
    for my $voice (@ARGV) {
	push @voice, split(/ /, $voice);
    }

    if (!defined($name)) { Usage(); }
    `mkdir -p $dir`;

    chdir $dir;
    writing("cmdline", $cmdline, "!");
    for (qw/Makefile score_glb.ily/) {
	my $cmd = "ln -sf ../include/$_ .";
	#print $cmd, "\n";
	`$cmd`;
    }

    mk_header($name, $parts);
    mk_instr($name, @voice);
    mk_ily($name, $parts, @voice);
    mk_ly($name, $parts, @voice);
    mk_tex($name, $parts);

    print `make dep`;
}

main();

__END__

    if (@ARGV == 0) {
	my $str = "";
	for (my $ix = 1; $ix <= 15; $ix++) {
	    my $alfa = numAlfa(sprintf("%02d", $ix));
	    $str .= "hdr$alfa = { }\n";
	}
	print $str;
	return;
    }
