#####################################################################
#!/usr/bin/perl -w
# Mode: perl
# Programmer: Kuan Chang
# Date: 3/14/2002
#####################################################################

use strict;
use lib '/export/share_more/ensembl/gramene_ensembl/perl/ontology/';

use DBI;
use CGI qw(:standard *table *TR *th *td *ul *ol);
use OntologyDB;
use GL qw(:DEFAULT);
use GramenePage;
use File::Temp qw/ tempfile /;

#####################################################################
# constants
use constant DISPLAY_CUTOFF => 100; 
my $GO_PREFIX = "GO:";
my $TO_PREFIX = "TO:";
my $TAIR_PREFIX = "PO:";
my $INVALID_TYPE = -1;
my $GO_TYPE = 1;
my $TO_TYPE = 2;
my $TAIR_TYPE = 3;
my $HTML_HOME = "/plant_ontology";
my $EXE_HOME ="/perl/ontology/";
my $EXE_NAME ="search_term";
my $SEARCH_PROTEIN_EXE_NAME ="protein_search";

#####################################################################
# Connect to the database
my $db = OntologyDB->new();
my $page = GramenePage->new(Apache->request);

my $input  = param('id');
my $turn_on_display = param('display') ? 1 : undef;
#my ($accession, $is_TO) = extract_accessionID($input);
my ($accession, $term_type) = extract_accessionID($input);
#my $id   = $input ?  $db->get_termID($accession, $is_TO) : undef;
my $id   = $input ?  $db->get_termID($accession, $term_type) : undef;
my $name;
my $definition;
my $synonym;
my $comment;
# my @gene_product_ids =();
my $is_GO;
my $is_TO;
my $is_TAIR;
my (@gene_product_ids, @association_ids, @gene_product_names, @gene_product_symbols, @evidence_codes, @term_accessions, @term_names);
my ($gene_product_ids_ref, $association_ids_ref, $gene_product_names_ref, $gene_product_symbols_ref, $evidence_codes_ref, $term_accessions_ref, $term_names_ref);


if(defined $term_type){
  if($term_type == $GO_TYPE) {
    $is_GO = 1;
  }
  
  if($term_type == $TO_TYPE) {
    $is_TO = 1;
  }
  
  if($term_type == $TAIR_TYPE) {
    $is_TAIR = 1;
  }
}

if(defined $id ){
  $name       =  $db->get_name($id);
  $definition =  $db->get_definition($id);
  $synonym =  $db->get_synonym($id);
  $comment = $db->get_comment($id);
  undef @gene_product_ids; 

  if($term_type == $GO_TYPE){

    ($gene_product_ids_ref, $association_ids_ref, $gene_product_names_ref, $gene_product_symbols_ref, $evidence_codes_ref, $term_accessions_ref, $term_names_ref) = $db->get_quick_go_to_rice($id);

    #@term_ids = @$term_ids_ref;
    @gene_product_ids = @$gene_product_ids_ref;
    @association_ids = @$association_ids_ref;
    @gene_product_names = @$gene_product_names_ref;
    @gene_product_symbols = @$gene_product_symbols_ref;
    @evidence_codes = @$evidence_codes_ref;
    @term_accessions = @$term_accessions_ref;
    @term_names = @$term_names_ref;
  }
}

my $cgi = new CGI;
print $cgi->header;

