#!/usr/bin/env perl 

# Enable Perl warnings
#use strict;
use warnings;

use SOAP::Lite;
use Getopt::Long qw(:config no_ignore_case bundling);
use Data::Dumper;

my ($help, $outfile, $debug, $trace);
my %paramsI = (
	"Evalue"	=> 0.001,
	"Identity"	=> 30.0,
	"Overlap"	=> 80,
);
my %paramsO = ();

GetOptions(
	"evalue|E:f"	=> \$paramsI{"Evalue"},
	"identity|I:f"	=> \$paramsI{"Identity"},
	"overlap|X:i"	=> \$paramsI{"Overlap"},
	"stringency|s"	=> \$paramsO{"Stringency"},
	"verbosity|v"	=> \$paramsO{"Verbose"},
	"outfile|O:s"	=> \$outfile,
	"help|h"	=> \$help,
        'debug'         => \$debug, # Debug output 
	'trace'         => \$trace, # Show SOAP messages
);

my $NAMESPACE = 'http://www.ebi.ac.uk/WSsas';
my $ENDPOINT = 'http://www.ebi.ac.uk/thornton-srv/databases/cgi-bin/WSsas/WSsas.cgi';

# If required enable SOAP message trace
if ($trace) {
	print "Tracing active\n";
	SOAP::Lite->import( +trace => 'debug' );
}

if ( $help || !(-f $ARGV[0]) ) {
	&usage();
	exit;
}

# Get a service proxy and map SOAP faults to exceptions
my $soap = SOAP::Lite
    ->uri($NAMESPACE)
    ->proxy($ENDPOINT)
    ->on_fault(
	sub {
		my $soap = shift;
		my $res  = shift;

		# Throw an exception for all faults
		if ( ref($res) eq '' ) {
			die($res);
		}
		else {
			die( $res->faultstring );
		}
		return new SOAP::SOM;
	}
  );

my $Sequence;
if (-f $ARGV[0]) {	
	$Sequence=&read_file($ARGV[0]);	
}

my $sequenceData = SOAP::Data->name(Sequence=>$Sequence);
my $paramsIData = SOAP::Data->name(ParametersI=>\%paramsI);
my $paramsOData = SOAP::Data->name(ParametersO=>\%paramsO);
print STDERR "[debug] Submit runFUNCRES\n" if ($debug);
my $results = $soap->runFUNCRES($sequenceData, $paramsIData, $paramsOData);
if($debug) {
	print STDERR "[debug] results:\n", Dumper($results);
}

my $myoutput = "";
$myoutput .= '<sas_residue_annotation xmlns="http://www.ebi.ac.uk/WSsas/Schema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.ebi.ac.uk/WSsas/Schema WSsas.xsd">'."\n";
$myoutput .= "<features>\n";
my $i = 0;
foreach my $a ($results->dataof("//runFUNCRESResponse/sas_residue_annotation/features/*")) {
	$i ++;
	my $feature = $a->value->{'feature_name'};
	$myoutput .= "<feature>\n";
	$myoutput .= "<feature_name>$feature</feature_name>\n";
	if ((exists $a->value->{'residues'}) && (exists $a->value->{'residues'}->{'residue'})) {
		my $j = 0;
		$myoutput .= "<residues>\n";
		foreach my $b ($results->dataof("//runFUNCRESResponse/sas_residue_annotation/features/[$i]/residues/*")) {
			$j ++;
			my $residue_i = $b->value->{'residue_index'};
			my $residue_n = $b->value->{'residue_name'};
			$myoutput .= "<residue>\n";
			$myoutput .= "<residue_index>$residue_i</residue_index>\n";
			$myoutput .= "<residue_name>$residue_n</residue_name>\n";
			if ((exists $b->value->{'sourceref'}) && (exists $b->value->{'sourceref'}->{'reference'})) {
				$myoutput .= "<sourceref>\n";
				my $k = 0;
				foreach my $c ($results->dataof("//runFUNCRESResponse/sas_residue_annotation/features/[$i]/residues/[$j]/sourceref/*")) {
					$k ++;
					$myoutput .= "<reference>\n";
					my $reference_n = $c->value->{'ref_name'};
					my $reference_c = $c->value->{'ref_chain'};
					my $reference_i = $c->value->{'ref_index'};
					my $reference_r = $c->value->{'ref_residue'};
					$myoutput .= "<ref_name>$reference_n</ref_name>\n";
					$myoutput .= "<ref_chain>$reference_c</ref_chain>\n";
					$myoutput .= "<ref_index>$reference_i</ref_index>\n";
					$myoutput .= "<ref_residue>$reference_r</ref_residue>\n";
					if (exists $c->value->{'annotations'}) {
						$myoutput .= "<annotations>\n";
						foreach my $d ($results->dataof("//runFUNCRESResponse/sas_residue_annotation/features/[$i]/residues/[$j]/sourceref/[$k]/annotations/*")) {
							my $annotation = $d->value();
							$myoutput .= "<annotation>$annotation</annotation>\n";
						}
						$myoutput .= "</annotations>\n";
					}
					if (exists $c->value->{'atomic_contacts'}) {
						$myoutput .= "<atomic_contacts>\n";
						foreach my $d ($results->dataof("//runFUNCRESResponse/sas_residue_annotation/features/[$i]/residues/[$j]/sourceref/[$k]/atomic_contacts/*")) {
							$myoutput .= "<atomic_contact>\n";
							my $contact_n = $d->value->{'contact_name'};
							my $contact_r = $d->value->{'ref_atom'};
							my $contact_p = $d->value->{'partner_atom'};
							my $contact_c = $d->value->{'partner_compound'};
							$myoutput .= "<contact_name>$contact_n</contact_name>\n";
							$myoutput .= "<ref_atom>$contact_r</ref_atom>\n";
							$myoutput .= "<partner_atom>$contact_p</partner_atom>\n";
							$myoutput .= "<partner_compound>$contact_c</partner_compound>\n";
                                                                $myoutput .= "</atomic_contact>\n";
						}
						$myoutput .= "</atomic_contacts>\n";
					}
					$myoutput .= "</reference>\n";
				}
				$myoutput .= "</sourceref>\n";
			}
			$myoutput .= "</residue>\n";
		}
		$myoutput .= "</residues>\n";
	}
	$myoutput .= "</feature>\n";
}
$myoutput .= "</features>\n";

