#! /usr/local/bin/perl
#
# $Id: render.cgi,v 1.2 1998/11/20 01:41:55 helgew Exp $
#
# This file is part of the RCSB query & render interfaces
#
# (c) Dave Martinez <damartin@sdsc.edu>
#     Helge Weissig <helgew@sdsc.edu>
#
# PURPOSE: This CGI script produces
#	   VRML 2.0 formats are produced using the molauto and molscript
#	   applications available at http://www.avatar.se/molscript/
#
# INPUT ARGS: PDB_ID
#	      format ('vrml_default', 'vrml_custom', 'ras_default' or
#		'quickpdb_default')
#	      molauto options from pdb2vrml.html (optional)
#	      rasmol options from rasmol.html (optional)
#
# OUPUT: 
#	 VRML: generated by 'molauto -options | molscript -vrml -s'
#	 Rasmol: generated rasmol script or simple PDB file
#	 QuickPDB: simple forward to quickpdb.html
#

require 5.001;
use FindBin;
use lib qq($FindBin::RealDir/lib),
	qq($FindBin::RealDir/lib/perl5);

use CGI;
use CGI::Carp qw(fatalsToBrowser);
$cgi = new CGI();

use POM::Info;

$info = new POM::Info();
require "ssbond.pl";
require "site.pl";

require "rcsb_settings.pl";

$PDB_ID	= lc($cgi->param('pdbId'));

%forwards = (
    'rasmol'	=> { 'custom'	=> 
			sub {
			    RCSB::GO_AWAY("$DOC_URL/rasmol.html?$PDB_ID")
			},
		     'default'	=> \&rasmol,
		     'relocate'	=> "$RCSB::DOC_URL/rasmol.html" },

    'vrml'	=> { 'custom'	=> 
			sub {
			    RCSB::GO_AWAY("$TOP_URL/pdb/pdb2vrml.shtml?$PDB_ID")
			},
		     'default'	=> \&vrml,
		     'relocate'	=> "$RCSB::TOP_URL/pdb/pdb2vrml.shtml" },

    'quickpdb'	=> { 'custom'	=> \&quickpdb,
		     'default'	=> \&quickpdb,
		     'relocate'	=> "$RCSB::TOP_URL/pdb/quickpdb.html" },
);

$format = $cgi->param('format');
$format =~ s/_(.*)//;
$displayOptions = $1;

# make vrml default output
if (!exists($forwards{$format}) ||
    !$cgi->param('format')) {
	$format = 'vrml';
	$displayOptions = 'custom';
}

$relocate = $forwards{$format}{'relocate'};

$pdb_file = &RCSB::GET_PDB_FILE($PDB_ID);

# print STDERR "$PDB_ID\n$pdb_file\n";
&RCSB::GO_AWAY($relocate) unless (-e $pdb_file);

&{$forwards{$format}{$displayOptions}};

sub quickpdb() {
	print $cgi->header();
	# just to make sure it's there! :))
	my $pdbFile = &RCSB::GET_FILE($PDB_ID, "PDB");
	open IN, "$RCSB::TOP_DIR/pdb/quickpdb.html"
		or die "$RCSB::TOP_DIR/pdb/quickpdb.html: $!\n";

	while (<IN>) {
	  if (/^<!-- <(\w+)> -->/) {
	    if ($1 eq "AddParams") {
		print;
		print qq[<PARAM NAME="pdb_file" VALUE="$PDB_ID">\n];
		print qq[<PARAM NAME="top_url" VALUE="$RCSB::TOP_URL/pdb">\n];
		next;
	    }
	  }
	  print;
	}

	close IN;
}

sub rasmol() {
	print $cgi->header(-type => 'chemical/x-ras');
	print "load pdb inline\n";

	# script goes here!

	print "exit\n";
	open IN, $pdb_file or die "$pdb_file: $!\n";
	while (<IN>) { print; }
	close IN;
}

