#!/usr/bin/perl
use strict;
use warnings;
use CGI qw(:standard :netscape);
use RFC::Main;
use RFC::Rig;
use RFC::RFCCGI qw(:cgi :html);

my $F = 96485;
my $R = 8.31;


my @gasses = ('Ar','CO2','CO','CH4','O2','H2','H2O');  #### Used for ch4 ###
my $ref = &RFC::RFCCGI::get_user_data_ref();
my $uid = $$ref{'uid'};

if (!defined(param))
{
    print process('to_login.tt');
}
else
{
    if ($uid)
    {
	print process('main_nav.tt');
	param(-name=>'action',-value=>'') unless (param('action'));
	$_ = param('action');
      CASE:
	{
	    ### Insert case statements ###
	    /^ch4$/ and do {&ch4; last CASE;};
	    /^calc_ch4$/ and do {&calc_ch4; last CASE;};
	    /^fu$/ and do {&fu; last CASE;};
	    /^calc_fu$/ and do {&fu; &calc_fu; last CASE;};
	    /^imp_comp/ and do {&comp; last CASE;};
	    /^pO2/ and do {&pO2; last CASE;};
            ### Insert case statements ###
	    ### Default response ####
	}
	print process('end_html.tt');
    }
    else 
    {
        print process('not_auth.tt');
    }
}


sub ch4()
{
    unless (-e '/usr/local/bin/Reforming_delG_Min')
    {
	print h1({-class=>'Alert'},'Warning: /usr/local/bin/Reforming_delG_Min does not exist!');
	return;
    }
    print process('ch4.tt');
}

sub calc_ch4()
{
    unless (-e '/usr/local/bin/Reforming_delG_Min')
    {
	print h1({-class=>'Alert'},'Warning: /usr/local/bin/Reforming_delG_Min does not exist!');
	return;
    }
    my $cstr = '/usr/local/bin/Reforming_delG_Min --command par_all';
    my %input = &get_input;
    my %out = ();
    if ($input{'temp'} > 1200)
    {
        print h2({-class=>'alert'},"Temperature above 1200C entered, setting temperature to 1200C.");
        $input{'temp'} = 1200;
    }
    if ($input{'temp'} < 300)
    {
        print h2({-class=>'alert'},"Temperature below 300C entered, setting temperature to 300C.");
        $input{'temp'} = 300;
    }
    $input{'temp'} += 273.15;
    my $rest = param('calc');
    my $sum = 0;
    for my $key ('Ar','CO2','CO','CH4','O2','H2','H2O')
    {
	next if ($key eq $rest);
	$sum += $input{$key};
        $cstr = $cstr . ' --'.$key. ' '.$input{$key};
    }
    for my $key ('P','temp')
    {
        $cstr = $cstr . ' --'.$key. ' '.$input{$key};
    }
    my $topup = 1 - $sum;
    if ($topup >= 0)
    {
	$cstr = $cstr . ' --'.$rest. ' '.$topup;
    }
    else
    {
	print h1({-class=>'Alert'},"Error: Mole fractions add up to more than 1!");
	print process('ch4.tt',&get_template_data_ref(\%out));
	return;
    }
    my $result = '';
    my @res = `$cstr`;
#    print h3($cstr);
    $out{'temp'} = $input{'temp'};
    $out{'P'} = $input{'P'};
    $res[5] =~ /\s+([\-\.\deE\-\+]+)/;
    $out{'H2'} = $1;
    $res[4] =~ /\s+([\-\.\deE\-\+]+)/;
    $out{'H2O'} = $1;
    $res[2] =~ /\s+([\-\.\deE\-\+]+)/;
    $out{'CH4'} = $1;
    $res[7] =~ /\s+([\-\.\deE\-\+]+)/;
    $out{'CO2'} = $1;
    $res[6] =~ /\s+([\-\.\deE\-\+]+)/;
    $out{'CO'} = $1;
    $res[8] =~ /\s+([\-\.\deE\-\+]+)/;
    $out{'O2'} = $1;
    $res[9] =~ /\s+([\-\.\deE\-\+]+)/;
    $out{'C_a'} = $1;
    $out{'OCV'} = - log(0.21 / $out{'O2'}) * $R * $out{'temp'} / (4 * $F);
    $out{'OCV_O2'} = - log(1 / $out{'O2'}) * $R * $out{'temp'} / (4 * $F);
    $out{'Ar'} = 0;
    my $total = 0;
    for my $gas (@gasses)
    {
        $total += $out{$gas};
    }
    $out{'Ar'} = 1 - $total;
    $out{'action'} = 'calc';
    print process('ch4.tt',&get_template_data_ref(\%out));
}

