#!/usr/bin/perl

use POSIX 'setsid';
use CGI qw/:standard :html3/;
use CGI::Carp qw/fatalsToBrowser/;
use Time::Local;
use rnak;

$program_path="";

@parts = split "<!--RNAKINETICS-->", `cat start.html`;
print header;
check_ifunderconstruction();
if(param('results')) {
    check_queries(1);
    exit(1);
}
$id = param('id');
$id =~ s/\D//g;
unless($id) {
    foreach $z(param) {
	if($z=~/^id(\d+)$/) {
	    $id = $1;
	    if(param($z)=~/^Remove/) {
	        remove_results();
		check_queries(1);
		exit(1);
	    }
	    last;
	}
    }
}
 
if($id || param('check')) {
    $pid=$id;
    substr($pid,0,12+$NRND)="";
    if(`ls $outdir$id.log` eq "") {
        em("Query $id is not found");
        input($err[0]);
    }
    else {
	readlogfile();
        if($percent_ready<1) {
	    if(param('submit')=~/^Terminate/) {
        	terminate();
        	input(red("The query $id has been terminated"));
  	    }	
	    else {
                fold_monitor();
	    }
        }
        else {
	    if(param('submit') eq "Create figures") {
		format_submit();
	    }
	    elsif(param('submit') =~/^Remove results/) {
        	remove_results();
        	input();
  	    }
	    else {
		if(`ls $outdir$id.flg` eq "") {
		    format_input();
		}
		else {
		    readflgfile();
		    if($percent_ready<1) {
            		if(param('submit')=~/^Terminate/) {
                	    terminate();
                	    format_input(red("The query $id has been ".
				"successfully terminated ($pid)"));
			}
			else {
		            format_monitor();
			}
		    }
		    else {
		   	report();
		    }
		}
	    }
        }
    }
}
else {
    if(param('submit') eq "Submit") {
        fold_submit();
    }
    else {
        input();
    }
}
cleanup();
print end_html;


#######################################################################

sub terminate {
    @a = split /\n/, `ps -A -l`;
    foreach $z(@a) {
	@b = split /\s+/, $z;
	if($b[4] eq $pid) {
	    system("kill -1 $b[3]");
        }
    }
    remove_results();
}

sub remove_results {
    if(`ls $outdir$id.flg` eq "") {
        system("rm -f $outdir$id.*");
	system("rm -f $outdir$id\_*.*");
    }
    else {
        system("rm -f $outdir$id.flg");
        system("rm -f -r $outdir$id");
    }
}

sub fold_submit {
    $err = check_before_submitting();
    if($err) {
	input($err);
	return;
    }
    exit(1) if($err = check_queries());
    $id = get_new_id();
    return(undef) unless($id);
    if ($pid = fork) {
	$id.=$pid;
	$start_time = time;
        $percent_ready = 0;
	$est_time = undef;
	$upd_time = 3;
        $IP = remote_host();
        $cmd = "$id\t$pid\t$nr\t$start_time\t$IP\n";
        open(LOG, ">>$logfile");
        flock(LOG, 2);
        print LOG $cmd;
        close(LOG);
   	fold_monitor(); 
    } else {
	$id.=$$;
	die "can't fork: $!" unless defined $pid;
        open STDIN, '/dev/null' or die "Canā~@~Yt read /dev/null: $!";
        open STDOUT, '>/dev/null'
                        or die "Canā~@~Yt write to /dev/null: $!";
        setsid                  or die "Canā~@~Yt start a new session: $!";
        open STDERR, '>&STDOUT' or die "Canā~@~Yt dup stdout: $!";
	$line = "-id $outdir$id -seq $seq -tm $tm -gr $gr -ncl $nc -m $nr ".
		"-gu $gu -hl $mhl -ht $ht"; 
	$program_name = $program_path."java -jar RNA6.jar";
#	open(FIL, ">>flg");print FIL " $program_name $line\n"; close(FIL);
	system("$program_name $line");
    }

}


