#!/usr//bin/perl

# quick hack for CAEBAT to ECPower file converter
# will be written as xslt, this program is for testing of xpaths
# needs modules XML::LibXML and XML::Tidy

use warnings;
use strict;

# standard packages
use IO::File;
use Getopt::Long;

# non-standard packages
use XML::LibXML;
use XML::Tidy;

my ($TIDY, $DEBUG, $VERSION, $HELP);
{ # process options
    GetOptions(
	"tidy"      => \$TIDY,
	"debug"     => \$DEBUG,
	"version"   => \$VERSION,
	"help"      => \$HELP
	);
}

if ( $VERSION ) {
    print "C2ECPT version 0.1 date 01/25/13\n";
}
if ( $HELP ){
    &help_print();
}

&help_print_and_exit if @ARGV < 2;

my ($fi, $fo) = @ARGV;

my $fhi = new IO::File($fi, "r") or die "$fi: $!\n";   # input
my $doc = XML::LibXML->load_xml(IO => $fhi);
my $root  = $doc->documentElement();
close ($fhi);

# $fhi = new IO::File($ft, "r") or die "$ft: $!\n";   # input
# my $tmpl      = XML::LibXML->load_xml(IO => $fhi);

my $template=&set_template();
my $tmpl      = XML::LibXML->load_xml(string => $template);
my $root_tmpl = $tmpl->documentElement();

# close ($fhi);

my $xpc;
$xpc = XML::LibXML::XPathContext->new;
$xpc->registerNs('CB','BatteryML:2.0');

my @xpath_nodes;
@xpath_nodes = $root_tmpl->findnodes('//xpath');

foreach my $iXnode (@xpath_nodes){
    my $parentnode = $iXnode->parentNode;

    my $xentry=$iXnode->textContent();
    my @parameterNodes = $xpc->findnodes($xentry, $root);


    foreach my $inode (@parameterNodes){
	my $newprop=&Parameter2property($inode);
	if(defined($newprop)){
	    $parentnode->addChild( $newprop );	    
	}
    }
    $parentnode->removeChild( $iXnode );
}

if($TIDY){
    my $docstring = $tmpl->toString( 1 );
    my $tidy_obj = XML::Tidy->new('xml' => $docstring);
    $tidy_obj->tidy();
    $tidy_obj->write($fo);
}
else{
    my $fho = new IO::File($fo, "w") or die "$fo: $!\n";   # output
    $tmpl->toFH($fho, 2);
    close ($fho);
}

# ---- subs ----

sub Parameter2property{
    my $node=shift;
    my $ixpath;
    my $ivalue;
    my $parentnode;
    my $xpc;
    $xpc = XML::LibXML::XPathContext->new;
    $xpc->registerNs('CB','BatteryML:2.0');

    my %map=(
	'@id' => 'name',
	'CB:Scalar/CB:String' => 'value',
	'CB:Unit' => 'unit',
	'CB:Description' => 'description',
	);
    my @mapo=('@id','CB:Scalar/CB:String','CB:Unit','CB:Description');

    my $name=$node->nodeName();

    if($name eq 'Parameter'){
	my $propertyNode = XML::LibXML::Element->new('property');

	foreach $ixpath (@mapo){
	    $ivalue = $xpc->exists($ixpath,$node) ? $xpc->findvalue( $ixpath,$node ) : undef;
	    $ivalue //= '';

	    if($ivalue =~ m/__CAEBAT[a-zA-Z]+_/){
#		print "ivalue: $ivalue\n";
		$ivalue =~ s/__CAEBATPrefix_//g;
		$ivalue =~ s/__CAEBATHash_/\#/g;
		$ivalue =~ s/__CAEBATSpace_/ /g;
		$ivalue =~ s/__CAEBATComma_/,/g;
		$ivalue =~ s/__CAEBATSlash_/\//g;
		$ivalue =~ s/__CAEBATEmpty_//g;
#		print "ivalue: $ivalue\n";
	    }
	    $propertyNode->setAttribute( $map{$ixpath}, $ivalue );
	}
	$parentnode = $node->parentNode;
	$parentnode->replaceChild( $propertyNode, $node );
	return $propertyNode;
    }
    else{
	undef;
    }
}

#
# User manual
#
sub help_print_and_exit{
    print STDERR <<EOF
C2ECPT.pl: Convert CAEBAT XML file to ECPower XML file

Usage: C2ECPT.pl [--tidy | --help | --version] CAEBAT_XML_file ECPower_XML_file 

	--tidy    : Tidy XML output
	--help    : This help message
	--version : Print version on standard output and exit
EOF
;
    exit;
}

