#####################################################################
#!/usr/bin/perl -w
# Programmer: Kuan Chang
# Date: 01/22/2002
# Version: 2.1
#####################################################################

use strict;
use DBI;
use CGI qw(:standard *table *TR *th *td *ul *ol);
use GramenePage;
use CSHL::Config;

#####################################################################
#constants

use constant HOME => '../../plant_ontology/index.html';
# use constant GO_PREFIX => 'GO:';
# use constant TO_PREFIX => 'TO:';
my $GO_PREFIX = 'GO:';
my $TO_PREFIX = 'TO:';
my $TAIR_PREFIX = 'PO:';

use constant TRAIT => 5;
use constant EXE_NAME => 'search_term';

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

#check which types of query
my $input = param('query');
# my ($final_accession, $is_TO) = extract_accessionID($input);
my ($final_accession, $term_type) = extract_accessionID($input);
$input =~ tr/A-Z/a-z/;
my $co_tag = "";                                                                 
my $co_tag = '<span class="matching">'.$input.'</span>';
# print redirect("$HOME") if (remove_spaces_on_both_sides($input) eq "");
print redirect(HOME) if (remove_spaces_on_both_sides($input) eq "");

# Connect to the database
my $dbh  = initialize_database();

my @candidates;
#if(is_digit($input) || $is_TO != -1){
#  if($is_TO == -1) {
if(is_digit($input) || $term_type != -1){
  if($term_type == -1) {
    @candidates = get_possible_matches_II($input);
  }
  else {
#    @candidates = get_possible_matches_III($final_accession, $is_TO);
    @candidates = get_possible_matches_III($final_accession, $term_type);
  }

} else {
  @candidates = get_possible_matches($input);
}

if($#candidates+1 == 1){
  terminate_database($dbh);
  my $only_you = get_accession($candidates[0]); 
 
  print redirect("./".EXE_NAME."?id=$only_you");
}

my $page = GramenePage->new(Apache->request);
my $cgi = new CGI;
print $cgi->header,
      $cgi->start_html(-title=>"Search for $input",
			 -style=>{'src'=>'/stylesheets/gramene.css'});
print header();
print $page->start_body;

#print_top("Search for $input");
print_search_area();
if($#candidates+1 == 0){
    print h1("Sorry! Cannot find any information about <i>$input</i>");
} else {
  print h1("Summary for <i>$input</i>");
  print_suspects(\@candidates, $input);
}
#print_bottom();
print $page->end_body;
terminate_database($dbh);

sub is_digit{
  my $query = shift;
  $query =~ s/^\s+//;
  $query =~ s/\s+$//;
  if ($query =~ /^\d+$/ ){
    return 1;
  }else{ 
    return 0;
  }
}

sub remove_spaces_on_both_sides{
  my $query = shift;
  $query =~ s/^\s+//;
  $query =~ s/\s+$//;
  return $query;
}

sub initialize_database {
  my $dbh =  DBI->connect(OntologyDataSource, OntologyDBUser, OntologyDBPassword,   
{
        'PrintError'  => 1, 
        'RaiseError'  => 1,
        'LongReadLen' => 3000,
        'LongTruncOk' => 1,
      }); 

  return $dbh;
}

sub get_possible_matches {
  my $pattern = shift;
  die "Invalid input in get_possible_matches" unless defined $pattern;
  my %seen;
  my $sth = $dbh->prepare("SELECT term_id FROM term WHERE lower(term_name) like '%$pattern%' UNION SELECT term_id FROM term_synonym WHERE lower(synonym_name) like '%$pattern%'") || die $dbh->errstr;
  $sth->execute || die "Execute: ", $sth->errstr;
  my $sth2 =  $dbh->prepare(" SELECT term_id FROM term_definition WHERE lower(definition) like '%$pattern%'") || die $dbh->errstr;
  $sth2->execute || die "Execute: ", $sth2->errstr;
  my @matches = ();
  while(my $row = $sth->fetchrow_array){
    $seen{$row}++;
    push @matches, $row;
  }
  $sth->finish;
  
  while(my $row = $sth2->fetchrow_array){
    if(!$seen{$row}){
      push @matches, $row;
    }
  }
  $sth2->finish;
  return @matches; 
}

sub get_possible_matches_II {
  my $id = shift;
  die "Invalid input in get_possible_matches_II" unless defined $id;
  my $sth = $dbh->prepare("SELECT term_id FROM term WHERE term_accession=$id") || die $dbh->errstr;
  $sth->execute || die "Execute: ", $sth->errstr;
  my @matches = ();
  while(my $row = $sth->fetchrow_array){
    push @matches, $row;
  }
  $sth->finish;
  
  return @matches; 
}