sub fu()
{
    my %out = (
	'h2' => 24,
	'ch4' => 0,
	'o2' => 0,
	'co' => 0,
	'co2' => 0,
	'n2' => 0,
	'nh3' => 0,
	'air' => 140,
	'o2_cathode' => 0,
	'n2_cathode' => 0,
	'water' => 21,
	'enabled' => 1,
	'current' => 16,
	'cell_area' => 16,
	'segments' => 20,
	'temp' => 850,
	'pO2in' => 1070,
	'po2_temp' => 850,
	'U' => 600,
	'emf' => 1056,
	'useemf' => 1,
	'use_ch4' => 1,
	);
    foreach my $key (keys %out)
    {
	next unless (defined param($key));
	$out{$key} = param($key);
    }
#    unless (-e '/usr/local/bin/ch4_args.pl')
    unless (-e '/usr/local/bin/Reforming_delG_Min')
    {
	$out{'use_ch4'} = 0;
    }
    print process('fu.tt',&get_template_data_ref(\%out));
}

sub calc_fu()
{
    #### Get input values for gasses  ####
    my @gaslst = ('h2','co','co2','ch4','o2','nh3','n2','air','o2_cathode','n2_cathode'); 
    my %i = ();
    for my $gas (@gaslst)
    {
        $i{$gas} = 0;
        $i{$gas} = param($gas) if (defined(param($gas)));
        $i{$gas} =~ /([\w\.\+\-]*)/;
        $i{$gas} = $1;
    }
    my $use_ch4 = '';
    $use_ch4 = ' --use_ch4 YES' if ($i{'co'} || $i{'co2'} || $i{'ch4'});
    #### Get input values for NON-gasses  ####
    for my $gas ('current','cell area','segments','temperature','pO2 in','pO2 temp','U','emf','water','enabled','useemf')
    {
        $i{$gas} = 0;
        $i{$gas} = param($gas) if (defined(param($gas)));
        $i{$gas} =~ /([\w\.\+\-]*)/;
        $i{$gas} = $1;
    }
    ### Generate command string for use with OCV_corr ####
    my $emf = ' --emf '.-$i{'emf'}/1000;
    my $u = ' --U '.-$i{'U'}/1000;
    my $cmd = '/usr/local/bin/OCV_corr --command par_all --Air 0 --A '.$i{'cell area'};
    my $h2 = $i{'h2'};
    my $o2 = $i{'o2'};
    my $ch4 = $i{'ch4'};
    my $co = $i{'co'};
    my $co2 = $i{'co2'};
    #### Calculate anode gas flow and composition ###
    if ($use_ch4)
    {
        #### Convert to simulate internally reformed methane ####
        #### if carbon containing gasses are used            ####
        $cmd .= $use_ch4;
        $cmd .= ' --CH4 '.$ch4;
        $cmd .= ' --CO '.$co;
        $cmd .= ' --CO2 '.$co2;
    }
    $h2 += $i{'nh3'} * 3 / 2;
    my $n2 = $i{'n2'} + $i{'nh3'}/2;
    $cmd .= ' --O2_add '.$o2;
    $cmd .= ' --H2 '.$h2;
    $cmd .= ' --N2 '.$n2;
    ### Calculate cathode gas flow and composition ###
    $o2 = $i{'air'}*0.21;
    $n2 = $i{'air'}*(1-0.21);
    $o2 += $i{'o2_cathode'};
    $n2 += $i{'n2_cathode'};
    $cmd .= ' --O2_cathode '. $o2;
    $cmd .= ' --N2_cathode '.$n2;
    ### Set rest of options ###
    $cmd .= ' --I '.$i{'current'};
    $cmd .= $u;
    if ($i{'enabled'})
    {
        $cmd .= ' --water '.$i{'water'};
    }
    else
    {
        $cmd .= ' --dry 1';
    }
    $cmd .= ' --N '.$i{'segments'};
    my $po2cmd = $cmd;
    $cmd .= $emf if ($i{'useemf'});
    $cmd .= ' --cell '.$i{'temperature'};
    $po2cmd .= ' --emf '.$i{'pO2 in'}/(-1000);
    $po2cmd .= ' --cell '.$i{'pO2 temp'};
    my @res = (); 
    my %out = ();
    eval {
        #### Run calculation ###
        @res = `$cmd`;
        #### Get result into hash ###
        for my $l (@res)
        {
            my ($key,$val) = split(/[\s\t]+/,$l);
            $out{$key} = $val;
            #### Preformat output numbers #####
            $out{$key} = sprintf("%.4f",$val) if ($val =~ /\d+/);
            $out{$key} = sprintf("%.5f",$val) if (($key =~ /leak/i) || ($key =~ /xh2/i)) && ($val =~ /\d+/);
        }
        ### Run calculation for pO2 in ###
        @res = `$po2cmd`;
        my %out_pO2in = ();
        #### Get result into hash ###
        for my $l (@res)
        {
            my ($key,$val) = split(/[\s\t]+/,$l);
            $out_pO2in{$key} = $val;
            #### Preformat output numbers #####
            $out_pO2in{$key} = sprintf("%.4f",$val) if ($val =~ /\d+/);
            $out_pO2in{$key} = sprintf("%.5f",$val) if (($key =~ /leak/i) || ($key =~ /xh2/i)) && ($val =~ /\d+/);
        }
	$out{'pO2_in_calc'} = \%out_pO2in;
    };
    if ($@)
    {
        #### Catch errors ###
        print h1({-class=>'Alert'},"$@");
    }
    $out{'use_ch4'} = 1;
    unless (-e '/usr/local/bin/ch4_args.pl')
    {
	$out{'use_ch4'} = 0;
    }
    print process('fu_calc.tt',&get_template_data_ref(\%out));
}