sub fold_monitor {
    $beg_time = localtime($start_time);
    $refresh ="$upd_time;URL=start.cgi?id=$id";
    ($beforemeta,$aftermeta)= split "<!--RNAMETA-->", $parts[0];
    print $beforemeta;
    print "<meta http-equiv=\"Refresh\" content=\"$refresh\">"
	unless($trash0 || $est_time>$MAXWRKTIME);
    print $aftermeta;
    print start_multipart_form();
    print "Your reqest has been submitted to the server<p>";
    print "Query ID: <B>$id</B><p>";
    if($trash0) {
	print "<B>Cannot be completed because $trash0</B><p><hr>";
        print submit(-name=>'submit', -value=>'Return');
	print end_form;
        remove_results();
	return;
    }
    if($est_time>$MAXWRKTIME) {
	print red("<B>Has been terminated because WRKTIME exceeded</B>");
        print "<p><hr>";
        print submit(-name=>'submit', -value=>'Return');
        print end_form;
        remove_results();
        return;
    }
    print "Start time: $beg_time<p>";
    if($est_time) {
        $wrk_time = $est_time;
        use POSIX qw(strftime);
        $end_time = strftime "%a %b %e %H:%M:%S %Y", localtime(time+$est_time);
        print "End time:   $end_time (estimated)<p>";
        print "Remaining time: <B>$wrk_time</B> sec or less<p>";
    }
    else {
	print "Remaining time: not determined yet<p>";
    }
    print "This page will be updated automaticaly after <B>$upd_time</B> seconds<p><hr>";
    print submit(-name=>'submit', -value=>'Check status');
    print submit(-name=>'submit', -value=>'Terminate this query');
    print hidden(-name=>'id', -value=>$id);
    print end_form;
    print $parts[3];

}

sub format_submit {
    if($err = check_before_formatting()) {
        format_input($err);
        return;
    }
    exit(1) if($err = check_queries());
    $start_time = time;
    $cmd = join(",", ($maxs,$minl,$pqty)).",".
           join(":",(param('hel'),param('str'),param('rep'),param('ors')));
    if ($pid = fork) {
        $start_time = time;
	rpr(0,1); 
        $est_time = undef;
	$upd_time = 3;
	format_monitor();
    } else {
	die "can't fork: $!" unless defined $pid;
        open STDIN, '/dev/null' or die "Canā~@~Yt read /dev/null: $!";
        open STDOUT, '>/dev/null'
                    or die "Canā~@~Yt write to /dev/null: $!";
        setsid                  or die "Canā~@~Yt start a new session: $!";
        open STDERR, '>&STDOUT' or die "Canā~@~Yt dup stdout: $!";
	system("mkdir $outdir$id");
#        system("chmod 777 $outdir$id");
        system("perl makeoutput.cgi $id $start_time $$ $cmd");
	exit(1);
    }
}

sub format_input {
    print $parts[0];
    if($_[0]) {
        print $_[0],"<p><hr>";
    }
    else {
      print "The folding for the query <b>$id</b> has been completed in <b>";
      print $current_time-$start_time+1, "</b> sec<p>";
    }
    print "Please choose from the following options for the output:<p>";
    $Q = `cat $outdir$id.xml`;
    ($H) = parsexml(Heliset,$Q);
    ($G) = parsexml(GroupList,$Q);
    @helices = parsexml(Helix,$H);
    @groups = parsexml(GroupElement,$G);
    $nh=0+@helices;
    $ns=0+@groups;
    print start_form;
    print "<b><u>Helices (total of $nh):</u></b><ol>";
    print checkbox_group(-name=>'hel',-values=>['htp','heh'],
		-default=>['htp','heh'],-linebreak=>'true',
		-labels=>{'htp'=>'Create probability vs time plots',
         'heh'=>'Hide helices that are not present in any structure'});
    print "</ol>";
    print "<b><u>Groups of structures (total of $ns):</u></b><ol>";
    $ns = 40 if($ns>40);
    print table({-border=>undef},"",Tr([
	td(["Max number of groups to show",textfield(-name=>'maxs',
		-size=>6, -default=>$ns)]),
	td(["Min group lifetime (sec)",textfield(-name=>'minl',
		-size=>6, -default=>'1E-4')])
	]));
    print checkbox_group(-name=>'str',-values=>['stp','sop','ors'],
                -default=>['stp'],-linebreak=>'true',
                -labels=>{'stp'=>'Create probability vs time plots',
		'sop'=>'Optimize representation of big loops (option temporarily disabled)',
		'ors'=>'Report only the representative structure for each group'});
    print "</ol><b><u>Figures</u></b><ol>";
    print table({-border=>undef},"",Tr(td(["Image quality&nbsp;",
        textfield(-name=>'qty',-size=>6,-default=>'70')."\%"])));
    print checkbox_group(-name=>'rep',-values=>['rep'],default=>['rep'],
		-labels=>{'rep'=>'Remove EPS sources'}),"<p>";
    print "</ol><hr>",submit(-name=>'submit',-value=>'Create figures');
    print submit(-name=>'submit',-value=>'Remove results of this query');
    print hidden(-name=>'id', -value=>$id);
    print end_form,$parts[3];
}

