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

#use warnings;
use strict;

use CGI qw(:standard *table *TR *th *td *ul *ol);
use Gramene::Ontology::OntologyDB;
use Gramene::Page;
use File::Temp qw/ tempfile /;
use POSIX;

#####################################################################
# constants
use constant DISPLAY_CUTOFF => 100;
use constant ICON_HOME => '/images/icons/'; 
use constant HTML_HOME => '/plant_ontology';
use constant EXE_HOME =>'/db/ontology/';
use constant EXE_NAME =>'search_term';
use constant SEARCH_PROTEIN_EXE_NAME =>'protein_search';

my $GO_TYPE = 1;
my $TRAIT_TYPE = 5;
my $GROWTH_STAGE_TYPE = 7;
my $PO_TYPE = 6;
my $EO_TYPE = 9;
my $GR_TAX_TYPE = 10;
#####################################################################

local $SIG{CHLD} = 'DEFAULT'; # for debug the system failed

# Connect to the database
my $db       = Gramene::Ontology::OntologyDB->new();
my $page     = Gramene::Page->new( Apache->request );
my $doc_root = Apache->request->document_root;
my $term_id  = param( 'term_id' ) || '';
my $input    = param( 'id' ) || '';
$input       =~ s/^\s+|\s+$//g;
my $id       = $term_id ? $term_id : $input ? $db->get_termID( $input ) : undef;

my ($name,$term_type_id, $term_type, $accession,$is_obsolete) =  $db->get_term($id) if $id;
if($term_type_id <= 4){
  $term_type_id = 1; # all GO types(process, component etc. treat the same as one type)
}elsif($term_type_id == 11 ){
    $term_type_id = 6; # PO growth stage
}


my ($definition,$comment);
my $synonym;
my $total_association_count;



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

