#!/usr/bin/perl -i.bak

use English;


$EASYLATEXSTORE_RESERVED_WORD = 'EASYLATEXSTORE';
use vars qw($StorageIndex @Stored);
$StorageIndex = 0;


## get input
undef $INPUT_RECORD_SEPARATOR;
$file = <>;

 #print STDERR "I got:**********************\n".$file."***************\n";

## transform it

$equalsRE = '(?:=|\\\\Rightleftarrow|\\\\Rightarrow|\\\\Leftarrow|\\\\geq|\\\\leq)';
#$equalsRE = '=';
#$mathLinesepStuffRE = '(?:\\\\Rightleftarrow|\\\\Rightarrow|\\\\Leftarrow)?';
$mathLinesepStuffRE = '';



my $beginMathRE = '\\\\begin{(?:eqnarray|align)\\*?}';
my $endMathRE = '\\\\end{(?:eqnarray|align)\\*?}';

#my $notEqualsDoubleBackslashNotAmpersandRE = '(?:(?!\\\\\\\\)[^=&\n])*';
my $notEqualsDoubleBackslashNotAmpersandRE = '(?:(?!\\\\\\\\)(?!\\\\)(?!'.$equalsRE.')[^\n&])*';
my $notEqualsDoubleBackslashNotAmpersandRE = '(?:(?!\\\\\\\\)(?!'.$equalsRE.')[^\n&])*';
    ## confusing!! aloowed ampersand without changing name!
#my $doubleBlackslashOrEndRE = '(?:\n\\\\\\\\|\n)';
my $doubleBlackslashOrEndRE = '(?:\n\\\\\\\\'.$mathLinesepStuffRE.'|\n)';


my $lineInMathModeRE = '(?:(?!\\\\\\\\).)*' . $doubleBlackslashOrEndRE;    
my $lineWithOneEqualsRE = $notEqualsDoubleBackslashNotAmpersandRE . '(?:'.$equalsRE.'|\\\\geq|\\\\leq)' . $notEqualsDoubleBackslashNotAmpersandRE . $doubleBlackslashOrEndRE;



$mainRegexp = "($beginMathRE\n?$lineInMathModeRE(?:$lineWithOneEqualsRE(?:$doubleBlackslashOrEndRE)*)+$endMathRE\n)";
#$mainRegexp = "($beginMathRE\n$lineInMathModeRE$notEqualsDoubleBackslashNotAmpersandRE(?:$equalsRE)$notEqualsDoubleBackslashNotAmpersandRE$doubleBlackslashOrEndRE(.|\n)*?$endMathRE\n)";
#$mainRegexp = "($beginMathRE\n$lineInMathModeRE$notEqualsDoubleBackslashNotAmpersandRE(?:$equalsRE)$notEqualsDoubleBackslashNotAmpersandRE(.|\n)*?$endMathRE\n)";
#$mainRegexp = "(($beginMathRE\n)$lineInMathModeRE((?:$notEqualsDoubleBackslashNotAmpersandRE(?:$equalsRE)$notEqualsDoubleBackslashNotAmpersandRE$doubleBlackslashOrEndRE)+)(.|\n)*?$endMathRE\n)";



#print STDERR "REGEXP=" . $mainRegexp . "\n";


#$file =~ /$mainRegexp/;

#$file =~ s/($beginMathRE\n$lineInMathModeRE(?:$lineWithOneEqualsRE)+$endMathRE\n)/processEqnArray($1)/eg;

#print STDERR "1: $1\n\n";
#print STDERR "2: $2\n\n";
#print STDERR "3: $3\n\n";
#print STDERR "4: $4\n\n";
#print STDERR "5: $4\n\n";
#print STDERR "6: $4\n\n";

$file = storeTexts($file);

    #print STDERR $file;
$file =~ s/$mainRegexp/processEqnArray($1)/eg;
$file = unstoreTexts($file);

print $file; 

#print STDERR "I sent:**********************\n".$file."***************\n";

##############
# end MAIN
##############









sub processEqnArray {
    my ($block) = @_;

    #print STDERR "**************\nEntered EqnArray\n****************\n";
    #print STDERR $block;

$block = unstoreTexts($block);

#    if (! ($block =~ /$beginMathRE\n$lineWithOneEqualsRE(?:$lineWithOneEqualsRE)+$endMathRE\n/) )
#	{
#	    $block =~ s/(}\n?)/$1&/;   ## right after the \begin{}, add a '&' 
#	}

    $block = alignEquals($block);
    $block = alignTextAtBeginningOrEndOfLine($block);

    if ($block =~ /$beginMathRE\n\s*[^&].*\n(\s*\\\\\s*&.*\n)+$endMathRE\n/)
	{
	    #print STDERR "*\n*\n*\nyes\n\n";
	    $block =~ s/(}\n?)/$1&/;   ## right after the \begin{}, add a '&' 
	}


     $block = blankLinesToIntertext($block);
     $block = removeLinefeedAfterBeginOrIntertext($block);


    return $block;
}