sub format_monitor {
    $beg_time = localtime($start_time);
    $refresh ="$upd_time;URL=start.cgi?id=$id";
    ($beforemeta,$aftermeta)= split "<!--RNAMETA-->", $parts[0];
    print $beforemeta;
    print "<meta http-equiv=\"Refresh\" content=\"$refresh\" />";
    print $aftermeta;
    print start_multipart_form();
    print "Creating $err figures for the query <B>$id</B><p>";
    print "Start time: $beg_time <p>";
    if($est_time) {
        $wrk_time = $est_time;
        use POSIX qw(strftime);
        $end_time = strftime "%a %b %e %H:%M:%S %Y", localtime(time+$est_time);
        print "End time:   $end_time (estimated)<p>";
        print "Remaining time: <B>$wrk_time</B> sec or less<p>";
    }
    else {
        print "Remaining time: not determined yet<p>";
    }
    print "This page will be updated automaticaly after ".
		"<B>$upd_time</B> seconds<p><hr>";
    print submit(-name=>'submit', -value=>'Check status');
    print submit(-name=>'submit', -value=>'Terminate this query');
    print hidden(-name=>'id', -value=>$id);
    print end_form;
    print $parts[3];
}

sub report {
         print start_html(-title=>'RNA kinetics server',
        -head=>meta({-http_equiv=>'Refresh',
        -content=>"1;URL=$outdir$id.html"
          }));
         print h2("Transfering...");
}

sub input{
    $myerr = $_[0];
    exit(1) if($err = check_queries());
    print $parts[0];
    if($myerr) {
	print "$myerr<p><hr>";
    }
    print start_form,"<h4><b><u>Input sequence:</u></b></h4><p>";
    print textarea(-name=>'seq',-rows=>'10',-columns=>'70'),"<p>";
    print "<table border=\"1\">\n";
    print "<tr><td>Chain's growth rate</td><td>";
    print textfield(-name=>'gr',-size=>'10',-default=>'40'),"nt/sec";
    print "</td></tr><tr><td>Nucleation constant</td><td>";
    print textfield(-name=>'ncl',-size=>'10',-default=>'1.E+7');
    print "</td></tr><tr><td>Final time</td><td>";
    print textfield(-name=>'time',-size=>'10',-default=>'3'),"sec";
    print "</td></tr><tr><td>Number of runs</td><td>";
    print textfield(-name=>'nruns',-size=>'10',-default=>'100');
    $advanced = (param('advanced') =~ /^Advanced/);
    if($advanced) {
        print "</td></tr><tr><td>Min helix length</td><td>";
        print textfield(-name=>'mhl',-size=>'10',-default=>'4'),"nt";
        print "</td></tr><tr><td>Helix energy threshold</td><td>";
        print textfield(-name=>'ht',-size=>'10',-default=>'-7.0'),"kCal/mol";
        print "</td></tr><tr><td>Allow terminal GU</td><td>";
        print radio_group(-name=>'gu',-values=>['0','1'],
	 -default=>'1',-linebreak=>'true',-labels=>{'1'=>"False",'0'=>"True"});
    }
    else {
	print hidden(-name=>'mhl',-value=>'4');
	print hidden(-name=>'ht',-value=>'-7.0');
	print hidden(-name=>'gu',-value=>'1');
    }
    print "</td></tr></table><p><hr>";
    print submit(-name=>'submit',-value=>'Submit');
    print defaults(-value=>'Clear');
    print submit(-name=>'advanced',-value=>'Advanced form') unless($advanced);
    print submit(-name=>'advanced',-value=>'Simple form') if($advanced);
    print end_form,$parts[3];

}


