#!/usr/bin/perl -w

#
# Standard Perl modules
#
use warnings ;
use Getopt::Long;
use XML::LibXML;

@TBMXDATA=(
    ["neg.eps",'/TBM/Physical_Cell_Description/Electrode[@type="Anode"]//ActiveMaterial/m_dPorosity',"percentage"],
    ["sep.eps",'/TBM/Physical_Cell_Description/Separator[@idx="1"]/m_dPorosity',"percentage"],
    ["pos.eps",'/TBM/Physical_Cell_Description/Electrode[@type="Cathode"]//ActiveMaterial/m_dPorosity',"percentage"],
    ["neg.epsp",'/TBM/Physical_Cell_Description/Electrode[@type="Anode"]//Binder/../m_dVolfrac',"fraction"],
    ["neg.epsf",'/TBM/Physical_Cell_Description/Electrode[@type="Anode"]//CondAid/../m_dVolfrac',"fraction"],
    ["pos.epsp",'/TBM/Physical_Cell_Description/Electrode[@type="Cathode"]//Binder/../m_dVolfrac',"fraction"],
    ["pos.epsf",'/TBM/Physical_Cell_Description/Electrode[@type="Cathode"]//CondAid/../m_dVolfrac',"fraction"],
    ["neg.stoich100soc",'/TBM/Physical_Cell_Description/Electrode[@type="Anode"]/m_dInitStoic',"num"],
    ["pos.stoich100soc",'/TBM/Physical_Cell_Description/Electrode[@type="Cathode"]/m_dInitStoic',"num"],
    ["neg.climax",'/TBM/REPORT/m_dRepNegCapacity',"mAh/cm^2"],
    ["pos.climax",'/TBM/REPORT/m_dRepPosCapacity',"mAh/cm^2"],
    ["cel.ce0",'/TBM/Physical_Cell_Description/Electrolyte/m_dSaltConcn',"mol/l"],
    ["neg.thcc",'/TBM/Physical_Cell_Description/Electrode[@type="Anode"]/Collector/m_dAvgThickness_um',"um"],
    ["neg.th",'/TBM/Physical_Cell_Description/Electrode[@type="Anode"]/CoatThickness_mm',"mm"],
    ["sep.th",'/TBM/Physical_Cell_Description/Separator/m_dAvgThickness_um',"um"],
    ["pos.th",'/TBM/Physical_Cell_Description/Electrode[@type="Cathode"]/CoatThickness_mm',"mm"],
    ["pos.thcc",'/TBM/Physical_Cell_Description/Electrode[@type="Cathode"]/Collector/m_dAvgThickness_um',"um"],
    ["cel.area",'/TBM/Physical_Cell_Description/Settings/m_dActiveArea',"m^2"],
    ["neg.ecd0ref",'/TBM/SIMMOD/__LABEL[text()="Distributed NP"]/../Negative_Particle/Pre-Exp_BATML_Space_Factor_BATML_Comma_',"mA/cm^2"],
    ["pos.ecd0ref",'/TBM/SIMMOD/__LABEL[text()="Distributed NP"]/../Positive_Particle/Pre-Exp_BATML_Space_Factor_BATML_Comma_',"mA/cm^2"],
    ["neg.Dsref",'/TBM/Physical_Cell_Description/Electrode[@type="Anode"]//ActiveMaterial/m_dDCoeff_cm2pers',"cm^2/s"],
    ["pos.Dsref",'/TBM/Physical_Cell_Description/Electrode[@type="Cathode"]//ActiveMaterial/m_dDCoeff_cm2pers',"cm^2/s"],
    ["neg.afa",'/TBM/SIMMOD/__LABEL[text()="Distributed NP"]/../Negative_Particle/Anodic_BATML_Space_Transfer_BATML_Space_Coefficient',"none"],
    ["neg.afc",'/TBM/SIMMOD/__LABEL[text()="Distributed NP"]/../Negative_Particle/Cathodic_BATML_Space_Transfer_BATML_Space_Coefficient',"none"],
    ["pos.afa",'/TBM/SIMMOD/__LABEL[text()="Distributed NP"]/../Positive_Particle/Anodic_BATML_Space_Transfer_BATML_Space_Coefficient',"none"],
    ["pos.afc",'/TBM/SIMMOD/__LABEL[text()="Distributed NP"]/../Positive_Particle/Cathodic_BATML_Space_Transfer_BATML_Space_Coefficient',"none"],
    ["neg.ex",'/TBM/SIMMOD/__LABEL[text()="Distributed NP"]/../m_dNegBruggeman',"none"],
    ["pos.ex",'/TBM/SIMMOD/__LABEL[text()="Distributed NP"]/../m_dPosBruggeman',"none"],
    ["neg.condref",'/TBM/SIMMOD/__LABEL[text()="Distributed NP"]/../m_dNegEtrdeECond',"S/cm"],
    ["pos.condref",'/TBM/SIMMOD/__LABEL[text()="Distributed NP"]/../m_dPosEtrdeECond',"S/cm"],
    ["neg.rsei",'/TBM/SIMMOD/__LABEL[text()="Distributed NP"]/../Negative_Particle/SEI_BATML_Space_Pre-Exp_BATML_Period__BATML_Space_Factor_BATML_Comma_',"ohm*cm^2"],
    ["pos.rsei",'/TBM/SIMMOD/__LABEL[text()="Distributed NP"]/../Positive_Particle/SEI_BATML_Space_Pre-Exp_BATML_Period__BATML_Space_Factor_BATML_Comma_',"ohm*cm^2"],
    ["neg.cdl",'/TBM/SIMMOD/__LABEL[text()="Distributed NP"]/../Negative_Particle/Double-layer_BATML_Space_Capacitance_BATML_Comma_',"F/m^2"],
    ["pos.cdl",'/TBM/SIMMOD/__LABEL[text()="Distributed NP"]/../Positive_Particle/Double-layer_BATML_Space_Capacitance_BATML_Comma_',"F/m^2"],
    ["neg.eactecd0",'/TBM/SIMMOD/__LABEL[text()="Distributed NP"]/../Negative_Particle/Activation_BATML_Space_Energy',"J/mol-K"],
    ["pos.eactecd0",'/TBM/SIMMOD/__LABEL[text()="Distributed NP"]/../Positive_Particle/Activation_BATML_Space_Energy',"J/mol-K"],
    ["neg.eactDs",'/TBM/Physical_Cell_Description/Electrode[@type="Anode"]//ActiveMaterial/m_dEa',"J/mol"],
    ["pos.eactDs",'/TBM/Physical_Cell_Description/Electrode[@type="Cathode"]//ActiveMaterial/m_dEa',"J/mol"],
    ["neg.dUdT",'/TBM/Physical_Cell_Description/Electrode[@type="Anode"]//ActiveMaterial/EquilData[@idx="1"]/dEqData_dEdT',"none","array"],
    ["neg.xdUdT",'/TBM/Physical_Cell_Description/Electrode[@type="Anode"]//ActiveMaterial/EquilData[@idx="1"]/dEqData_xt',"none","array"],
    ["pos.dUdT",'/TBM/Physical_Cell_Description/Electrode[@type="Cathode"]//ActiveMaterial/EquilData[@idx="1"]/dEqData_dEdT',"none","array"],
    ["pos.xdUdT",'/TBM/Physical_Cell_Description/Electrode[@type="Cathode"]//ActiveMaterial/EquilData[@idx="1"]/dEqData_xt',"none","array"],
    ["neg.u",'/TBM/Physical_Cell_Description/Electrode[@type="Anode"]//ActiveMaterial/EquilData[@idx="1"]/dEqData_E',"none","array"],
    ["neg.x",'/TBM/Physical_Cell_Description/Electrode[@type="Anode"]//ActiveMaterial/EquilData[@idx="1"]/dEqData_x',"none","array"],
    ["pos.u",'/TBM/Physical_Cell_Description/Electrode[@type="Cathode"]//ActiveMaterial/EquilData[@idx="1"]/dEqData_E',"none","array"],
    ["pos.x",'/TBM/Physical_Cell_Description/Electrode[@type="Cathode"]//ActiveMaterial/EquilData[@idx="1"]/dEqData_x',"none","array"],
    );