# sub processEqnArrayAndIndentFirstLine {
#     my ($block) = @_;

#     print STDERR $block;

#     $block =~ s/(}\n?)/$1&/;   ## right after the \begin{}, add a '&&'     
#     $block = processEqnArray($block);

#     return $block;
# }


sub alignEquals {
    my ($block) = @_;


    #print STDERR "AEb: $block";
    $block = storeTexts($block);    

#    $block =~ s/(?<!\\\\)($equalsRE)/&\1/g;
    $block =~ s/($equalsRE)/&\1/g;
    #$block =~ s/\\leq/&\\leq/g;
    #$block =~ s/\\geq/&\\geq/g;

    $block = unstoreTexts($block);

    #print STDERR "AEf: $block";

    return $block;
}


sub alignTextAtBeginningOrEndOfLine {
    my ($block) = @_;

    $block = alignTextAtBeginningOfLine($block);
    $block = alignTextAtEndOfLine($block);

    return $block;
}

sub alignTextAtBeginningOfLine {
    my ($block) = @_;

    $textAtBeginningOfLineRE = '^(\\\\\\\\\\\\textrm{[^}]*?)}';

###    if ($block =~ s/^((?:\\\\)*\s*\\textrm{[^}]*?)}/$1 } & /mg) {print STDERR "yes!\n"};
#    if ($block =~ s/^(\\\\\\textrm{[^}]*?)}/$1 } & /mg) {print STDERR "yes!\n"};
    if ($block =~ /$textAtBeginningOfLineRE/mg) 
    {
#	print STDERR "found it!\n";

	$block =~ s/$textAtBeginningOfLineRE/$1 } && /mg;
        $block =~ s/\\\\/\\\\&& /g ;
        $block =~ s/(}\n?)/$1&&/;   ## right after the \begin{}, add a '&&' 
        $block =~ s/^\\\\&& \s*\\textrm{/\\\\ \\textrm{/mg;
    }


    return $block;
}

sub alignTextAtEndOfLine {
    my ($block) = @_;

#    print STDERR $block;

    $block =~ s/\\textrm{([^}]*?}\s*)$/& \\textrm{ $1/mg;
	   # if a line ends in \textrm{...}
	   # then indent the \textrm, and add a space to the text inside of it

    return $block;
}


sub blankLinesToIntertext {
    my ($block) = @_;

    #print STDERR $block;
    $block =~ s/\\\\\n/\\\\\\intertext{}\n/mg;


    return $block;
}

sub removeLinefeedAfterBeginOrIntertext {
    my ($block) = @_;

    #print STDERR $block;

    $block =~ s/(\\begin{align}(?:\\label{[^}]+})?|\\intertext{[^}]*})\n\\\\/$1/mg;


    return $block;
}







###########
# "store" subroutines
###########


######################
# "store" subroutines
######################

sub storeTexts {
    my ($file) = @_;

#    print STDERR "TESTING for storage:$file\n\n";

    $file =~ s/(\\textrm{[^}]*})/store($1)/egs;
    $file =~ s/((?<!\\begin)(?<!\\end){[^}]*})/store($1)/egs;

    return $file;
}

sub unstoreTexts {
    my ($file) = @_;

#    print STDERR "UNSTORE:\n\n".$file;

    while ($file =~ s/${EASYLATEXSTORE_RESERVED_WORD}_(\d+)_${EASYLATEXSTORE_RESERVED_WORD}/$Stored{$1}/egs) {}

    return $file;
}



sub store {
    # got this idea from UseMod
  my ($toBeStored) = @_;

  $Stored{$StorageIndex} = $toBeStored;
  #print STDERR "STORED: $toBeStored\n";

#  print STDERR "REPLACEDW: ".${EASYLATEXSTORE_RESERVED_WORD}.'_' . $StorageIndex . '_'.${EASYLATEXSTORE_RESERVED_WORD};

  return ${EASYLATEXSTORE_RESERVED_WORD}.'_' . $StorageIndex++ . '_'.${EASYLATEXSTORE_RESERVED_WORD};
}