sub get_possible_matches_III {
  # my ($id, $is_TO) = @_;
  my ($id, $term_type) = @_;

  die "Invalid input in get_possible_matches_III" unless defined $id;
  #die "Invalid input in get_possible_matches_III" unless defined $is_TO;
  die "Invalid input in get_possible_matches_III" unless defined $term_type;
  my $sth;
  #if($is_TO) {
  if($term_type == 2) {
    $sth = $dbh->prepare("SELECT term_id FROM term WHERE term_accession=$id AND term_id >= 2000000") || die $dbh->errstr;
  }
  elsif($term_type == 1){
    $sth = $dbh->prepare("SELECT term_id FROM term WHERE term_accession=$id AND term_id > 1000000") || die $dbh->errstr;
  }
  else {
     $sth = $dbh->prepare("SELECT term_id FROM term WHERE term_accession=$id AND term_id < 1000000") || die $dbh->errstr;
  }

  $sth->execute || die "Execute: ", $sth->errstr;
  my @matches = ();
  while(my $row = $sth->fetchrow_array){
    push @matches, $row;
  }
  $sth->finish;
  
  return @matches; 
}


sub get_name {
  my $id = shift;
  die "Invalid input in get_name" unless defined $id;
  my $sth = $dbh->prepare("SELECT term_name FROM term WHERE term_id=$id")
    || die $dbh->errstr;
  $sth->execute || die "Execute: ", $sth->errstr;
  my $term_name = $sth->fetchrow_array;
  $sth->finish;
  return $term_name;
}

sub get_accession {
  my $id = shift;
  die "Invalid input in GetAccessionID" unless defined $id;
  my $sth = $dbh->prepare("SELECT term_accession FROM term WHERE term_id=$id") || die $dbh->errstr;
  $sth->execute || die "Execute: ", $sth->errstr;
  my $sth2 = $dbh->prepare("SELECT term_type FROM term WHERE term_id=$id") || die $dbh->errstr;
  $sth2->execute || die "Execute: ", $sth2->errstr;
  my $exact_accession;
#  if($sth2->fetchrow_array == $TRAIT) {
  if($sth2->fetchrow_array == TRAIT) {
    if($id >= 2000000) {
      $exact_accession = $TAIR_PREFIX; 
    }
    else{
     $exact_accession = $TO_PREFIX;
   }
  }
  else {
    $exact_accession = $GO_PREFIX;
  }
  my $accession = $sth->fetchrow_array;
  my $length = 7 - length($accession);
  for my $x (1 .. $length){
      $exact_accession .= "0";
  }
  $exact_accession .= $accession;
  $sth->finish;
  $sth2->finish;
  return $exact_accession;
}