my $pgnam=$0;                # program name
my @VERSION=('major'=>1,
             'minor'=>2,
             'date'=>04032014);

#
# Process the command line
#
my $DEBUG=0;
my ($VERBOSE,$HELP,$VERSION);
my $XML='on';
{ # process options
    GetOptions(
        "xml=s"     => \$XML,
        "verbose"   => \$VERBOSE,
        "debug"     => \$DEBUG,
        "version"   => \$VERSION,
        "help"      => \$HELP,
        );
}

(&help_print() && exit) if $HELP;;
if($VERSION){
    print STDERR "@VERSION\n";
    exit;
}

if(@ARGV < 2){
    die "Usage: $pgnam [options ...] tbmx_input_file svm_output_file
options:
  --xml=(on|off)
  --verbose
  --debug
  --version
  --help\n";
}

($fin,$fout)=@ARGV;
open my($IFILE), $fin or die $!;
$doc = XML::LibXML->load_xml(IO => $IFILE);

open(my $OFILE, '>', $fout) or die $!;

foreach my $ivar ( @TBMXDATA ){
    my ($var, $xp, $unit, $dtype)=@{ $ivar };
    my @nodes=$doc->findnodes( $xp );

    if(defined($dtype) && $dtype eq 'array' ){
	my ($iref, $aref);
	($iref, $aref)=&reorder_valuearray(\@nodes, 'idx');
	$" = ', ';
	print $OFILE "$var = \[ @{$aref} \]  \% \[$unit\]\n";
    }
    else{
	$content = 0;
	if(@nodes){
	    $node=shift @nodes;
	    $content = $node->textContent;
	    $content=~s/\s+.*$//;
	}
	print $OFILE "$var = $content \% \[$unit\]\n";
    }
}

sub help_print{
    print STDERR <<EOF

Converts TBM XML input file (tbmx_input_file) into SVM battery model
file (svm_output_file).

Program errors messages indicate errors in the input file.

Program switches:

--help    This help.

--xml=(on|off)
          Write XML declaration as the first line of the ParameterList
          XML file. Default=on.

--verbose Add processing printouts as the code executes.

--debug   Create debug files for finding the errors in the converter
          program. Does not help much in tracing invalid input.

EOF
}

sub reorder_valuearray{
    my ($nodes, $idxname) = @_;
    my %aryh;
    my @index;
    my @value;

    foreach ( @{ $nodes } ){
        my $k=$_->getAttribute( $idxname );
        my $v=$_->textContent;
        $aryh{ "$k" } = $v;
    }

    my @an=sort by_number keys(%aryh);
    foreach ( @an ){
        push @index, $_;
        push @value, $aryh{$_};
    }

    return (\@index, \@value);
}

sub by_number {
    $a <=> $b;
}