if(! defined $accession){ # nothing found
    print $page->start_html(-title=>"Cannot find any info about $input");
    print $page->start_body;
    print_search_area();	
    print h1("Sorry! Cannot find any information about <i>$input</i>");

    print $page->end_body;

}else{

    ($definition,$comment) =  $db->get_definition_and_comment($id);
    $synonym =  $db->get_synonym($id);

    my $xref_db_urls = $db->get_all_xref_db_urls();

    my $term_xrefs = $db->get_term_xrefs($id);

    $total_association_count = $db->get_association_count_by_type($id,'');

    my %term_type_desc=(
          $GO_TYPE => 'GO',
          $TRAIT_TYPE => 'TO',
          $GROWTH_STAGE_TYPE => 'Gramene growth stage',
          $PO_TYPE => 'PO',
          $EO_TYPE => 'EO',
          $GR_TAX_TYPE => 'Gramene taxonomy'
    );



    print $page->start_html(-title=>
        "Summary for $term_type_desc{$term_type_id} Term: $name ($accession)");
    print $page->start_body;
    print_search_area();
    if($total_association_count && $total_association_count>0) {
	print <<SMALLBAR_AN;
	&nbsp;&nbsp;<img src="/images/icons/grain_icon.jpg" alt="grain_icon" height=16 width=16 align="top">
	&nbsp;<a href="#term" class="gopage"><b>Term</b></a>&nbsp;
	|&nbsp;<a href="#associations" class="gopage"><b>Annotations</b></a>&nbsp;
SMALLBAR_AN

    }
    print h1("<a name=\"term\"></a>Summary for $term_type_desc{$term_type_id} Term: <i>$name</i> ($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'));
    }
  
    print  TR(th({-align=>'left', -class=>'datatitle'}, 'Aspect'), td({-class=>'databody'}, $term_type));
    if(defined $definition) 
    { 
      print  TR(th({-align=>'left', -class=>'datatitle'}, 'Definition'), td({-class=>'databody'},$definition||'No definition available'));
    }


    if($comment) 
    { 
      
	$comment =~s#\\:#:#g;  # GO add \: in the acc, have to remove
	print  TR(th({-align=>'left', -class=>'datatitle'}, 'Comment'), td({-class=>'databody'},$comment));
    }

    if($term_xrefs && scalar(@$term_xrefs)>0){
	my $xrefs='';
	foreach my $xref (@$term_xrefs){
	    my ($db_name,$db_key) = split(/:/,$xref,2);
	    my $url_link = _get_xref_url($xref_db_urls,$db_name, $db_key);
	    $xrefs.="$db_name:$url_link".'&nbsp;&nbsp; ';
	}
	print  TR(th({-align=>'left', -class=>'datatitle'},'External References'),td({-class=>'databody'},$xrefs));

    }

    # link to GOC, POC
     if($term_type_id == $GO_TYPE){
	print TR(th({-align=>'left', -class=>'datatitle'},'Source Ontology
	Database Link'),td({-class=>'databody'}, a({-target=>'_blank',-href=>"http://amigo.geneontology.org/cgi-bin/amigo/go.cgi?query=$accession&search_constraint=terms&action=query&view=query"},"The GO browser of Gene Ontology Database.")));
      }elsif($term_type_id == $PO_TYPE){
	print TR(th({-align=>'left', -class=>'datatitle'},'Source Ontology Database Link'),td({-class=>'databody'}, a({-target=>'_blank',-href=>"http://www.plantontology.org/amigo/go.cgi?action=plus_node&depth=1&search_constraint=terms&query=$accession"},"The ontology browser of Plant Ontology Database.")));
    }


    print end_table;

    if($term_type_id){
      if($term_type_id == $GO_TYPE) {
	 print_tree($db,$id, 1);
      }else{
	 print_tree($db,$id,2);
	 print_immediate_family($db,$id);
      }
    }

    # print association statistics report
    if($total_association_count && $total_association_count>0) { 
	print_associations($db,$id,$accession,$total_association_count); 
      }




#
#    # link to GOC, POC
#     if($term_type_id == $GO_TYPE){
#        print p("&nbsp;&nbsp;More information about this term can be found at",
#        a({-target=>'_blank',-href=>"http://amigo.geneontology.org/cgi-bin/amigo/go.cgi?action=plus_node&search_constraint=terms&query=$accession"},"the GO browser of Gene Ontology Database."));
#      }elsif($term_type_id == $PO_TYPE){
#        print p("&nbsp;&nbsp;More information about this term can be found at",
#        a({-target=>'_blank',-href=>"http://www.plantontology.org/amigo/go.cgi?action=plus_node&depth=1&search_constraint=terms&query=$accession"},"the ontology browser of Plant Ontology Database."));
#      }
#
      print $page->end_body;

}


#####################################################
sub print_tree {
  my ($db,$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($db,$id);
  my @paths_unsorted = get_paths($db,$id); # liya
  #sort the family tree, make the short branch showed first to avoid the script
  #ignoring them if they showed in long branch already 
  my @paths = sort by_depth @paths_unsorted; # liya

  my %seen_it;
  my $previous = 0;
  for my $path (@paths) {
    my $skip;  # every path reset the skip
    for my $component (@$path) {
      print start_ul();
      if($seen_it{$component} && !$skip){
	$previous = $component;    
      }
      next if $seen_it{$component}++ && !$skip;      #skip the showed component
      $skip++;
      my $magic = $db->get_accession($component);
      my $early_children_count =  $db->get_term_children_count($component);


      my $assoc_count = $db->get_association_count_by_type($component,'');

      if($term_typeII == 1){
	    if($early_children_count){
	        print li($component eq $id ? ($db->get_relationship_symbol($previous, $component), b($co_name. " (".$magic.")" . " #<i>$assoc_count</i>")) 
		 : ($db->get_relationship_symbol($previous, $component), object_link($db,$component,b($db->get_name($component) ." (".$magic.")")), " #<i>$assoc_count</i>", img({-src=>ICON_HOME . "plus.gif", -height=>15, -width=>15, -align=>"absmiddle"}) )),"\n";
	   # img({-src=>ICON_HOME . "plus.gif", -alt=>"haha"});
	    } else{
	        print li($component eq $id ? ($db->get_relationship_symbol($previous, $component), b($co_name. " (".$magic.")" . " #<i>$assoc_count</i>" )) 
		 : ($db->get_relationship_symbol($previous, $component), object_link($db,$component,b($db->get_name($component) ." (".$magic.")")), " #<i>$assoc_count</i>")),"\n";
	    }

     }else {
	    if($early_children_count){
	        print li($component eq $id ? ($db->get_relationship_symbol($previous, $component), b($co_name. " (".$magic.")" . " #<i>$assoc_count</i>")) 
		 : ($db->get_relationship_symbol($previous, $component), object_link($db,$component,b($db->get_name($component) ." (".$magic.")")), " #<i>$assoc_count</i>", img({-src=>ICON_HOME . "plus.gif", -height=>15, -width=>15, -align=>"absmiddle"}) )),"\n";
	    } else{
	        print li($component eq $id ? ($db->get_relationship_symbol($previous, $component), b($co_name. " (".$magic.")" . " #<i>$assoc_count</i>" )) 
		 : ($db->get_relationship_symbol($previous, $component), object_link($db,$component,b($db->get_name($component) ." (".$magic.")")), " #<i>$assoc_count</i>")),"\n";
	    }
	}

	$previous = $component;
    }

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

        foreach my $child (@children) {
	    my $children_count = $db->get_term_children_count($child);
            my $child_assoc_count = $db->get_association_count_by_type($child,'');
	    if($term_typeII == 1){
	        if($children_count) {
		    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>".$child_assoc_count."</i>", img({-src=>ICON_HOME . "plus.gif", -height=>15, -width=>15, -align=>"absmiddle"})  ));
		} 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).")") ." #<i>".$child_assoc_count."</i>"  ));
		}
	    } else {
	        if($children_count) {
		    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>".$child_assoc_count."</i>", img({-src=>ICON_HOME . "plus.gif", -height=>15, -width=>15, -align=>"absmiddle"})  ));
		} 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).")") ." #<i>".$child_assoc_count."</i>"  ));
		}
	    }
	    # undef $children_count;
	}
    }
    print scalar(end_ul()."\n") x @$path;
 
    # reset the seen_it to previous components only,some tree branches can be traversed more than once, can't ignore them    
    %seen_it = map { $_=>1 } @$path;
 
  }
  print end_td,end_TR,end_table;
}

