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

use English;

    use vars qw($EASYLATEXSTORE_RESERVED_WORD @MATH_MODE_SYMBOLS $MATH_MODE_SYMBOL_FILEPATH);

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

    $StorageIndex = 0;



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

## transform it

$openingSquareBracketRE = '(?:^|(?<=\s))\\[\\['; 
  # opening square bracket, either at the beginning of a line
  # or preceded by whitespace (note: this won't trigger if preceded by
  #                            brackets either) 
$closingSquareBracketRE = '(?<!\\\\)\\]\\]';

$file =~ s/${openingSquareBracketRE}([^\]\]]*?)${closingSquareBracketRE}'/matlabStyleMatrixTransposeReplace($1)/emgs;  # do transpose replaces first

$file =~ s/${openingSquareBracketRE}([^\]\]]*?)${closingSquareBracketRE}/matlabStyleMatrixReplace($1)/emgs; # now do the normal ones


## unescape \[ and \] s (which the user might use to escape things that weren't supposed to be easy matrices)
#$file =~ s/\\\[/[/g;
#$file =~ s/\\]/]/g;

$file = easyMatricesToMathMode($file);


## print output
print $file;
#print "\n";
#print STDERR $file;


######################
# subroutines
######################

sub matlabStyleMatrixReplace {
    my ($expr) = @_;

    my @rows;
    my $out;

    @rows = readInMatlabStyleMatrix($expr);
    $out = matrixToLatex(@rows);

    return $out;
}

sub matlabStyleMatrixTransposeReplace {
    my ($expr) = @_;

    my @rows;
    my $out;

    @rows = readInMatlabStyleMatrix($expr);
    @rows = transpose(@rows);
    $out = matrixToLatex(@rows);

    return $out;
}


sub readInMatlabStyleMatrix {
    my ($expr) = @_;
    
    my @inputRows;
    my @inputCols;
    my @rows;
    my @cols;
    my ($colIndex, $rowIndex);
    my $row;
    my $cols;

    @inputRows = split(/;/, $expr);
    for ($rowIndex = 0; $rowIndex <= $#inputRows; $rowIndex++) {
	$row = $inputRows[$rowIndex];
	$cols = []; $colIndex = 0;
	@inputCols = split(/ /, $row);
	foreach $col (@inputCols) {
	    if ($col =~ /^\W*$/) {next;}  # bypass whitespace
	    if ($col =~ /&/) {$cols[$colIndex++] = ''; next;} 
                                     # bypass column separators;
	                             #  this can be used to indicate an empty
	                             #  column.

	    $cols->[$colIndex++] = $col;
	}
	$rows[$rowIndex] = $cols;
    }

#    use Data::Dumper;
#    print Dumper(@rows);

#    print "ir = $#inputRows\n";

    return @rows;
} 

sub matrixToLatex {
    my @rows = @_;

    my @cols;
    my ($row, $out);
    my $colCount;
    my $colSpecifier;
    my $i;
    my $out;

    foreach $row (@rows) {
	@cols = @$row;
	$colCount = $#cols + 1; 
           # yeah, okay, so we do this for every row
	   # and we only need to do it once!
	foreach $col (@cols) {
	    $out .= "$col & ";
              
	}
	$out = substr($out,0,-3); 
           ## STRIP OFF THE EXTRA & THAT WE PUT AFTER THE LAST COLUMN
	$out .= "\n".'\\\\ ';
    }
    
    ## STRIP OFF THE \\  THAT WE PUT AFTER THE LAST LINE OF THE MATRIX
    $out = substr($out,0,-3);

    for ($i = 0; $i < $colCount; $i++) {
	$colSpecifier .= 'l';
    }

    $out = '\left[ \begin{array}{'.$colSpecifier.'}'."\n".'   ' . $out . '\end{array} \right]';

#    print STDERR "**************$out\n";

    return $out;
}


sub transpose {
    my @inRows = @_;
    my ($rowIndex,$colIndex);
    my @outRows;


    #TODO: put in error checking in case the # of columns in each row is not the same



    my @firstRow = @{$inRows[0]};



    for($rowIndex=0;$rowIndex<=$#firstRow; $rowIndex++)
    {
	@outRows[$rowIndex] = [];
	for($colIndex=0;$colIndex<=$#inRows; $colIndex++)
	{
#	    print STDERR "($rowIndex,$colIndex)";
	    @outRows[$rowIndex]->[$colIndex] = $inRows[$colIndex]->[$rowIndex];
	}
    }

#    use Data::Dumper;
#    print STDERR Dumper(@outRows);



    return @outRows;
}

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


    $file = storeMathModes($file);
    $file =~ s/(\\left\W.*?\\right\W)/\n\\begin{align*}\n$1\n\\end{align*}\n/gs;
    $file = unstoreMathModes($file);

    return $file;
}


######################
# store subroutines
######################


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

    ${notSlashRE_begin} = '(^|(?!\\).)';
    ${notSlashRE} = '(?!\\).';

    $file =~ s/(\\begin{align}.*?\\end{align})/store($1)/egs;
    $file =~ s/(\\begin{align\*}.*?\\end{align\*})/store($1)/egs;
    $file =~ s/(\\begin{eqnarray}.*?\\end{eqnarray})/store($1)/egs;
    $file =~ s/(\\begin{eqnarray\*}.*?\\end{eqnarray\*})/store($1)/egs;
    $file =~ s/(\\begin{equation}.*?\\end{equation})/store($1)/egs;
    $file =~ s/(\\begin{equation\*}.*?\\end{equation\*})/store($1)/egs;
    $file =~ s/(\\begin{verbatim}.*?\\end{verbatim})/store($1)/egs;

    $file =~ s/((?<!\\)\$.*?(?<!\\)\$)/store($1)/egs;

    return $file;
}

sub unstoreMathModes {
    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}.' ';
}