sub comp()
{
    my $mdata = '';
    $mdata = param('measure') if (defined(param('measure')));
    my $cdata = '';
    $cdata = param('compensation') if (defined(param('compensation')));
    my $mode = 'Add';
    $mode = param('mode') if (defined(param('mode')));
    if ($mdata && $cdata && $mode)
    {
	$mdata = &calc_comp($mode,$cdata,$mdata);
    }
    my %out = (
	'measure' =>$mdata,
	'compensation' => $cdata,
	'mode' => $mode,
	);
    print process('imp_comp.tt',&get_template_data_ref(\%out));
}

sub pO2()
{
    my @list = `/bin/ls -1 /home/http/html/tmp`;
    foreach (@list)
    {
        my $f = '/home/http/html/tmp/'.$_;
        if ($f =~ /([\w\.\/]+)/)
        {
            unlink $1;
        }
    }
    my $temp = 1000;
    $temp = param('temp') if (defined(param('temp')));
    my $data = '';
    $data = param('data') if (defined(param('data')));
    my $mode = undef;
    $mode = param('mode') if (defined(param('mode')));
    $data = "8       270     0.4\n16      278.6   0.4\n24      285     0.45\n32      294     0.4\n48      296     0.4\n56      297.6   0.4\n" unless ($data);
    my $f = '/tmp/po2_public_'.$$.'.txt';
    open MYOUT,'>',$f or die "Could not open file $f for writing $!\n";
    print MYOUT $temp,"\n";
    $data =~ s/[\s\t\n]+$//s;
    print MYOUT $data,"\n";
    close MYOUT;
    my @fs = `/usr/local/bin/check_monitor.pl $f`;
    unlink $f if (-e $f);
    foreach my $i (@fs)
    {
        $i =~ /\/([\w\.\-]+)$/;
        $i = '/tmp/'.$1;
    }
    my %out = (
	'temp' => $temp,
	'data' => $data,
	'mode' => $mode,
	'url1' => $fs[0],
	'url2' => $fs[1],
    );
    print process('pO2.tt',&get_template_data_ref(\%out));
}

sub get_input
{
    my %temp = ();
    for my $gas (@gasses)
    {
        if (defined(param($gas)))
        {
            my $test = param($gas);
            $test =~ /([\d\.]+)/;
            $temp{$gas} = $1;
        }
        ### Make sure that all gasses return a defined value ###
        $temp{$gas} = 0 unless ($temp{$gas});
    }
    if (defined(param('calc')))
    {
        my $test = param('calc');
        $test =~ /([\w]+)/;
        $temp{'calc'} = $1;
    }
    if (defined(param('P')))
    {
        my $test = param('P');
        $test =~ /([\d\.]+)/;
        $temp{'P'} = $1;
    }
    if (defined(param('temp')))
    {
        my $test = param('temp');
        $test =~ /([\d\.]+)/;
        $temp{'temp'} = $1;
    }
    return %temp;
}

sub calc_comp($$$)
{
    my $mode = shift;
    my $comp = shift;
    my $data = shift;
    return '' unless ($data && $comp && $mode);     ### Retrun if no imput is given ###
    my $m = '';
    $m = 'A' if ($mode =~ /Add/);
    $m = 'S' if ($mode =~ /Subtract/);
    $m = 'M' if ($mode =~ /Multiply/);
    $m = 'D' if ($mode =~ /Divide/);
    #### Set file names and command string ###
    my $dir = '/tmp/';
    my $datafile = $dir.$$.'data.i2b';
    my $outfile = $dir.$$.'data_cor.i2b';
    my $compfile = $dir.$$.'comp.i2b';
    my $cmd = &get_cv('impedance','comp_program').' -'.$m.' '.$compfile.' '.$datafile;
    eval {
        open MYOUT,'>',$datafile or die "Could not open file $datafile for writing!";
        print MYOUT $data;
        close MYOUT;
        open MYOUT,'>',$compfile or die "Could not open file $compfile for writing!";
        print MYOUT $comp;
        close MYOUT;
        ### Det default error if failed compensation ###
        $data = 'Compensation Failed!';
        ### call hio_korr to do compensation ###
        system($cmd);
        if (-e $outfile)
        {
            open MYIN,'<',$outfile or die "Could not open file $outfile!";
            my @dat = <MYIN>;
            close MYIN;
            $data = join('',@dat);
        }
        ### Cleanup after use ###
        unlink $datafile if (-e $datafile);
        unlink $compfile if (-e $compfile);
        unlink $outfile if (-e $outfile);
    };
    &errorlog($@) if ($@);
    return $data;
}
