#!/usr/bin/perl -w

# assumptions made about the quotes file:
# - quotes are separated with /^--/, and followed by optional flags
# - all blank lines will be dumped from a quote

use POSIX;

$quotes_file_name="~/docs/quotes";
$delim_str="--";
$geek_code_file_name="~/.geek_code";
$sig_file_name="~/.signature";
$last_quote_file="~/.last_quote";
$keep_newlines_flag=0;
$max_col=78;

@sig_boilerplate=("Maciej Kalisiak",
		  "mac\@dgp.utoronto.ca",
		  "www.dgp.utoronto.ca/~mac",
		  "PGP key: finger|web");

if (!open (QUOTES,glob($quotes_file_name))) {
  die "Couldn't open file ".$quotes_file_name."\n";
}
@quotes_file_lines=<QUOTES>;
close(QUOTES);

# expand tabs to 8-column spacing
$line=0;
while($line < @sig_boilerplate) {
  $_=$sig_boilerplate[$line];
  1 while s/\t+/' ' x (length($&)*8 - length($`)%8)/e;
  $sig_boilerplate[$line]=$_;
  $line++;
}

if (!open (GEEKCODE,glob($geek_code_file_name))) {
  die "Couldn't open geek code file ".$geek_code_file_name."\n";
}
@geek_code_lines=<GEEKCODE>;
close(GEEKCODE);

$sig_file_name_full = glob($sig_file_name);
if (!open (SIG,"> $sig_file_name_full") ) {
  die "Couldn't open ".$sig_file_name." for output.\n";
}

### figure out at which column the quote is supposed to start
$quote_col=0;
foreach $_ (@sig_boilerplate) {
    $quote_col=(length($_)+1) if ((length($_)+1) > $quote_col);
}

### first quote is index 0
### pass in the desired index in $_[0]
sub get_nth_quote {
  @res = ();
  $quote_num = 0;
  my $quote_flags="";
  foreach (@quotes_file_lines) {
    if (/^$delim_str/) {
      $quote_flags=$';
      ++$quote_num;
    } elsif ($quote_num==$_[0] && !/^\s*$/) {
      push(@res,$_);
      if($quote_flags =~ /k/) {
	$keep_newlines_flag=1;
      }
    }
    if ($quote_num > $_[0]) {
      last;
    }
  }

  # return the result
  @res;
}

sub count_quotes {
  $quotes_num = 0;
  foreach (@quotes_file_lines) {
    if (/^$delim_str/) {
      ++$quotes_num;
    }
  }
  $quotes_num + 1;
}

$quotes_total = count_quotes();

# find out what the last used quote was
if (!open (LQ_IN,glob($last_quote_file)) ) {
  srand;
  $which_quote = floor(rand $quotes_total);
} else {
  $which_quote = <LQ_IN>+1;
  if ($which_quote >= $quotes_total) {
    $which_quote = 0;
  }
  close(LQ_IN);
}

# prepare the quote
@quote_lines = get_nth_quote( $which_quote );
@clean_quote_lines = ();
foreach (@quote_lines) {
    chop;
    s/^\s*(.*)\s*$/$1/;
    push(@clean_quote_lines,$_);
    push(@clean_quote_lines," \\n ") if $keep_newlines_flag;
}
$_ = "@clean_quote_lines";

@words = ();
@words = split(/\s+/);


# now assemble the sig
$cur_col=0;
$cur_row=0;
$cur_line="";
@fmt_lines=();

while(1) {
    foreach (@words) {
	if($cur_col == 0) {
	    local $_=shift @sig_boilerplate || " ";
	    $cur_line=$_." "x($quote_col - length($_));
	    $cur_col = $quote_col;
	}

	if ($_ eq "\\n") {
	    push(@fmt_lines,$cur_line);
	    $cur_line = "";
	    $cur_col = 0;
	    $cur_row++;
	} elsif (length($_)+$cur_col >= $max_col) {
	    push(@fmt_lines,$cur_line);
	    $cur_line = "";
	    $cur_col = 0;
	    $cur_row++;
	    redo;		# redo with the current word
	} else {
	    $cur_line .= " $_";
	    $cur_col += length($_)+1;
	}
    }
    
    if (length $cur_line) {
	push(@fmt_lines,$cur_line);
	$cur_col = 0;
	$cur_row++;
	$cur_line = "";
    }
    
    # add GEEK code if the original quote only took one line
    if (@fmt_lines == 1) {
	$_="@geek_code_lines";
	@words = split(/\s+/);
	unshift @words, "\\n";	# so we get a blank in the quote
	next;
    } else {
	last;
    }
}

# use up any remaining sig_boilerplate lines
push @fmt_lines, @sig_boilerplate if(@sig_boilerplate);

# now dump the formatted text into the sig file
foreach (@fmt_lines) {
    print SIG "$_\n";
}
close(SIG);

# save the quote we used now
$out_lq_file = glob($last_quote_file);
if (!open(LQ_OUT,"> $out_lq_file") ) {
  die "Couldn't open $out_lq_file file for output\n";
}
print LQ_OUT $which_quote;
close(LQ_OUT);