if(defined $id){

my $go_accession =  $db->get_accession($id);

if($term_type == $TO_TYPE){
  print $cgi->start_html(-title=>"Summary for TO Term: $name ($go_accession)",
			 -style=>{'src'=>'/stylesheets/gramene.css'});
}
elsif($term_type == $TAIR_TYPE) {
  print $cgi->start_html(-title=>"Summary for TAIR Term: $name ($go_accession)",
			  -style=>{'src'=>'/stylesheets/gramene.css'}); 
}
else{
  print $cgi->start_html(-title=>"Summary for GO Term: $name ($go_accession)",
			 -style=>{'src'=>'/stylesheets/gramene.css'});  
}

print header();
print $page->start_body;

if($term_type == $TO_TYPE) {
  print_search_area();
  print h1("Summary for TO Term: <i>$name</i> ($go_accession)");
}
elsif($term_type == $TAIR_TYPE){
  print_search_area();
  print h1("Summary for TAIR Term: <i>$name</i> ($go_accession)");
}
else {
  print_search_area();
  print h1("Summary for GO Term: <i>$name</i> ($go_accession)"); 
}

print start_table({-width=>'98%', -align=>'center', -cellpadding=>4, -cellspacing=>1});
print TR(th({-align=>'left', -class=>'datatitle', -width=>'12%'}, 'Term Name'), td({-class=>'databody'}, $name));
if(defined $synonym)
{
  print  TR(th({-align=>'left', -class=>'datatitle'}, 'Synonym'), td({-class=>'databody'}, $synonym||'No synonym available'));
}
if(defined $definition) 
{ 
  print  TR(th({-align=>'left', -class=>'datatitle'}, 'Definition'), td({-class=>'databody'},$definition||'No definition available'));
}
if(defined $comment)
{
  print TR(th({-align=>'left', -class=>'datatitle'}, 'Comment'), td({-class=>'databody'},$comment||'No comment available'));
}
  
print end_table;

#print_tree($id);
if(defined $is_GO) {
  print_tree($id, 1);
}

if(defined $is_TO) {
  print_tree($id, 2);
}

if(defined $is_TAIR) {
  print_tree($id, 3);
}


if($term_type > $GO_TYPE){
  print_immediate_family($id);
}

if(defined  @gene_product_ids) {
#  my @filtered_gene_product_ids = ();
#  undef @filtered_gene_product_ids;
#  @filtered_gene_product_ids = @gene_product_ids;

#  if(defined @filtered_gene_product_ids){

  print hr();
  print start_table({-border=>'1', -width=>'98%', -align=>'center', -cellpadding=>4, -cellspacing=>1});

  my $template_name = "GO2Rice_" . $go_accession . "_XXXXX";
  #my $template_name = "GO2Rice_" . $go_accession . ".txt";
  my ($fh, $filename) = tempfile($template_name, DIR=> "download");
  my $count2 = 0;
  print $fh "GO ID\tTERM NAME\tGRAMENE ID\tGENE PRODUCT NAME\tGENE SYMBOL\tEVIDENCE CODE\n";

  while($count2 <= scalar(@gene_product_ids)){
    print $fh "$term_accessions[$count2]\t$term_names[$count2]\t$gene_product_ids[$count2]\t$gene_product_names[$count2]\t$gene_product_symbols[$count2]\t$evidence_codes[$count2]\n";
    $count2 ++;
  }

  close $fh;
  my $old_filename = $filename;
  $filename =~ s/_\w+$//;
  my @command_args2 = ("mv", $old_filename, $filename);
  system(@command_args2) == 0 or die "system failed: $?";
  
  my $filename2 = $filename . ".zip";
  my @command_args = ("zip", "-j", $filename2, $filename);
  # close $fh;
  system(@command_args) == 0 or die "system failed: $?";
  my @fnames = split("/", $filename);
  my $filename3 = "/ontology/download/$fnames[scalar(@fnames)-1]" . ".zip";

  #decide 
  if(scalar(@gene_product_ids) == 1) {
     $turn_on_display = 1;
     print TR({-align=>'left', -class=>'datatitle'},th('Gene Product Association (', ($#gene_product_ids+1), ' record found )'), start_form(-method=>'GET', -action=>"$filename3"), td(submit(-value=>'Download')), end_form());
  }
  elsif(scalar(@gene_product_ids) <= DISPLAY_CUTOFF){
    $turn_on_display = 1;
    print TR({-align=>'left', -class=>'datatitle'},th('Gene Product Association (', ($#gene_product_ids+1), ' records found )'), start_form(-method=>'GET', -action=>"$filename3"), td(submit(-value=>'Download')), end_form());
  }
  elsif(defined $turn_on_display){
    
    print TR({-align=>'left', -class=>'datatitle'},th('Gene Product Association (', ($#gene_product_ids+1), ' records found )'), start_form(-method=>'GET', -action=>"$filename3"), td(submit(-value=>'Download')), end_form());
  }
  else{
    print TR({-align=>'left', -class=>'datawarning'}, th('NOTICE: Please be patient!&nbsp It will take a while to display all the associations!'), td('&nbsp'), td('&nbsp'));
  
    print TR({-align=>'left', -class=>'datatitle'},th('Gene Product Association (', ($#gene_product_ids+1), ' records found )'), start_form(-method=>'GET', -action=>"$filename3"), td(submit(-value=>'Download')), end_form(), start_form(-method=>'GET', -action=>"search_term"), hidden(-name=>'id', -value=>"$input"), td(submit(-name=>'display', -value=>'Display All')), end_form() );
  }

  print end_table;

  if(defined $turn_on_display){
    print start_table({-border=>'1', -width=>'98%', -align=>'center', -cellpadding=>4, -cellspacing=>1});
    print TR({-align=>"left", -class=>'datatitle'},
	     th(['#','Associated GO Term', 'Associated Product Name', 'Product Symbol', 'Evidence Code']));
    my $count = 0;
    my $current_name  =  $db->get_name($id);	
    my $current_co_name = '<span class="currentterm">'.$current_name.'</span>';
    #for my $gene_product_id (@filtered_gene_product_ids) {
    while($count < scalar(@gene_product_ids)){
      my $gene_product_symbol = $gene_product_symbols[$count];
      my $gene_product_name = $gene_product_names[$count];
      my $association_id = $association_ids[$count];
      my $quick_evidence_codes = $evidence_codes[$count];
      $count ++;

      if($count %2 == 1) {	
	print start_TR({-align=>'left', -class=>'databody'});
      }else {
	print start_TR({-align=>'left'});	
      }
      print td($count);
      #print td($term_ids[$count - 1]);

      my $current_term_accession =  $term_accessions[$count-1];
      $current_term_accession =~ s/$GO_PREFIX//;
      if($current_term_accession == $accession) {
	print td($current_co_name);
      }
      else{
	print td(a({-href=>"$EXE_NAME?id=".($term_accessions[$count-1])}, $term_names[$count-1]));
      }
      
      print td(a({-href=>"../$SEARCH_PROTEIN_EXE_NAME?protein_id=".($gene_product_ids[$count-1])},$gene_product_name));
      print td($gene_product_symbol|| 'Not Available');
      print td($quick_evidence_codes);
      print end_TR;   
    }
    print end_table;
  }
# }
}

if($term_type == $GO_TYPE){
print p("More information about this term can be found at",
        a({-target=>'_blank',-href=>"http://golgi.ebi.ac.uk/ego/QuickGO?mode=display&entry=$go_accession"},"the Interpro GO browser."));
}
}
else{
  print_top("Cannot find any information about $input");
  print_search_area();	
  print h1("Sorry! Cannot find any information about <i>$input</i>");
}
print $page->end_body;

sub print_tree {
  my ($id, $term_typeII) = @_;
  my $self = url(-relative=>1);
  my $name  =  $db->get_name($id);	
  my $co_name = '<span class="currentterm">'.$name.'</span>';

  print start_table({-width=>'98%',-align=>'center',-cellpadding=>3, -cellspacing=>0});
  print TR({-class=>'datatitle', -align=>'left'},th('Derivation'));
  print start_TR({-class=>'databody'}), start_td;

  my @paths = get_paths($id);
  my %seen_it;
  my $previous = 0;
  for my $path (@paths) {
    my $skip;
    for my $component (@$path) {
      print start_ul();
      if($seen_it{$component} && !$skip){
	$previous = $component;
      }
      next if $seen_it{$component}++ && !$skip;
      $skip++;
      my $magic = $db->get_accession($component);

      if($term_typeII == 1){
	my $gene_count = $db->get_gene_association_count($component);
	print li($component eq $id ? ($db->get_relationship_symbol($previous, $component), b($co_name. " (".$magic.")" . " #<i>$gene_count</i>" )) 
		 : ($db->get_relationship_symbol($previous, $component), object_link($component,b($db->get_name($component) ." (".$magic.")")), " #<i>$gene_count</i>")),"\n";
      }
      else{
	print li($component eq $id ? ($db->get_relationship_symbol($previous, $component), b($co_name. " (".$magic.")")) 
		 : ($db->get_relationship_symbol($previous, $component), object_link($component,b($db->get_name($component) ." (".$magic.")")))),"\n";
      }
      
       $previous = $component;
    }

    if (my @children = $db->get_children($id)) {

      foreach my $child (@children) {
	#if($term_typeII == $GO_TYPE){
	if($term_typeII == 1){
	  print ul(li($db->get_relationship_symbol($id, $child).a({-class=>'gopage', -href=>"$self?id=".$db->get_accession($child)}, $db->get_name($child) . " (".$db->get_accession($child).")") ." #<i>".$db->get_gene_association_count($child)."</i>"  ));
	}else{
	  print ul(li($db->get_relationship_symbol($id, $child).a({-class=>'gopage', -href=>"$self?id=".$db->get_accession($child)}, $db->get_name($child) . " (".$db->get_accession($child).")")));
	}
      }
    }
    print scalar(end_ul()."\n") x @$path;
  }
  print end_td,end_TR,end_table;
}

sub print_search_area {
  my $self = url(-relative=>1);
  print start_form(-method=>'GET', -action=>"search");
  print table({-width=>'100%', -align=>'center'}, '<th align=center class=searchtitle>Ontology Database</th><tr align=center class=searchbody><td align=center><span class="alert">Type in ID or keyword to search for</span>&nbsp;&nbsp;&nbsp;<input type=text value="" framewidth=4 name=query size=50 maxlength=256>&nbsp;&nbsp;&nbsp;&nbsp;<input name=btn type=submit value="Ontology Search"> &nbsp;&nbsp;<input name=Clear type=reset value="Clear"><p>[e.g. <a href="/perl/ontology/search_term?id=TO:0000303">cold tolerance</a> or <a href="/perl/ontology/search_term?id=TO:0000303">TO:0000303</a>] &nbsp;&nbsp;&nbsp;<a href="/documentation/ontology_help.html">HELP</a> </p></td></tr>' );
  
  print end_form();
  print "<hr>"; 	
}

sub print_immediate_family {
  my $id = shift;
  my $self = url(-relative=>1);
  my @parents = $db->get_parents($id);
  my @children = $db->get_children($id);
  my $parent_title = 'Parent Term';
  my $children_title = 'Child Term';

  if($#parents+1 > 1) {
    $parent_title .= 's';
  }

  if($#children+1 > 1) {
    $children_title .= 's';
  }

  if($#parents+1 > 0 || $#children+1 > 0) {
    print start_table({-width=>'98%',-cellpadding=>3,-cellspacing=>0, -align=>"center"});

    if($#parents+1 > 0 && $#children+1 > 0) {
      print TR({-align=>"left", -class=>'datatitle'}, 
	   th($parent_title." (".($#parents+1).")"),
	   th($children_title." (".($#children+1).")"));
    }
    elsif($#parents+1 <= 0) {
      print TR({-align=>"left", -class=>'datatitle'}, 
	       th($children_title." (".($#children+1).")"));
    }
    elsif($#children+1 <= 0) {
      print TR({-align=>"left", -class=>'datatitle'}, 
	       th($parent_title." (".($#parents+1).")"));
    }

    print start_TR({-class=>'databody'}), start_td;
    if($#parents + 1 > 0) {
      print "<ul>";
      foreach my $parent (@parents) {
	print li($db->get_relationship_symbol($parent, $id).a({-class=>'gopage', -href=>"$self?id=".$db->get_accession($parent)}, $db->get_name($parent) . " (".$db->get_accession($parent).")") );
      }
      print "<\ul>";
      #  print ul(li([map { a({-class=>'gopage', -href=>"$self?id=".$db->get_accession($_)}, $db->get_name($_) . " (".$db->get_accession($_).")") } @parents]));
      print end_td;
    }

    if($#children + 1 > 0) {
      print start_td;
      print "<ul>";
      foreach my $child (@children) {
	print li($db->get_relationship_symbol($id, $child).a({-class=>'gopage', -href=>"$self?id=".$db->get_accession($child)}, $db->get_name($child) . " (".$db->get_accession($child).")") );
     } 
      print "</ul>";
    #  print ul(li([map { a({-class=>'gopage', -href=>"$self?id=".$db->get_accession($_)}, $db->get_name($_) . " (".$db->get_accession($_).")") } @children]));
      print end_td;
    }
    print end_TR,end_table;
  }
}

sub get_paths {
  my $id    = shift;
  my @result;
  my @parents = $db->get_parents($id);
  return [$id] unless @parents;
  for my $parent (@parents) {
    my @paths = get_paths($parent);
    push @result,[@$_,$id] foreach @paths;
  }
  @result;
}

sub object_link {
  my($term_id,$title) = @_;
  my $accession = $db->get_accession($term_id);
  my $href = "$EXE_HOME$EXE_NAME?id=$accession";
  return a({-href=>$href,-class=>'gopage'},$title);
}

# utility functions
sub extract_accessionID{
  my $id = shift;
  my $term_typeI = $INVALID_TYPE;
  
  if($id =~ /$TO_PREFIX/) {
    $id =~ s/$TO_PREFIX//;
    $term_typeI = $TO_TYPE;
  }
  elsif($id =~ /$TAIR_PREFIX/){
    $id =~ s/$TAIR_PREFIX//;
    $term_typeI = $TAIR_TYPE;
  }
  elsif($id =~ /$GO_PREFIX/){
    $id =~ s/$GO_PREFIX//;
    $term_typeI = $GO_TYPE;
  }
  else{
    $term_typeI = $INVALID_TYPE;
  }

  return ($id, $term_typeI);
}

1;