sub vrml() {
	@omit		= ( "submit" );
	@singlekeys	= ( "nocentre", "cylinder", "turns", "thin" );
	@multikeys	= ( "schematic", "ligands", "secondary", "bgcolor" );

	foreach (@singlekeys) {
		if ($cgi->param($_) == 1) {
		    $options .= " -$_";
		}
	}

	$nocolor = 0;
	foreach (@multikeys) {
		if ($_ eq "schematic") {
		    if ($cgi->param($_) eq "nice") {
			$options .=" -nice";
		    } elsif ($cgi->param($_) eq "nocolour") {
			$options .=" -nocolour";
			$nocolor = 1;
		    }
		} elsif ($_ eq "ligands") {
		    if ($cgi->param($_) eq "noligand") {
			$options .=" -noligand";
		    } elsif ($cgi->param($_) eq "bonds") {
			$options .=" -bonds";
		    } elsif ($cgi->param($_) eq "stick") {
			$options .=" -stick";
		    } elsif ($cgi->param($_) eq "cpk") {
			$options .=" -cpk";
		    }
		} elsif ($_ eq "secondary") {
		    if ($cgi->param($_) eq "ss_pdb") {
			$options .=" -ss_pdb";
		    } elsif ($cgi->param($_) eq "ss_hb") {
			$options .=" -ss_hb";
		    } elsif ($cgi->param($_) eq "ss_ca") {
			$options .=" -ss_ca";
		    }
		} elsif ($_ eq "bgcolor") {
		    $bgcolor = ($cgi->param('bgcolor') ?
					$cgi->param('bgcolor') : "black");
		    $bgcolor = "white" if $nocolor;

		    if ($bgcolor eq "black") {
			$bgcolor = "";
			next;
		    }

		    $bgcolor = "  background $bgcolor;\n";
        	}

	}

	# **************************************************************
	# Set color on all carbon atoms to light grey
	#

	$greyString = "set atomcolour atom C* grey 0.7;\n ";

	# **************************************************************
	# Create the starting point for script
	#

    	$start="set segments 2;|set colourparts on";

	$command = "$RCSB::BIN_DIR/molauto $options $pdb_file";
	open(SCRIPT, " $command |" ) or die "$command: $!\n";
	while (<SCRIPT>) {
	    # fix title strings containing '"'s
	    if (/^title/) {
		s/"//g;
		s/(title) (.*)/$1 "$2"/;
	    }       

	    if (/end_plot/) {
		$lastline = $_;
		next;
	    }
	    # **************************************************************
	    # Section for adding DEF's
	    #
      	    if ($_ =~ /coil/) {
         	@temp=split ' ', $_;
         	chomp($temp[4]);
         	chop($temp[4]);
         	push (@ScriptArray, "comment \"DEF1 shape_$temp[0]_$temp[2]_$temp[4]\";\n");
         	push (@ScriptArray, $_);
         	next;
      	    }
      	    elsif ($_ =~ /helix/) {
         	@temp=split ' ', $_;
         	chomp($temp[4]);
         	chop($temp[4]);
         	push (@ScriptArray, "comment \"DEF1 shape_$temp[0]_$temp[2]_$temp[4]\";\n");
         	push (@ScriptArray, $_);
         	next;
	    }

	    elsif ($_ =~ /strand/) {
         	@temp=split ' ', $_;
         	chomp($temp[4]);
         	chop($temp[4]);
         	push (@ScriptArray, "comment \"DEF1 shape_$temp[0]_$temp[2]_$temp[4]\";\n");
         	push (@ScriptArray, $_);
         	next;
	    }

	    else {
	    	push @ScriptArray, $_;
	    }
 
	    if ($bgcolor ne "" && /^plot/) {
		push @ScriptArray, $bgcolor;
	    }

	    if ($bgcolor eq "" && /$start/) {
		push @ScriptArray, $greyString;
	    }
	}

	close SCRIPT;

	if ($cgi->param('disul') == 1) {

	    # *********************************************************
	    # Determine if DiSulfide Bonds exist and add info to script
	    #

	    $info->setProp("ssbond.com");
	    $ssBondRef = &GET_SSBONDS($info, uc($PDB_ID));
	 
	    if ($ssBondRef) {
		if (!$nocolor) {
			push @ScriptArray, "set colourparts on;\n";
		} else {
			push @ScriptArray, "set atomcolour atom * grey 0.7;\n";
		}

	        foreach (@{$ssBondRef}) {
		    $res1 = "${$_}{'ch1'}${$_}{'res1'}";
		    $res2 = "${$_}{'ch2'}${$_}{'res2'}";
		    push @ScriptArray, <<EOFSCRIPT;
  ball-and-stick in either residue $res1 or residue $res2;
  set bonddistance 2.5;
  ball-and-stick require atom SG and in either residue $res1 or residue $res2;
  set bonddistance 1.9;
EOFSCRIPT
	        }

	        # ****************************************************
	        # Add viewpoints for Disulfide Bonds
	        #

	        $count=0;
	        foreach (@{$ssBondRef}) {
		    $count++;
		    push @ScriptArray, <<EOFSCRIPT;
  viewpoint "Disulfide Bond #$count"
	from position require in
		residue ${$_}{'ch1'}${$_}{'res1'} and atom SG
	to position require in
		residue ${$_}{'ch1'}${$_}{'res1'} and atom CB
	10;
EOFSCRIPT
	        }
	    }
	}

	if ($cgi->param('sites') == 1) {
		# *********************************************************
		# Determine if SITE record exists and add info to script
		#

		$info->setProp("site.com");
		$siteRef = &GET_SITES($info, uc($PDB_ID));
		@names = keys %{$siteRef};

		if (@names) {
		    # create colors based on numsites
		    for ( $i=0; $i< scalar( @names ); $i++ ) {
			$hh[$i] = ($i)/(scalar(@names));
		    }

		    $sites = 0;
		    foreach $name (sort @names) {

			# set the colors
			$h = $hh[$sites++];
			if (!$nocolor) {
			    $key = "set atomcolour atom * hsb $h 0.8 1.0;\n";
			    $key .= "set planecolour hsb $h 0.8 1.0;\n";
			} else {
			    $key = "set atomcolour atom * grey 0.7;\n";
			}
			$key .= "ball-and-stick in either\n";
			push @ScriptArray,$key;

			$lastone = scalar @{${$siteRef}{$name}};
			$prelast = $lastone - 1;
			$count = 0;

			foreach (@{${$siteRef}{$name}}) {
			    $count++;

			    $key = "\trequire type ${$_}{'res'}";
			    $key .= " and residue ${$_}{'ch'}${$_}{'num'}";

			    if ($lastone == 1) {
				pop @ScriptArray;
				$key = "ball-and-stick in\n$key;";
				push @ScriptArray, $key;
				last;
			    } 
			    
			    if ($count < $prelast) {
				$key .= ",\n";
			    } elsif ($count == $prelast) {
				$key .= " or\n";
			    } elsif ($count == $lastone) {
				$key .= ";\n";
			    }

			    push @ScriptArray,$key;
			}

			push @ScriptArray, "\n";

		    }
		} # if (@names)
	} # end if ($cgi->param($key) == 1) {

	# **************************************************************
	# Add end plot to last line of @ScriptArray
	push @ScriptArray,$lastline;

	$Script = join "", @ScriptArray;

	if ($cgi->param('debug')) {
		print "Content-type: text/html\n\n";
		print "<html>\n";
		print "<head>\n";
		print "<title>Variables test Page</title>\n";
		print "</head>\n";
		print "<body>\n";
		print "script: $0\ndebug output on:<p>\n";
		print $cgi->dump();
		print "command=$command<br>\n";
		print "options=$options<br>\n";
		print "PDB_ID=$PDB_ID<br>\n";
		print "pdb_file=$pdb_file<br>\n";
		print "</pre>\n<p>\nmolauto output plus:\n<p>\n<pre>";
		foreach (@ScriptArray) {
		    print;
		}
		print "</pre>\n</body>\n";
		print "</html>\n";
		exit(0);
	} else {

		use IPC::Open2;
		$default_options = " -s -vrml -pretty ";
		$command = "molscript $default_options ";
		$pid = open2( \*IN, \*OUT, $command );
		print OUT @ScriptArray;
		close(OUT);
		@output = <IN>;
		close(IN);

		#Replace # DEF1 with DEF
		foreach $line (@output) {
   		    if ($line =~ /DEF1/) {
      			@temp=split ' ', $line;
      			chomp($temp[2]);
      			push (@out, "DEF $temp[2]\n");
      			next;
   		    }
   		    else {
      			push (@out, $line);
   		    }
		}

	    	#*************************************************
		# Create temp file based on sessionId 
		# if it doesn't exist.
		$sessionId = ($cgi->param('sessionId')
		
		$topdir = "$RCSB::TOP_DIR/pdb/temp";
		$direct = $topdir.$sessionId;

 		if (opendir(ROOT, "$direct")) {
		}
		else {
		    system(mkdir "$direct" );
		}
 		chdir("$direct");
		
		
		#*************************************************
		# Create temp file
		#

		$vrml_file = $pdbid.".wrl";
		open (VRML, ">$vrml_file");
		#foreach $line (@out) {
		for ($i=0; $i<=$#out; $i++) {
		    print VRML $line;
		}
		close (VRML);
		# mkindex on $vrml_file??
		system("chmod a+rw  $vrml_file ");

		#*************************************************
		# Return URL to file
		#
		$url = "http:\/\/www.rcsb.org:8400\/msd/temp\/$sessionId\/$vrml_file";
		return($url);
	}
}