sub set_template{
    return
'<?xml version="1.0" encoding="UTF-8"?>
<ECPower>
  <Designer>
    <Package type="1">
      <Prismatic type="2">
        <Battery_SED type="2">
	  <xpath>
	    //CB:PackDB/CB:Pack[@id="Pack_Simulation"]/CB:Parameters/CB:Parameter
	  </xpath>
        </Battery_SED>
      </Prismatic>
    </Package>
    <Electrode_Assembly type="1">
      <Positive_Electrode type="1">
        <Foil type="2">
	  <xpath>
	    //CB:BuildingBlockDB/CB:BuildingBlock[@id="Positive_Electrode"]//CB:BuildingBlock[@id="Foil"]/CB:Parameters/CB:Parameter
	  </xpath>
        </Foil>
        <Formula type="3">
          <Active_Material type="3">
	    <xpath>
	      //CB:BuildingBlockDB/CB:BuildingBlock[@id="Positive_Electrode"]//CB:ParameterSet[@id="Active_Material"]/CB:Parameter
	    </xpath>
          </Active_Material>
          <Conductive_Agent type="3">
	    <xpath>
	      //CB:BuildingBlockDB/CB:BuildingBlock[@id="Positive_Electrode"]//CB:ParameterSet[@id="Conductive_Agent"]/CB:Parameter
	    </xpath>
          </Conductive_Agent>
          <Binder type="3">
	    <xpath>
	      //CB:BuildingBlockDB/CB:BuildingBlock[@id="Positive_Electrode"]//CB:ParameterSet[@id="Binder"]/CB:Parameter
	    </xpath>
          </Binder>
          <Additive type="3">
	    <xpath>
	      //CB:BuildingBlockDB/CB:BuildingBlock[@id="Positive_Electrode"]//CB:ParameterSet[@id="Additive"]/CB:Parameter
	    </xpath>
          </Additive>
        </Formula>
        <Coating type="2">
	  <xpath>
	    //CB:BuildingBlockDB/CB:BuildingBlock[@id="Positive_Electrode"]//CB:BuildingBlock[@id="Coating"]/CB:Parameters/CB:Parameter
	  </xpath>
        </Coating>
        <Summary type="4">
	  <xpath>
	    //CB:BuildingBlockDB/CB:BuildingBlock[@id="Positive_Electrode"]//CB:ParameterSet[@id="Summary"]/CB:Parameter
	  </xpath>
        </Summary>
      </Positive_Electrode>
      <Negative_Electrode type="1">
        <Foil type="2">
	  <xpath>
	    //CB:BuildingBlockDB/CB:BuildingBlock[@id="Negative_Electrode"]//CB:BuildingBlock[@id="Foil"]/CB:Parameters/CB:Parameter
	  </xpath>
        </Foil>
        <Formula type="3">
          <Active_Material type="3">
	    <xpath>
	      //CB:BuildingBlockDB/CB:BuildingBlock[@id="Negative_Electrode"]//CB:ParameterSet[@id="Active_Material"]/CB:Parameter
	    </xpath>
          </Active_Material>
          <Conductive_Agent type="3">
	    <xpath>
	      //CB:BuildingBlockDB/CB:BuildingBlock[@id="Negative_Electrode"]//CB:ParameterSet[@id="Conductive_Agent"]/CB:Parameter
	    </xpath>
          </Conductive_Agent>
          <Binder type="3">
	    <xpath>
	      //CB:BuildingBlockDB/CB:BuildingBlock[@id="Negative_Electrode"]//CB:ParameterSet[@id="Binder"]/CB:Parameter
	    </xpath>
          </Binder>
          <Additive type="3">
	    <xpath>
	      //CB:BuildingBlockDB/CB:BuildingBlock[@id="Negative_Electrode"]//CB:ParameterSet[@id="Additive"]/CB:Parameter
	    </xpath>
          </Additive>
        </Formula>
        <Coating type="2">
	  <xpath>
	    //CB:BuildingBlockDB/CB:BuildingBlock[@id="Negative_Electrode"]//CB:BuildingBlock[@id="Coating"]/CB:Parameters/CB:Parameter
	  </xpath>
        </Coating>
        <Summary type="4">
	  <xpath>
	    //CB:BuildingBlockDB/CB:BuildingBlock[@id="Negative_Electrode"]//CB:ParameterSet[@id="Summary"]/CB:Parameter
	  </xpath>
        </Summary>
      </Negative_Electrode>
      <Separator type="3">
	<xpath>
	  //CB:BuildingBlock[@id="Separator"]/CB:Parameters/CB:Parameter
	</xpath>
      </Separator>
    </Electrode_Assembly>
    <Electrolyte type="3">
      <xpath>
	//CB:BuildingBlock[@id="Electrolyte"]/CB:Parameters/CB:Parameter
      </xpath>
    </Electrolyte>
    <Cell_Specifications type="1">
      <xpath>
	//CB:CellDB/CB:Cell[@id="Battery_SED"]//CB:ParameterSet[@id="Cell_Specifications"]/CB:Parameter
      </xpath>
    </Cell_Specifications>
  </Designer>
  <Simulator>
    <ECT_Model type="1">
      <Model_Parameters type="1">
        <Control_Parameters type="2">
	  <xpath>
	    //CB:SimulationDB//CB:ParameterSet[@id="Control_Parameters"]/CB:Parameter
	  </xpath>
        </Control_Parameters>
        <Mesh_Number type="2">
	  <xpath>
	    //CB:SimulationDB//CB:ParameterSet[@id="Mesh_Number"]/CB:Parameter
	  </xpath>
        </Mesh_Number>
        <Operating_Conditions type="3">
	  <xpath>
	    //CB:SimulationDB//CB:ParameterSet[@id="Operating_Conditions"]/CB:Parameter
	  </xpath>
        </Operating_Conditions>
        <Initial_Conditions type="2">
	  <xpath>
	    //CB:SimulationDB//CB:ParameterSet[@id="Initial_Conditions"]/CB:Parameter
	  </xpath>
        </Initial_Conditions>
        <Butler-Volmer_Equation type="1">
          <Negative_Electrode type="3">
	  <xpath>
	    //CB:ModelDB//CB:Category[@id="Butler-Volmer_Equation"]//CB:ParameterSet[@id="Negative_Electrode"]/CB:Parameter
	  </xpath>
          </Negative_Electrode>
          <Positive_Electrode type="3">
	  <xpath>
	    //CB:ModelDB//CB:Category[@id="Butler-Volmer_Equation"]//CB:ParameterSet[@id="Positive_Electrode"]/CB:Parameter
	  </xpath>
          </Positive_Electrode>
        </Butler-Volmer_Equation>
        <Bruggeman_Exponents type="2">
	  <xpath>
	    //CB:ModelDB//CB:Category[@id="Bruggeman_Exponents"]//CB:Parameter
	  </xpath>
        </Bruggeman_Exponents>
        <Electrolyte_Concentration type="3">
	  <xpath>
	    //CB:ModelDB//CB:Category[@id="Electrolyte_Concentration"]//CB:Parameter
	  </xpath>
        </Electrolyte_Concentration>
        <Solid_State_Diffusion type="1">
          <Negative_Active_Material type="3">
	  <xpath>
	    //CB:ModelDB//CB:Category[@id="Solid_State_Diffusion"]//CB:ParameterSet[@id="Negative_Active_Material"]/CB:Parameter
	  </xpath>
          </Negative_Active_Material>
          <Positive_Active_Material type="3">
	  <xpath>
	    //CB:ModelDB//CB:Category[@id="Solid_State_Diffusion"]//CB:ParameterSet[@id="Positive_Active_Material"]/CB:Parameter
	  </xpath>
          </Positive_Active_Material>
        </Solid_State_Diffusion>
        <Electrolyte_Potential type="3">
	  <xpath>
	    //CB:ModelDB//CB:Category[@id="Electrolyte_Potential"]//CB:Parameter
	  </xpath>
        </Electrolyte_Potential>
        <Solid_Phase_Potential type="1">
          <Negative_Electrode type="2">
	  <xpath>
	    //CB:ModelDB//CB:Category[@id="Solid_Phase_Potential"]//CB:ParameterSet[@id="Negative_Electrode"]/CB:Parameter
	  </xpath>
          </Negative_Electrode>
          <Positive_Electrode type="2">
	  <xpath>
	    //CB:ModelDB//CB:Category[@id="Solid_Phase_Potential"]//CB:ParameterSet[@id="Positive_Electrode"]/CB:Parameter
	  </xpath>
          </Positive_Electrode>
        </Solid_Phase_Potential>
        <Heat_Transfer type="3">
	  <xpath>
	    //CB:ModelDB//CB:Category[@id="Heat_Transfer"]//CB:Parameter
	  </xpath>
        </Heat_Transfer>
        <Pack_Simulation type="3">
	  <xpath>
	    //CB:PackDB/CB:Pack[@id="Pack_Simulation"]//CB:ParameterSet[@id="Pack_Simulation"]/CB:Parameter
	  </xpath>
        </Pack_Simulation>
        <Safety_Simulation type="2">
          <Nail_Penetration type="3">
	  <xpath>
	    //CB:SimulationDB//CB:Scenario//CB:ParameterSet[@id="Nail_Penetration"]/CB:Parameter
	  </xpath>
          </Nail_Penetration>
        </Safety_Simulation>
      </Model_Parameters>
      <Mesh_Generation type="2">
        <SED_Mesh type="1">
	  <xpath>
	    //CB:SimulationDB/CB:Simulation[@id="Simulator"]//CB:ParameterSet[@id="SED_Mesh"]/CB:Parameter
	  </xpath>
        </SED_Mesh>
      </Mesh_Generation>
    </ECT_Model>
  </Simulator>
</ECPower>
';
}