sub check_queries {
    $id0 = $id;
    $percent_ready0=$percent_ready;
    my $ip = ipnumrep(remote_host());
    my @a = split /\n/, `ls $outdir$ip*.xml`;
    my $z;
    my @rows="<tr><th rowspan=2>Query ID</th><th colspan=2>Folding</th>".
	  "<th colspan=2>Figures</th><th rowspan=2>Disk usage</th>".
	  "<th rowspan=2>Expires</th><th rowspan=2>Options</th></tr><tr><th>".
	  "Started</th><th>Status</th><th>Started</th><th>Status</th></tr>";
    foreach $z(@a) {
	next unless($z =~ m/\D(\d+)\./);
	$id = $1;
	#$beg_time;
	#$start_time;
	#$est_time;
	#$percent_ready;
	next if(`ls $outdir$id.log` eq "");
   	readlogfile();
        $et1=$est_time ? $est_time :65535;
        $et1=0 unless($percent_ready<1);
        $est_time = $est_time ? "$est_time sec remaining" : "N/A";
        $status = $percent_ready<1?red("Running ($est_time)"):"Completed";
	$beg_time = localtime($start_time);
        @m = ($id, $beg_time, $status);
        $timeout = localtime($start_time+$NDAYS* 60*60*24);
	$beg_time=$status="&nbsp;";
	@opt = $percent_ready<1 ? "Monitor" : ("Format","Remove query");
        unless(`ls $outdir$id.flg` eq ""){
	    readflgfile();
            $et2=$est_time ? $est_time :65535;
            $et2=0 unless($percent_ready<1);
	    $est_time = $est_time ? "$est_time sec remaining" : "N/A";
            $status = $percent_ready<1?red("Running ($est_time)"):"Completed";
            $beg_time = localtime($start_time);
            @opt = $percent_ready<1? "Monitor" : ("  View  ","Remove figures");
	}
 	push @m, ($beg_time, $status);
	@q = split /\n/, `du -k $outdir$id*`;
	$du=0;
	foreach $w(@q) {
	    $w=~m/^(\d+)\t/;
	    $du+=$1;
        }
	$o="";
	foreach $w(@opt) {
	    $o.=submit(-name=>"id$id",value=>$w); 
	}
        push @m, ($du."K",$timeout,$o);
	push @rows, td(\@m);
	$total_du+=$du;
	$total_et+=($et1+$et2);
	$total_q++;
    }
    $err = ($total_du > $MAX_DU)||($total_q > $MAX_Q)||($total_et > $MAX_ET);
    if(@_ || $err) {
      print $parts[0];
      if($total_q==0) {
        print h3("You currently have no results"),"<hr>";
      }
      else {
	print start_form;
	print table({-border=>'1'},caption(""),Tr({-align=>'center'},\@rows));
	print "<p><hr><p>";
        $e1=red(" - you currently exceed the quota of $MAX_ET sec")
                if($total_et>$MAX_ET);
        $e2=red(" - you currently exceed the quota of $MAX_DU K")
                if($total_du>$MAX_DU);
        $e3=red(" - you currently exceed the quota of $MAX_Q ")
                if($total_q>$MAX_Q);
	$total_et="N/A" if($total_et>65534);
	print table({-border=>'0',-cellspacing=>'10'},"", Tr({-align=>'left'},[
		th(['Total elasped time:',"$total_et sec",$e1]),
		th(['Total disk usage:',"$total_du K",$e2]),
		th(['Total number of queries:',$total_q,$e3])
		]));
	print "<hr>",submit(-name=>'results',-value=>'Refresh this table');
	print end_form;
      }
      print $parts[3];
    }
    $id=$id0;
    $percent_ready=$percent_ready0;
    return($err);
}