sub print_search_area {
  my $self = url(-relative=>1);
  print <<SMALLBAR;
<table>
  <tr>
    <td align="left">&nbsp;<img src="/images/icons/grain_icon.jpg" alt="grain_icon" height=16 width=16 align="top">
    </td>
    <td align="left">
        &nbsp;<a href="/plant_ontology/index.html#ontology" class="gopage"><b>Current Ontologies</b></a>&nbsp; 
        |&nbsp;<a href="/plant_ontology/index.html#doc" class="gopage"><b>Documentation</b></a>&nbsp; 
        |&nbsp;<a href="/plant_ontology/index.html#evi" class="gopage"><b>Evidence code</b></a>&nbsp; 
        |&nbsp;<a href="/plant_ontology/index.html#ftp" class="gopage"><b>FTP</b></a>&nbsp; 
        |&nbsp;<a href="/plant_ontology/index.html#sub" class="gopage"><b>Ontology suggestion</b></a>&nbsp; 
        |&nbsp;<a href="/plant_ontology/index.html#assoc" class="gopage"><b>Associations</b></a>&nbsp; 
        |&nbsp;<a href="/plant_ontology/index.html#pub" class="gopage"><b>Publications</b></a>&nbsp;
        |&nbsp;<a href="/tutorials/ontologies.html" class="gopage"><b>Tutorial</b></a>  &nbsp;
       |</b>&nbsp;<a href="/fom/cache/1.html" class="gopage"><b>FAQ</b></a>  &nbsp;
       |</b>&nbsp;<a href="/documentation/ontology_help.html" class="gopage"><b>HELP</b></a>  &nbsp;
 
    </td>
  </tr>
</table>
<p></p>
        <form action="/db/ontology/search" method=get name=f>
          <table align=center border=0 cellspacing=0 cellpadding=1 width='98%'>
            <tr>
            <th colspan=3 align=center class=searchtitle>Ontology Database</th>
            </tr>
            <tr align=center class=searchbody>
              <td align=center width=30%><span class="alert">Type ID or keyword to search</span></td>
              <td align=left width=40%><input type=text value="" framewidth=4 name=query size=55 maxlength=256></td>
              <td align=center width=30%>&nbsp;<input name=btn type=submit value="Search"> &nbsp;<input name=Clear type=reset value="Clear">
              </td>
            </tr>
            <tr class=searchbody>
              <td align=center nowrap width=30%>
              select ontology (optional) &nbsp;
              </td>
              <td align=left nowrap width=30%>

                 <input type=checkbox name=ontology_type value="GO">Gene (GO)&nbsp;
                 <input type=checkbox name=ontology_type value="PO">Plant structure (PO)&nbsp;
                 <input type=checkbox name=ontology_type value="GRO">Growth stage (GRO)<br>
                 <input type=checkbox name=ontology_type value="TO">Trait (TO) &nbsp;&nbsp;
                 <input type=checkbox name=ontology_type value="EO">Environment (EO)&nbsp;&nbsp;

                 <input type=checkbox name=ontology_type value="GR_tax">Taxonomy(GR_tax)
              </td>
              <td align=center width=30%>[e.g. <a href="/db/ontology/search?query=flower&btn=Search">flower</a> or <a href="/db/ontology/search?query=TO:0000303&ontology_type=TO&btn=Search">TO:0000303</a>]
                          </td>
            </tr>
    </table>
        </form>
	<hr width="100%">
SMALLBAR

}