$myoutput .= "<sources>\n";
foreach my $source ($results->valueof('//runFUNCRESResponse/sas_residue_annotation/sources/source/')) {
	$myoutput .= "<source>\n";
	my $source_n = $source->{'source_name'};
	my $source_i = $source->{'ref_identity'};
	my $source_o = $source->{'ref_overlap'};
	my $source_e = $source->{'ref_evalue'};
	my $source_p = $source->{'ref_pmid'};
	$myoutput .= "<source_name>$source_n</source_name>\n";
	$myoutput .= "<ref_identity>$source_i</ref_identity>\n";
	$myoutput .= "<ref_overlap>$source_o</ref_overlap>\n";
	$myoutput .= "<ref_evalue>$source_e</ref_evalue>\n";
	if ($source_p) {
		$myoutput .= "<ref_pmid>$source_p</ref_pmid>\n";
	}
	$myoutput .= "</source>\n";
}
$myoutput .= "</sources>\n";
$myoutput .= "</sas_residue_annotation>\n";

if ($outfile) {
	print STDERR "[debug] Write result to $outfile\n" if $debug;
	open (OUT, ">$outfile");
	print OUT "$myoutput\n";
	close OUT;
}
else {
	print STDERR "[debug] Get feature_names\n" if $debug;
	print "$myoutput";
}

sub read_file {

        my $filename = shift;

        my $content;
        open(FILE, $filename);
        while (<FILE>) {
                next if (/^>/);
                chomp;
                s/\*$//;
                $content .= $_;
        }
        close(FILE);

        return $content;
}

sub usage {
	print STDERR <<EOF

WSsas
=====

Sequence Annotated by Structure (Web Service)

For more information on this tool, please, refer to
http://www.ebi.ac.uk/thornton-srv/databases/sas/

[Required]
	seqfile.fasta	: file containing a protein sequence

[Optional]
	-h, --help	: prints this help text

	-s, --stringency: The presence of identical atoms in the query and
                          the hits is required for the prediction [Default
                          = FALSE]
	-v, --verbosity	: Output contains information about the atomic
                          contacts [Default = FALSE]

	-E, --evalue	: E-value from the FASTA search used for the 
                          functional annotation [Default = 0.001]
	-I, --identity	: Identity percentage between aligned stretches 
                          used for the functional annotation [Default = 30]
	-O, --outfile	: Output file. If no file is defined, results are 
                          printed on the screen
	-X, --overlap	: Overlap (number of residues) between query and 
                          hit sequences used for the functional annotation 
                          [Default = 80]
Usage:
	perl $0 [options] seqfile.fasta

EOF
;
}
