#!/usr/bin/perl


sub usage {
    print "usage:\n
perl cmi2xml.pl -h : ceci
perl cmi2xml.pl -f 'cmi file' [ -o 'output file']\n";
}



#===== mieux que getopts
sub getArgs {
    my @args=@_;
    my $oldKey="";
    my %opts=();
    for $el (@args) {
	if ($el=~/^-/) {
	    $el=~s/-+//g;
	    $opts{$el}="";
	    $oldKey=$el;
	}
	else {
	    $opts{$oldKey}=$el;
	}
    }
    return %opts;
}

sub purgeCr
{
    while ($curChar eq "\n") {&readOne()};
}

sub readOne 
{
    $curChar=substr($source,$offset++,1);
    return $curChar;
}
    

sub readStartBlock
{
    my $curStr="";
    my %line;
    $line{name}="entete";
    while ((&readOne() ne '|') && ($curChar ne ']'))
    {
		&purgeCr();
		my $name=$curChar;
		while (&readOne() ne "\n")
		{
			if (!exists($trad->{$name})) 
			{
				$trad->{$name}=$name; 
			}
			$line{$trad->{$name}}.=$curChar;
		}
		if (($name eq 'C') && ($line{$trad->{$name}} =~ /^[A-Z,a-z]/)) {
			$line{$trad->{$name}}="";
		}
    }
    return \%line;
}

sub readBlock
{
    my $curStr="";
    my %line;
    $line{name}="mouvement";
    while ((&readOne() ne '|') && ($curChar ne ']'))
    {
	&purgeCr();
	my $name=$curChar;
	while (&readOne() ne "\n")
	{
	    if (!exists($trad->{$name})) 
	    {
		$trad->{$name}=$name; 
	    }
	    $line{$trad->{$name}}.=$curChar;
	}
    }
    return \%line;
}

sub convertFromType 
{
    my $type=shift;
    my $value=shift;

    if ($type =~ /initial|montant_franc|montant_euro/)
    {
	$value=~s/[+ ]//g;
	$value=~s/,/./g;
	return $value;
    }

    if ($type =~ /date/)
    {
	return $value;
    }
    
    if ($type =~ /compte|guichet|banque|devise/)
    {
	return $value;
    }
    
    return "<![CDATA[$value]]>";
}
#3 cas :
#
#1 - start file
#2 - [ (contenu) ]
#  2.1 - start contenu
#  2.2 - | (tuple) |
#      2.2.1 (C)(date)
#      2.2.2 (C)(libellé)
#      2.2.3 (C)(signe)(montant)
#      2.2.4 (C)(T)
#      2.2.5 (C)(Id.)
#      ...

#Values for tags ($trad->{$name})
$trad->{"\$"}="devise";
$trad->{"D"}="date";
$trad->{"X"}="X";
$trad->{"F"}="F";
$trad->{"I"}="initial";
$trad->{"L"}="libelle";
$trad->{"M"}="montant_devise";
$trad->{"N"}="montant_autre";
$trad->{"C"}="nocompte";
$trad->{"R"}="nomcompte";
$trad->{"B"}="banque";
$trad->{"A"}="guichet";


#Global var :
$offset=0;
$result="";
$source="";
@listMvt=();
$curChar="";


#print $source;


#==========================
# MAIN


#------------------------
#                       |
#Gestion des entrées :
my %opts=();
%opts=getArgs(@ARGV);

if(exists $opts{h}) {
    &usage();
    exit 0;
}

if (exists $opts{f}) {
    $file=$opts{f};
} else {
    &usage();
    exit 0;
}

if (exists $opts{o}) {
    $output=$opts{o};
} else {
    $output="";
}
#                       |
#------------------------


#Lecture File :
open(IN,"<$file");
while (<IN>) {    $source.=$_;   }
close IN;


#Start parsing

do {
  readStart:while (&readOne ne "[") {} ;
	
	push(@listMvt,&readStartBlock());
	
	while (($curChar ne "") && ($curChar ne "]"))
	{
		$ref_line=readBlock();
		push(@listMvt,$ref_line);
	}

}
	until ($offset >= (length($source)-1));

#END MAIN


#Writing XML...

if ($output) {
    open(OUT,">$output");
} else {
    *OUT=*STDOUT;
}

$firstCompte=0;
print OUT "<liste_mouvement>\n";
for $ref_line (@listMvt) 
{
	if ($ref_line->{name} eq "entete") 
	{
		print OUT "</compte>\n" if ($firstCompte);
		print OUT "<compte>\n";
		$firstCompte=1;
	}
    print OUT "<".$ref_line->{name}.">\n";
    for $key (keys(%{$ref_line})) {
	print OUT "\t<$key>".&convertFromType($key,$ref_line->{$key})."</$key>\n" if ($key ne "name");
    }
    print OUT "</".$ref_line->{name}.">\n";
}
print OUT "</compte>\n";
print OUT "</liste_mouvement>\n";

close OUT ;