sub print_immediate_family {
  my ($db,$id) = @_;
  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 print_associations{
    my ($db,$id,$accession, $total_association_count) = @_;
    my @ordered_object_types = (
	'QTL',
	'Marker library',
	'Marker species',
	'Map set',
	'Gene',
	'Ensembl rice gene',
	'Ensembl maize gene',
	'Ensembl arabidopsis gene',
	'Protein'
    );

	my $total_objects = $db->get_total_associated_object_count($id);
	my @object_types = $db->get_associated_object_types($id);
	my $anno_url="/db/ontology/association_report?id=$accession";
	my %annotations;
	foreach my $obj_type (@object_types){
	    my $species_to_obj_count = $db->get_associated_objects_count_by_type($id,$obj_type);
	    my $obj_counts_by_spe = []; 
	    my $obj_count = 0;
	    my $species_count = 0;
	    foreach my $spec (sort keys %$species_to_obj_count){
		my $spec_count = $species_to_obj_count->{$spec};
		$obj_count += $spec_count;
		my $spec_anno_link= "$spec(".'<a href="'.$anno_url."&object_type=$obj_type&object_species=$spec".'">'.$spec_count.'</a>)';
		push @{$annotations{$obj_type}->{'count_by_spe'}},$spec_anno_link; 
	    }

	    $annotations{$obj_type}->{'total_object_count'}= $obj_count;
    
      }
	  print '<a name="associations"></a>';
	  print hr();
	  print start_table({-border=>'0', -width=>'98%', -align=>'center', -cellpadding=>'4', -cellspacing=>'1'});
	  print start_TR({-align=>'left', -class=>'datatitle'});
	  print th({ -width=>'12%'},'Total Number of Annotations:');
	  print start_td();
	  print "<a href=\"$anno_url\">$total_objects ";	
	  print &is_plural($total_objects,'object');
	  print ",&nbsp; $total_association_count ";
	  print &is_plural($total_association_count,'association');
	  print "<br>";
	#  foreach my $obj_type ( 
	#  sort { $annotations{$a}->{'total_object_count'} <=>
	#	  $annotations{$b}->{'total_object_count'} 
	#      } keys %annotations){
	  foreach my $obj_type ( @ordered_object_types){
	    if(exists $annotations{$obj_type}){
	      print "<a href=\"#$obj_type\">$obj_type</a>";
	      print "(<a href=\"$anno_url&object_type=$obj_type\">";
	      print $annotations{$obj_type}->{'total_object_count'};
	      print '</a>)&nbsp;&nbsp;';
	    }
	}
	    print end_td();
	    print end_TR();

   
	 # foreach my $obj_type (
	 # sort { $annotations{$a}->{'total_object_count'} <=>
	#	  $annotations{$b}->{'total_object_count'} 
	 #     } keys %annotations){
	foreach my $obj_type ( @ordered_object_types){
	    if(exists $annotations{$obj_type}){
	      

	    print start_TR({-class=>'databody', -align=>'left'}); 

	    print th({-valign=>'top'},"<a name=\"$obj_type\"></a>&nbsp;&nbsp;$obj_type:");
	    my $anno_report_link = $annotations{$obj_type}->{'count_by_spe'};
	    my @anno_links = @$anno_report_link;
	    my $display_number = 5;
	    print start_td;
	    print start_table();
	    my $n=scalar(@anno_links);
	    my $row_n = ceil($n/$display_number);
	    for(my $i=0; $i<$n; $i++){
		if($i % $display_number == 0){
		    print end_tr unless $i==0;
		    print start_TR;
		}
		print td({-valign=>'top'},"$anno_links[$i]");
	    }
	    my $remain = $row_n*$display_number - $n;
	    for(my $j=0; $j<$remain; $j++){
		print td("&nbsp;");
	    }
	    print end_TR; 
	    print end_table;
	    print end_td;
	    print end_TR();
	    
	}
      }

	print end_table;


}


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

sub object_link {
  my($db,$term_id,$title) = @_;
  my $accession = $db->get_accession($term_id);

  #my $href = "$EXE_HOME$EXE_NAME?id=$accession";         #old

  my $href = EXE_HOME;
  $href.= EXE_NAME;
  $href.= "?id=$accession";
 
  return a({-href=>$href,-class=>'gopage'},$title);
}

# sort arrays by size, if they have same size, sort by elements
sub by_depth{
   my $depth_a = scalar(@$a);
   my $depth_b = scalar(@$b);

   if($depth_a == $depth_b ){
       my $i=0;
       while($i < $depth_a){
          if($a->[$i] == $b->[$i]){
              $i++;
          }else{
             return $a->[$i] <=> $b->[$i]
          }
       }
   }else{
      return  $depth_a <=> $depth_b;
   }
}

sub is_plural{
    my ($number,$string) = @_;

    if($string eq 'QTL' || $string eq 'Marker species'){
	$string = $string;  # QTL no plural
    }else{
	if( $number >1 ){
	    if($string =~/ry/){
		$string =~s/ry$/ries/;
	    }else{
		$string .= 's';
	    }
	}else{
	    $string = $string;
	}
    }

    return $string;

}

 

sub _get_xref_url{
    my ($xref_db_urls,$db_name,$val) = @_;

    my $url_link = '';
    if($val =~/^http\:\/\//){
	$url_link = $val;
	$url_link = "<a href=\"$url_link\">$val</a>";
    }elsif($xref_db_urls->{uc($db_name)}){
	$url_link = $xref_db_urls->{uc($db_name)}->{'url_syntax'};
	$url_link =~s/\Q[%?%]/$val/;	
	$url_link = "<a href=\"$url_link\">$val</a>";
    }else{
	$url_link = $val;
    }

    return $url_link;
}