sub print_suspects {
  my ($suspects_ref, $input) = @_;
  # my $pattern = shift;
  # my @suspects = get_possible_matches($pattern);
  my $ctag = '<span class="matching">'.$input.'</span>';

  print start_table({-border=>'1', -width=>'98%',-cellpadding=>0,-cellspacing=>0, -align=>'center'});
if($#$suspects_ref>0) {
  print TR({-class=>'datatitle', -align=>'center'}, 
	   th('Candidate Term'."    (".($#$suspects_ref+1)." terms found)"));
}
else {
  print TR({-class=>'datatitle', -align=>'center'}, 
	   th('Candidate Term'."    (".($#$suspects_ref+1)." term found)"));
}
  print end_TR, end_table;
  print start_table({-border=>'1', -width=>'98%',-cellpadding=>4,-cellspacing=>1, -align=>'center'});
  print TR({-align=>"center", -class=>"datatitle"},
	  th(['#', 'TO ID | GO ID', 'Term Name', 'Synonym', 'Definition']));

  # print start_TR({-class=>'searchbody'}), start_td;
  my $count = 0;
  foreach my $suspect (@$suspects_ref){
    if($count % 2 == 0) {
      print start_TR({-class=>'databody', -align=>'center'});
     } else {
      print start_TR({-align=>'center'}); 
     }
   # print td([a({-href=>"./$EXE_NAME?id=".get_GO_accession($suspect)}, get_GO_accession($suspect)), highlight_patterns(get_name($suspect)), p({-align=>'left'}, highlight_patterns(get_definition($suspect)) || 'No Definition Available')]);
    print td($count+1);
   # print td(a({-href=>"./$EXE_NAME?id=".get_accession($suspect)}, get_accession($suspect)));
    print td(a({-href=>"./".EXE_NAME."?id=".get_accession($suspect)}, get_accession($suspect)));
    my $yoyo = highlight_patterns2(get_name($suspect),$input);
    print td(p({-align=>'left'},$yoyo));
my $all_synonym = highlight_patterns2(get_synonym($suspect), $input);
    print td(p({-align=>'left'}, $all_synonym  || 'No Synonym Available'));		
    print td(  p({-align=>'left'}, highlight_patterns2(get_definition($suspect), $input) || 'No Definition Available'));

    print end_TR;
    $count += 1;
  }

 #print ul(li([map { a({-href=>"./$EXE_NAME?id=".get_GO_accession($_)}, get_name($_) . " (".get_GO_accession($_).")") } @suspects]));
  print end_td,end_TR,end_table;
}

sub highlight_patterns {
  my $text = shift;
  $text =~ s/$input/$co_tag/g;
  return $text;
}

sub highlight_patterns2{
  my ($text, $input) = @_;
  $text =~ s/($input)/<span class="matching">$1<\/span>/ig;
  return $text;  
}

sub get_synonym {
  my $id = shift;
  die "Invalid input in get_synonym" unless defined $id;
  my $sth = $dbh->prepare("SELECT synonym_name FROM term_synonym WHERE term_id=$id")
    || die $dbh->errstr;
  $sth->execute || die "Execute: ", $sth->errstr;
  # my $synonym = $sth->fetchrow_array;
  # my @reference_ids = ();
 my $synonym;	
  while(my $row = $sth->fetchrow_array){
    $synonym .= $row .", ";
  }
  
  if(defined $synonym){
     $synonym =~ s/, $/./;
  }
		
  $sth->finish;
  return $synonym;
}

sub get_definition {
  my $id = shift;
  die "Invalid input in GetDefinition" unless defined $id;
  my $sth = $dbh->prepare("SELECT definition FROM term_definition WHERE term_id=$id")
    || die $dbh->errstr;
  $sth->execute || die "Execute: ", $sth->errstr;
  my $term_definition = $sth->fetchrow_array;
  $sth->finish;
  return $term_definition;
}

sub print_search_area {
  my $self = url(-relative=>1);
  #print "<p align='center'><font size=-2>Type in ID or keyword to search for.</font>\n"; 
 # print table({-width=>'100%'},
 # TR({-class=>'searchtitle'},th("Search Gramene Ontology Database")));
  print start_form(-method=>'GET', -action=>"$self");
  print table({-width=>'100%', -align=>'center', -cellspacing=>1, -cellpadding=>0}, 
	'<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>' 
);
	  
#<td align=center><input type=text value="" framewidth=4 name=query size=55 maxlength=256><br><input name=btn type=submit value="GO Search"><input name=btn type=submit value="TO Search"></td
  print end_form();
 # print "<br>", "<hr>";
  print "<hr>";	
}

sub print_top {
  my $title = shift;

#Already done before here:
# print table( {-border=>'0',
#		-cellpadding=>'0',
#		-width=>'100%'},
#  TR(td( {-width=>'150', -valign=>'TOP'} ), 
#		  td( p( {-align=>'CENTER'}, a( {-href=>'/index.html'}, img( {-src=>'/gramene/images/icons/gramene_banner.gif',
#									      -alt=>'[Gramene Home]',
#									      -border=>'0'} ) ) ) ) ) );
 # print "<hr>";
 # print h1($title);
}

sub print_bottom {
  print "<hr>";
  print table({-width=>'100%'},
	      TR(td( {-align=>"left",  -class=>"small"}, a( { -href=>'mailto:gramene@brie.cshl.org'}, 'gramene@gramene.org')),
		 td( {-align=>"right", -class=>"small"}, "&copy;2001 Cold Spring Harbor Laboratory")));
}

sub terminate_database{
  $dbh->disconnect();
}

sub extract_accessionID{
  my $id = shift;
#  my $is_TO = -1;
  my $term_type = -1;

  if($id =~ /$TO_PREFIX/i) {
    $id =~ s/$TO_PREFIX//i;
#    $is_TO = 1;
    $term_type = 1;
  }
  elsif ($id =~ /$GO_PREFIX/i){
    $id =~ s/$GO_PREFIX//i; 
    # $is_TO = 0;
    $term_type = 0;
  }
  elsif($id =~ /$TAIR_PREFIX/i){
    $id =~ s/$TAIR_PREFIX//i; 
    $term_type = 2;   
  }
  else{
    # $is_TO = -1;
    $term_type = -1;
  }
 
  # return ($id, $is_TO);
  return ($id, $term_type);
}
