#!/usr/bin/perl
package sdevGoCurationPage;

#######################################################################
##### Author :	Shuai Weng
##### Date   :  August 2000
##### Description : This package contains all necessary methods for dictyBase
#####               curators to display, update, insert or delete Go 
#####               related info in oracle database. 
#####              
#######################################################################
use strict;
use DBI;
use CGI qw/:all :html3/;
use CGI::Carp qw(fatalsToBrowser);
use lib "/usr/local/dicty/www_dictybase/db/lib/common";
use Login qw (ConnectToDatabase);
use TextUtil qw(DeleteUnwantedChar);
use lib "/usr/local/dicty/www_dictybase/db/lib/dictyBase";
use dictyBaseCentralMod qw(:formatPage :getInfo);
use Pubmed;
use lib "/usr/local/dicty/www_dictybase/db/lib/dictyBase/Objects";
use ConfigURLdictyBase;
use ConfigPathdictyBase;
use Go_locus_goev;
use Go_feat_goev;
use External_id;
use Reflink;
use Reference;
use Feature;
use Locus;
use Go;

#######################################################################
#################### global variables #################################
#######################################################################

my $dbh;
my $dblink; 
my $configUrl;
my $configPath;

#######################################################################
sub new {      ############ constructor ###############################
#######################################################################
       
	my ($self, %args) = @_;

	$self = {};
	bless $self;

      	$self->{'_database'} = $args{'database'};
	$self->{'_help'}     = defined($args{'help'}) ? 
	                       $args{'help'} : "usingGO.html";
	$self->{'_title'}    = defined($args{'title'}) ? 
	                       $args{'title'} : "GO Curation Page";
	$self->{'_user'}     = defined($args{'user'}) ? $args{'user'} : "";
	$self->{'_feat'}     = defined($args{'feat'}) ? $args{'feat'} : "";
	$self->{'_type'}     = defined($args{'type'}) ? $args{'type'} : "";
	$dbh = &ConnectToDatabase($self->database);
    	return $self;
}

sub help { $_[0]->{_help} }
sub database { $_[0]->{_database} }
sub title { $_[0]->{_title} }
sub user { $_[0]->{_user} }

######################################################################
sub DESTROY {   ############ destructor ##############################
######################################################################
    	if (defined $dbh) {
		$dbh->disconnect;
    	}
}

######################################################################
sub start{
######################################################################

    	my ($self) = @_;
	$configUrl = ConfigURLdictyBase->new;	
	$dblink = $configUrl->dblink($self->database);
	$configPath = ConfigPathdictyBase->new;
	if (!$self->user) {
	    print "location: ", $configUrl->dictyBaseCGIRoot, "$dblink/curatorLogin\n";
	    print "Content-type: text/html\n\n";
	    exit;
	}

	my ($dbuser, $dbpasswd) = &getUsernamePassword(uc($self->user), 
						       $self->database);
	
       
	if (!$dbuser || !$dbpasswd) {
	    print "location: ", $configUrl->dictyBaseCGIRoot, "$dblink/curatorLogin\n";
	    print "Content-type: text/html\n\n";
	    exit;
	}
	$self->{'_feat'} =~ s/^ *//;
	$self->{'_feat'} =~ s/ *$//;
	$self->{'_feat'} =~ s/[\t\r\f\n]+//g;
	if (param('goid')) {
	    $self->displaySharedAnnotation;
	}
	elsif (param('commit')) {
	    $dbh->disconnect;
	    $dbh = &ConnectToDatabase($self->database, $dbuser, $dbpasswd);
	    # $self->getEvidenceCode;
	    $self->commitInfo;
	}
	elsif (param('type')) {
	    if (!param('morerows')) {
		$self->checkQuery;
	        $self->displayRowsFromDB;
	    }
	    else {
		$self->displayMoreRows;
	    }
	}
        else {
	    $self->printEntryForm;
        }
}

#######################################################################
sub printEntryForm {
#######################################################################
        my ($self) = shift;

	&printStartPage($self->database, $self->title, $self->help);

	my %typeLabels = ('Locus'=>'Locus or locus_no',
			  'Feature'=>'Feature or feature_no');
	my @typeValues = qw/Locus Feature/;
	my $defaultType = 'Locus';

        ##########################
	print 
	table(Tr(td(
		    startform,
		    b("This form is for dictyBase curators to display, update, insert or delete GO related info in oracle database"),p,
		    b(font({-size=>"+1"}, 'Enter ')),
		    popup_menu(-name=>'type',
			       -"values"=>\@typeValues,
			       -default=>$defaultType,
			       -labels=>\%typeLabels
			       ), b(": "),      
		    textfield(-name=>'feat', -size=>30),
		    p,
		    hidden('user', "$self->user"),   
		    submit('Submit','Submit'), " ",
		    reset,

		    endform)));
	&printEndPage;
}

#######################################################################
sub displaySharedAnnotation {
#######################################################################
    my ($self) = shift;
    my $title = "Annotation for Locus and Feature";
    &printStartPage($self->database, $title, $self->help);
    my $go = Go->new(dbh=>$dbh,
		     goid=>param('goid'));
    my $locusArrayRef = $go->getLocusArrayRef;
    my $featArrayRef = $go->getFeatureArrayRef;

    print center(h2("goid = ".param('goid'))).p;
    ##############
    my $liList;
    foreach my $rowRef (@$locusArrayRef) {
	my ($locusNo, $locusNm) = @$rowRef;
	$liList .= li(a({-href=>$configUrl->dictyBaseCGIRoot."$dblink/locus.pl?locusNo=$locusNo", 
			 -target=>'anotherWin'},
			$locusNm)." (locus_no = ".
		      a({-href=>url."?user=".$self->user."&type=locus&feat=$locusNm", 
			-target=>'anotherWin'},
		      $locusNo).")");
	

    }
    foreach my $rowRef (@$featArrayRef) {
	my ($featNo, $featNm) = @$rowRef;
	$liList .= li(a({-href=>$configUrl->dictyBaseCGIRoot."$dblink/locus.pl?featureNo=$featNo",
			-target=>'anotherWin'}, 
		      $featNm)." ( feature_no = ".
		      a({-href=>url."?user=".$self->user."&type=feature&feat=$featNm",
			 -target=>'anotherWin'},
			$featNo).")");
    }
    print ul($liList);
    print 
          "<div align=center>\n",
          "<form>\n",
          "<input type=button value=\"    Close    \" onClick=\"self.close()\">\n",
          "</form>";
    print end_html;
    
}

########################################################################
sub displayRowsFromDB {
########################################################################
    my ($self) = shift;
    my ($title, $subtitle, $No, $tabNm);
    if ($self->{'_featNm'} && $self->{'_locusNm'}) {
	$title = $self->title." for ".$self->{'_featNm'}."/".$self->{'_locusNm'};
	$subtitle = $self->{'_featNm'}."/".$self->{'_locusNm'};
    }
    elsif ($self->{'_featNm'}) {
	$title = $self->title." for ".$self->{'_featNm'};
        $subtitle = $self->{'_featNm'};
    }
    elsif ($self->{'_locusNm'}) {
	$title = $self->title." for ".$self->{'_locusNm'};
	$subtitle = $self->{'_locusNm'};
    }
    &printStartPage($self->database, $title, $self->help);
    if (!$self->{'_locusNm'}) {
	$self->printSubtitle($subtitle, $self->{'_featNm'}, 
			     "(feature_no=$self->{'_featNo'})");
	$No = $self->{'_featNo'};
	$tabNm = "GO_FEAT_GOEV";
    }
    else {
	$self->printSubtitle($subtitle, $self->{'_locusNm'}, 
			     "(locus_no=$self->{'_locusNo'})");
	$No = $self->{'_locusNo'};
	$tabNm = "GO_LOCUS_GOEV";
    }
    print startform;
    print "<table border=1 cellpadding=1 cellspacing=1>";
    my $goidArrayRef;
    if (!$self->{'_locusNm'}) {
	my $featObj = Feature->new(dbh=>$dbh,
				   feature_no=>$self->{'_featNo'});
	$goidArrayRef = $featObj->goidArrayRef;
    }
    else {
	my $locusObj = Locus->new(dbh=>$dbh,
				  locus_no=>$self->{'_locusNo'});
	$goidArrayRef = $locusObj->goidArrayRef;
    }
    my $i = 0;   
    my %FOUNDannotation;
    my $count;
    foreach my $rowRef (@$goidArrayRef) {
	my ($goid) = @$rowRef;
	$count++;
	if ($count == 1) {
	    $self->printHeaderRow4existingInfo;
	}
	my $go = Go->new(dbh=>$dbh,
			 goid=>$goid);
	my $goAspect = $go->go_aspect;
	my $goTerm = $go->go_term;
	
	my $paperEtcRef;
	#### assume each paper has a unique IS_NOT value
	#### following query will return paper::is_not array ref
	if ($self->{'_locusNm'}) {
	    $paperEtcRef = Go->GetReferenceInfoNew(
					 dbh=>$dbh,
					 goid=>$goid,
					 type=>'LOCUS',
					 No=>$self->{'_locusNo'});
	}
	else {
	    $paperEtcRef = Go->GetReferenceInfoNew(
					 dbh=>$dbh,
					 goid=>$goid,
					 type=>'FEATURE',
					 No=>$self->{'_featNo'});
	}

	foreach my $paperRowRef (@$paperEtcRef) {
		my ($refNo, $paper, $goevNo, $goevCode, $isNot, $dateCreated, 
		    $externalIdNo, $externalId, $source) = @$paperRowRef;
		$i++;
		$paper = $paper." (refNo=$refNo)";
		my $shared = "no";
		foreach my $rowRef (@{$go->getLocusArrayRef}) {
		    my ($locus_no, $locus_name) = @$rowRef;
		    if ($locus_no != $self->{'_locusNo'}) {
			$shared = "yes";
			last;
		    }
		}
		if ($shared == "no") {
		    foreach my $rowRef (@{$go->getFeatureArrayRef}) {
			my ($feature_no, $feature_name) = @$rowRef;
			if ($feature_no != $self->{'_featNo'}) {
			    $shared = "yes";
			    last;
			}
		    }
		}
		my $deleteAnnot = "";
		$goAspect =~ s/^P$/Process/;
		$goAspect =~ s/^F$/Function/;
		$goAspect =~ s/^C$/Component/;
		print hidden("ontologyDB$i", "$goAspect"),
		      hidden("goidDB$i", "$goid"),
		      hidden("goTermDB$i", "$goTerm"),
		      hidden("isNotDB$i", "$isNot"),
		      hidden("referenceDB$i", "$paper"),
		      hidden("refNoDB$i", "$refNo"),
		      hidden("goEvNoDB$i", "$goevNo"),
		      hidden("goEvCodeDB$i", "$goevCode"),
		      hidden("externalIdNoDB$i", "$externalIdNo"),
		      hidden("externalIdDB$i", "$externalId"),
		      hidden("sourceDB$i", "$source"),
		      hidden("sharedDB$i", "$shared");
		my $displayGoTerm = $goTerm;
		if ($isNot =~ /Y/i) { 
		    $displayGoTerm = b(font({color=>'red'},"NOT ")).$goTerm; 
		}
		$self->printOneRow4existingInfo($i, $goAspect, $goid, 
						$displayGoTerm,
						$paper, $goevCode,
					        $externalId, $source, 
						$deleteAnnot, $shared);
	}
    }
    
    print "</table>";
    print "<p><table>";
    $self->printNewEntryTitle;
    $self->printMoreRows(1);
    print "</table>";    
    $self->printEndForm($self->{'_featNm'}, $self->{'_featNo'},
			$self->{'_locusNm'}, $self->{'_locusNo'});
    &printEndPage;
}


########################################################################
sub displayMoreRows {
########################################################################
    my ($self) = shift;
    my ($title, $featNm, $featNo, $locusNm, $locusNo, $subtitle);
    $locusNm = param('locusNm');
    $locusNo = param('locusNo');
    $featNm = param('featNm');
    $featNo = param('featNo');
    if ($featNm && $locusNm) {
	$title = $self->title." for ".$featNm."/".$locusNm;
	$subtitle = $featNm."/".$locusNm;
    }
    elsif ($featNm) {
	$title = $self->title." for ".$featNm;
        $subtitle = $featNm;
    }
    elsif ($locusNm) {
	$title = $self->title." for ".$locusNm;
	$subtitle = $locusNm;
    }
    &printStartPage($self->database, $title, $self->help);
    if (!$locusNm) {
	$self->printSubtitle($subtitle, $featNm, "(feature_no=$featNo)");
    }
    else {
	$self->printSubtitle($subtitle, $locusNm, "(locus_no=$locusNo)");
    }
    
    print startform;
    print "<table border=1 cellpadding=1 cellspacing=1>";
    my $i;
    for ($i = 1; $i <= 1000; $i++) {
	if ($i == 1 && param("ontologyDB$i")) { 
	    $self->printHeaderRow4existingInfo;
	}
	if (!param("ontologyDB$i")) { last; }
	my $goTerm = param("goTermDB$i");
	my $deleteAnnot = param("deleteAnnot$i");
	print hidden("ontologyDB$i", param("ontologyDB$i")),
	      hidden("goidDB$i", param("goidDB$i")),
	      hidden("goTermDB$i", param("goTermDB$i")),
	      hidden("isNotDB$i", param("isNotDB$i")),
	      hidden("referenceDB$i", param("referenceDB$i")),
	      hidden("refNoDB$i", param("refNoDB$i")),
	      hidden("goEvCodeDB$i", param("goEvCodeDB$i")),
	      hidden("goEvNoDB$i", param("goEvNoDB$i")),
	      hidden("externalIdNoDB$i", param("externalIdNoDB$i")),
              hidden("externalIdDB$i", param("externalIdDB$i")),
	      hidden("sourceDB$i", param("sourceDB$i")),
              hidden("sharedDB$i", param("sharedDB$i"));
	if (param("isNotDB$i") =~ /y/i) { 
	    $goTerm = b(font({color=>'red'},"NOT ")).$goTerm; 
	}
 	$self->printOneRow4existingInfo($i, 
					param("ontologyDB$i"), 
					param("goidDB$i"), 
					$goTerm,
 					param("referenceDB$i"), 
					param("goEvCodeDB$i"),
					param("externalIdDB$i"),
					param("sourceDB$i"),
 					$deleteAnnot, 
					param("sharedDB$i")
				   );
   
    }
    print "</table><p>";
    print "<table>";
    $self->printNewEntryTitle;
    print $self->headerRow;
    for ($i = 1; $i <= 1000; $i++) {
	my $goAspect = param("ontology$i");
	if (!$goAspect) { last; }
	my $goid = param("goid$i");
	$goid =~ s/^0+//;
	$goid =~ s/[\r\f\n\t ]*//g;	
	if (!$goid) { last;}
	my $go = Go->new(dbh=>$dbh,
			 goid=>$goid);
	my $goTerm = $go->go_term;
	my @goevCode = param("goEvCode$i");
	  	
	my @goevCode4withFrom = param("goEvCode4withFrom$i");

	$self->printOneRow($i, $goAspect, $goid, $goTerm, 
			   param("refNo$i"), 
			   param("pubmed$i"), 
			   \@goevCode,
			   param("isNot$i"), 
			   param("locuslist$i"), 
			   param("featlist$i"),
			   param("source$i"),
			   param("ID$i"),
			   param("ICgoid$i"),
			   \@goevCode4withFrom);
	
    }
    $self->printMoreRows($i);

    print "</table>";
       
    $self->printEndForm(param('featNm'), 
			param('featNo'),
			param('locusNm'),
			param('locusNo'),
			param('rowNo'));
    &printEndPage;
}

########################################################################
sub commitInfo {
########################################################################
    my ($self) = shift;
    my ($title, $type, $locusORfeatNo);
    if (param('locusNm') && param('featNm')) {
	$title = $self->title." for ".param('featNm')."/".param('locusNm');
	$locusORfeatNo = param('locusNo');
	$type = "locus";
    }
    elsif (param('featNm')) {
	$title = $self->title." for ".param('featNm');
	$locusORfeatNo = param('featNo');
	$type = "feature";
    }
    elsif (param('locusNm')){
	$title = $self->title." for ".param('locusNm');
	$locusORfeatNo = param('locusNo');
	$type = "locus";
    }
    &printStartPage($self->database, $title, $self->help);
    ######################
    
    my %goEvidenceNo;
    Go->GetGoEvidenceInfo(dbh=>$dbh,
			  goEvidenceNoRef=>\%goEvidenceNo);
    for (my $i = 1; $i <= 100; $i++) {
	my $goid = param("goidDB$i");
	if (!$goid) { last;}
	if (param("deleteAnnot$i") =~ /on/i) {
	    my $refNo = param("refNoDB$i");
	    my $externalIdNo = param("externalIdNoDB$i");
	    my $goevNo = param("goEvNoDB$i");
	    Go->DeleteAnnotationNew(dbh=>$dbh,
				    reference_no=>$refNo,
				    goid=>$goid,
				    No=>$locusORfeatNo,
				    type=>$type,
				    evidence_code_no=>$goevNo,
				    external_id_no=>$externalIdNo);
	    print font({-color=>'red'},b("The annotation for goid='$goid', ${type}_no='$locusORfeatNo', reference_no='$refNo', evidence_code_no='$goevNo', and external_id_no='$externalIdNo' has been deleted from database.")).p;  
	}
    }

    ###### new entries:

    for (my $i = 1; $i <= 100; $i++) {
	my $update = 0;
	my $goid = param("goid$i");
	$goid =~ s/^0+//;
	&DeleteUnwantedChar(\$goid);
	if ( !$goid) { last; }
	my $refNo = param("refNo$i");
	$refNo =~ s/^0+//;
	&DeleteUnwantedChar(\$refNo);
	my $pubmed = param("pubmed$i");
	$pubmed =~ s/^0+//;
	&DeleteUnwantedChar(\$pubmed);
	if (!$refNo && !$pubmed) { 
	    next;
	}
	if (!$refNo && $pubmed) {
	    my $refObject = Pubmed->new(dbh=>$dbh,
	     				pubmed=>$pubmed);
	    $refNo = $refObject->referenceNo;
	    if (!$refNo) {
		print "The pubmed=$pubmed is not found in database or can't create medline paper for it from NCBI.", p;
		next;
	    }
        }
	else {
	    my $refObj = Reference->new(dbh=>$dbh,
					reference_no=>$refNo);
	    if (!$refObj) {
		print "The reference_no=$refNo is not found in database.", p;
		exit;
	    }

	}
	my $isNot = param("isNot$i");
	if ($isNot) { $isNot = 'Y'; }
	else { $isNot = 'N'; }
	my $go = Go->new(dbh=>$dbh,
			 goid=>$goid);
	if (!$go) {
	    print font({-color=>'red'},b("The goid you entered ($goid) is not found in GO table. This entry can not be committed into database.")).p; 
	    next;
	}
	my $goAspect = param("ontology$i");
	if ($goAspect =~ /ontology/i || !$goAspect) {
	    print "<p>You have to select ontology before press the Submit button. Please go back, make all necessary selection and try again.<p>";
	    exit;
	}
	my @goevCode = param("goEvCode$i");
	if (!@goevCode) {
	    print "<p>You have to select the go_evidence_code before press the Submit Button. Please go back, make any necessary selection and try again.<p>";
            exit;
        }
	my $goevCodeList = join(":", @goevCode);
	if ($goevCodeList =~ /IC/i && !param("ICgoid$i")) {
	    print p("You have to enter 'IC from GOid' if you select 'IC' evidence code. Please go back, make any necessary change and try again."), p;
	    exit;
	}
	my @goevCode4withFrom = param("goEvCode4withFrom$i");
	my %foundGoEv;
	foreach my $goevCode (@goevCode) {
	    $foundGoEv{$goevCode}++;
	}
	my %isWithFrom;
	foreach my $goevCode (@goevCode4withFrom) {
	    if (!$foundGoEv{$goevCode}) {
		push(@goevCode, $goevCode);
	    }
	    $isWithFrom{$goevCode}++;
	}
	my $source = param("DB$i");
	my $ID = param("ID$i");
	&DeleteUnwantedChar(\$ID);
	my $ICgoid = param("ICgoid$i");
	&DeleteUnwantedChar(\$ICgoid);
	$ICgoid =~ s/^GO:0*//;
	$ICgoid =~ s/^0+//;
	my $goAspectDB = $go->go_aspect;
	my $goTermDB = $go->go_term;
	if ($goAspect ne $goAspectDB) {
	    $goAspectDB =~ s/C/Cellular Component/;
	    $goAspectDB =~ s/F/Function/;
	    $goAspectDB =~ s/P/Process/;
	    $goAspect =~ s/C/Cellular Component/;
	    $goAspect =~ s/F/Function/;
	    $goAspect =~ s/P/Process/;
	    print "The GOID $goid is associated with the go_term '$goTermDB' in the $goAspectDB ontology, not the $goAspect ontology. Please go back and make a correction.<p>";
	    exit;
	}
	
	my $locuslist = param("locuslist$i");
	my $featlist = param("featlist$i");
	&DeleteUnwantedChar(\$locuslist);
	&DeleteUnwantedChar(\$featlist);
	my @loci = split(/\|/, $locuslist);
	my @feats = split(/\|/, $featlist);
	my $featNum = 0;
	foreach my $feat (1, @loci, @feats) { 
            ### 1 -- for current locus or feature name
	    $featNum++;
	    my $THISlocusORfeatNo = $locusORfeatNo;
	    my $THIStype = $type;
	    if ($featNum > 1) {
		if ($featNum <= @loci + 1) { ### it is locus in the locuslist
		    my $locus = Locus->new(dbh=>$dbh,
					   locus_name=>$feat);
		    if (!$locus) {
			print "The locus ($feat) is not in locus table in database.", p;
			next;
		    }
		    $THISlocusORfeatNo = $locus->locus_no;
		    $THIStype = "locus";
		}
		else {  ### it is feature in the featlist
		    my $feature = Feature->new(dbh=>$dbh,
					       feature_name=>$feat);
		    if (!$feature) {
			print "The feature ($feat) is not in feature table in database.", p;
			next;
		    }
		    $THISlocusORfeatNo = $feature->feature_no;
		    $THIStype = "feature"
		}    
	    }
	    
	    foreach my $goevCode (@goevCode) {

	        my $goevNo = $goEvidenceNo{$goevCode};
	        my ($tabNm, $prikeyCol);
	        if ($THIStype =~ /locus/i) {
		    my $goLocusGoev = Go_locus_goev->new(
					      dbh=>$dbh,
					      goid=>$goid,
					      locus_no=>$THISlocusORfeatNo,
					      go_evidence_no=>$goevNo,
					      is_not=>$isNot);
							 
                    if (!$goLocusGoev) { ## is not in db. Insert it
			eval {
			    Go_locus_goev->Insert(dbh=>$dbh,
					     binds=>{goid=>$goid,
						     locus_no=>$THISlocusORfeatNo,
						     go_evidence_no=>$goevNo,
						     is_not=>$isNot});
			};
			if ($@) {
			    print "An error occurred when inserting Go_Locus_Goev entry into database.$@", br;
			    $dbh->rollback;
			}
			else {
			    $dbh->commit;
			    print "The Go_Locus_Goev entry for goid='$goid', locus_no='$THISlocusORfeatNo' and goevNo='$goevNo' has been inserted into database.", p;
			}
		    }
		    else {
			print "The Go_Locus_Goev entry for goid='$goid', locus_no='$THISlocusORfeatNo' and goevNo='$goevNo' is already in database.", p;
		    }
		    $tabNm = "GO_LOCUS_GOEV";
		    $prikeyCol = "GOID::LOCUS_NO::GO_EVIDENCE_NO::IS_NOT";
	        }
	        else {
		    my $goFeatGoev = Go_feat_goev->new(
					      dbh=>$dbh,
					      goid=>$goid,
					      feature_no=>$THISlocusORfeatNo,
					      go_evidence_no=>$goevNo,
					      is_not=>$isNot);
							 
                    if (!$goFeatGoev) { ## is not in db. Insert it
			eval {
			    Go_feat_goev->Insert(dbh=>$dbh,
					      binds=>{goid=>$goid,
						      feature_no=>$THISlocusORfeatNo,
						      go_evidence_no=>$goevNo,
						      is_not=>$isNot});
			};
			if ($@) {
			    print "An error occurred when inserting Go_Feat_Goev entry into database.$@", br;
			    $dbh->rollback;
			}
			else {
			    $dbh->commit;
			    print "The Go_Feat_Goev entry for goid='$goid', feature_no='$THISlocusORfeatNo' and goevNo='$goevNo' has been inserted into database.", p;
			}
		    }
		    else {
			print "The Go_Feat_Goev entry for goid='$goid', feature_no='$THISlocusORfeatNo' and goevNo='$goevNo' is already in database.", p;
		    }
		    $tabNm = "GO_FEAT_GOEV";
		    $prikeyCol = "GOID::FEATURE_NO::GO_EVIDENCE_NO::IS_NOT";
	        }
	        my $prikey = $goid."::".$THISlocusORfeatNo."::".$goevNo."::".$isNot;

		my $reflinkObj = Reflink->new(dbh=>$dbh,
						  reference_no=>$refNo,
						  tab_name=>$tabNm,
						  primary_key=>$prikey,
						  primary_key_col=>$prikeyCol);
		
		if (!$reflinkObj) {

		    eval {
			Reflink->Insert(dbh=>$dbh,
				    literals=>{reflink_no=>'CGM_DDB.reflinkno_seq.nextval'},
				    binds=>{reference_no=>$refNo,
					    tab_name=>$tabNm,
					    primary_key=>$prikey,
					    primary_key_col=>$prikeyCol}
				    );
		    };
		    if ($@) {
			print "An error occurred when inserting reference_no='$refNo', tab_name='$tabNm', primary_key_col='$prikeyCol', and primary_key='$prikey' into reflink table. see following error msg.<br>$@", p;
			$dbh->rollback;
		    }
		    else {
			print "The reflink info for reference_no='$refNo', tab_name='$tabNm', primary_key_col='$prikeyCol', and primary_key='$prikey' has been inserted into database.", p;

			$reflinkObj = Reflink->new(dbh=>$dbh,
						  reference_no=>$refNo,
						  tab_name=>$tabNm,
						  primary_key=>$prikey,
						  primary_key_col=>$prikeyCol);
		    
		    }
		}
		else {

		    print "The reflink entry for reference_no='$refNo', tab_name='$tabNm', primary_key_col='$prikeyCol', and primary_key='$prikey' is already in database.",p;

		}

		if (!$reflinkObj) { next; }

		if (($isWithFrom{$goevCode} && $source && $ID) ||
			($goevCode eq "IC" && $ICgoid)) { 
			
			my $prikey = $reflinkObj->reflink_no;
	    
			my $tabNm = "REFLINK";

			my $thisSource = $source;

			my $thisID = $ID;

			if ($goevCode eq "IC" && $ICgoid) {
			    $thisSource = 'GO';
			    $thisID = $ICgoid;
			}

			my @ID = split(/\|/, $thisID);
		    
			foreach my $thisID (@ID) {
			    &DeleteUnwantedChar(\$thisID);
			    eval {
				External_id->Insert(dbh=>$dbh,
					     literals=>{external_id_no=>'CGM_DDB.extidno_seq.nextval'},
					     binds=>{external_id=>$thisID,
						source=>$thisSource,
						tab_name=>$tabNm,
						primary_key=>$prikey});

			    };
			    if ($@) {
				print "An error occurred when inserting external_id='$thisID', source='$thisSource', tab_name='$tabNm', and primary_key='$prikey' into external_id table. See following error msg. :$@:", p;
				$dbh->rollback;
			    }
			    else {
				print "The external_id entry for external_id='$thisID', source='$thisSource', tab_name='$tabNm', and primary_key='$prikey' has been inserted into database.",p;
			    }
			}
		    
			$update++;
		}
	    }
        }
	   
    }

    ##################
    if (param('locusNm')) {
	print p, b("View locus ".a({-href=>$configUrl->dictyBaseCGIRoot."gene_page.pl?gene_name=".param('locusNm'),
				    -target=>'infowin'}, param('locusNm')));
    }
    elsif (param('featNm')) {
	print p, b("View feature ".a({-href=>$configUrl->dictyBaseCGIRoot."$dblink/locus.pl?featureName=".param('featNm'),-target=>'infowin'}, param('featNm')));
    } 
    print p, b("Return to ".a({-href=>$configUrl->dictyBaseCGIRoot."$dblink/curatorLogin?user=".$self->user}, "dictyBase Curator Central")), br;
    ##################

    ##################
    &printEndPage;
    ##################
}

########################################################################
sub checkQuery {
########################################################################
    my ($self) = shift;
    if (!$self->{'_feat'}) {
	$self->err_report("You have to enter locus or feature name or number before press the Submit button. Please go back and try again.");           
    }
    if ($self->{'_type'} =~ /Feature/i) {
	my $feature;
	if ($self->{'_feat'} =~ /^[0-9]+$/) {
	    $self->{'_featNo'} = $self->{'_feat'};
	    $feature = Feature->new(dbh=>$dbh,
				       feature_no=>$self->{'_featNo'});
	    if (!$feature) {
		$self->err_report("The feature_no you entered ($self->{'_featNo'}) is not found in database. Please go back, change the input and try again."); 
		exit;
	    }
	    $self->{'_featNm'} = $feature->feature_name;
	}
	else {
	    $self->{'_featNm'} = "\U$self->{'_feat'}";
	    $feature = Feature->new(dbh=>$dbh,
				       feature_name=>$self->{'_featNm'});
	    if (!$feature) {
		$self->err_report("The feature_name you entered ($self->{'_featNm'}) is not found in database. Please go back, change the input and try again."); 
		exit;
	    }
	    $self->{'_featNo'} = $feature->feature_no;
	}
	$self->{'_locusNm'} = $feature->locus_name;
	$self->{'_locusNo'} = $feature->locus_no;
    }
    else {
	my $locus;
	if ($self->{'_feat'} =~ /^[0-9]+$/) {
	    $self->{'_locusNo'} = $self->{'_feat'};
	    $locus = Locus->new(dbh=>$dbh,
				locus_no=>$self->{'_locusNo'});
	    if (!$locus) {
		$self->err_report("The locus_no you entered ($self->{'_locusNo'}) is not found in database. Please go back, change the input and try again.");               
	    }
	    $self->{'_locusNm'} = $locus->locus_name;
	}
	else {
	    $self->{'_locusNm'} = "\U$self->{'_feat'}";
	    $locus = Locus->new(dbh=>$dbh,
				locus_name=>$self->{'_locusNm'});
	    if (!$locus) {
		$self->err_report("The locus_name you entered ($self->{'_locusNm'}) is not found in database. Please go back, change the input and try again.");               
	    }
	    $self->{'_locusNo'} = $locus->locus_no;
	}
	$self->{'_featNm'} = $locus->featureNameList;
	if ($self->{'_featNm'} && $self->{'_featNm'} !~ /\|/) {
	    my $feature = Feature->new(dbh=>$dbh,
				       feature_name=>$self->{'_featNm'});
	    $self->{'_featNo'} = $feature->feature_no;
	}
    }
}

########################################################################
sub printSubtitle {
########################################################################
    my ($self, $subtitle, $feature, $text) = @_;
    print center(h2(a({-href=>$configUrl->dictyBaseCGIRoot."gene_page.pl?gene_name=$feature",
		       -target=>"infowin"},
		      $subtitle).$text 
	             ));
    print center(a({-href=>$configUrl->dictyBaseServerRoot."GO/main.html",
		    -target=>"infowin"}, 
		    "Open GO BROWSER")
		 );
}

########################################################################
sub printNewEntryTitle {
########################################################################
    print "<tr><td colspan=5 align=center BGCOLOR='#a4abc2'><b>Enter New Annotations</b></td></tr>";
}

########################################################################
sub printEndForm {
########################################################################
    my ($self, $featNm, $featNo, $locusNm, $locusNo) = @_;
    print
	hidden('user', "$self->user"),
	hidden('type', "$self->{'_type'}"),
	hidden('featNm', "$featNm"),
	hidden('featNo', "$featNo"), 
	hidden('locusNm', "$locusNm"),
	hidden('locusNo', "$locusNo"),
	submit('morerows','More Rows'), " ",
	submit('commit','Submit'), " ",
	endform;
}


########################################################################
sub headerRow {
########################################################################
    return Tr(td({-align=>'center'},
			b(font({-size=>'-1'},
			       "Choose Ontology"))).
	      td({-align=>'center'},
			b(font({-size=>'-1'},
			       "Enter GO ID number"))).
	      td({-align=>'center'},
			font({-size=>'-1'},
			      b("Enter reference_no OR pubmed id").br.i("(if more than one, enter in another row)"))).
	      td({-align=>'center'},
			b(font({-size=>'-1'},
			       "Choose Evidence code"))).
       	      td({-align=>'center'},
			font({-size=>'-1'},
			      b("Enter With OR From Association").br.i("(if more than one DB:ID, enter in another row)")))
	   );
		      
}

########################################################################
sub ontologyField {
########################################################################
    my ($self, $i, $ontology) = @_;
    my %ontologyLabels = ('ontology'=>'-Ontology-',
			  'P'=>'Process',
			  'F'=>'Function',
			  'C'=>'Component');
    my @ontologyValues = qw/ontology P F C/;
    
    my $defaultOntology = "$ontology";

    return popup_menu(-name=>"ontology$i",
                   -"values"=>\@ontologyValues,
                   -default=>$defaultOntology,
                   -labels=>\%ontologyLabels
                  );      
}

########################################################################
sub goidField {
########################################################################
    my ($self, $i, $goid, $goTerm, $isNot) = @_;
    return table(Tr(td({-align=>'left'},
		       b(font({-size=>'-1'},
			      "GO#:"))).
		    td({-align=>'left'},
		       textfield(-name=>"goid$i",
				 -value=>"$goid",
				 -size=>'7').br.
		       checkbox(-name=>"isNot$i",
				-label=>' NOT'))
		 ));
    
}

########################################################################
sub goReferenceField {
########################################################################
    my ($self, $i, $refNo, $pubmed) = @_;
    return table(Tr(td({-align=>'right'},
		       b(font({-size=>'-1'},
			      "Reference_No:"))).
		    td({-align=>'left'},
		       textfield(-name=>"refNo$i",
				 -value=>"$refNo",
				 -size=>'12'))
		 ).
		 Tr(td({-align=>'right'},
		       b(font({-size=>'-1'},
			      "Pubmed:"))).
		    td({-align=>'left'},
		       textfield(-name=>"pubmed$i",
				 -value=>"$pubmed",
				 -size=>'12'))
		 )
	   );

}

########################################################################
sub goEvidenceField {
########################################################################
    my ($self, $i, $goevRef) = @_;

    # my @goevValues = qw/IMP IGI IPI ISS IDA IEP TAS NAS ND/;
    my @goevValues;
    my $arrayRef = Go->GetGoEvidenceCodeArrayRef(dbh=>$dbh);
    foreach my $rowRef (@$arrayRef) {
	my ($code) = @$rowRef;
	if ($code eq "NR") {
	    next;
	}
	push(@goevValues, $code);
    }
 
    return table(Tr(td(checkbox_group(-name=>"goEvCode$i",
				      -"values"=>\@goevValues,
				      -default=>\@$goevRef,
				      -rows=>'4')
		       )
		  ));

}

########################################################################
sub goWithFromField {
########################################################################
    my ($self, $i, $defaultSource, $ID, $ICgoid, $goevRef4withFrom) = @_;

    my $DBcodeFile = $configPath->dataDir."dictyBase_GO_DB_code_mapping";

    open(IN, "$DBcodeFile") ||
	die "Can't open '$DBcodeFile' for reading:$!\n";

    my %isDBcode;
    while(<IN>) {
	my ($dbCode, $goCode) = split(/\t/);
	$isDBcode{$dbCode}++;
    }
    close(IN);
    
    my @sourceValues;
    my $arrayRef = External_id->GetUniqueSource(dbh=>$dbh);
    foreach my $rowRef (@$arrayRef) {
	my ($source) = @$rowRef;
	if ($isDBcode{$source}) {
	    push(@sourceValues, $source);
	    delete $isDBcode{$source};
	}
    }

    foreach my $code (keys %isDBcode) {
	print font({-color=>'red'}, "Warning: The code '$code' is not found in database."), br; 
    }
 
    return table(Tr(td(checkbox_group(-name=>"goEvCode4withFrom$i",
				      -values=>['IGI', 'IPI', 'ISS'],
				      -default=>\@$goevRef4withFrom).b(" with:"))
		 ).
		 Tr(td(b("DB:").
		       popup_menu(-name=>"DB$i",
				  -values=>\@sourceValues,
				  -default=>$defaultSource))    
		 ).
		 Tr(td({-align=>'left'},
		       b("ID:").
		       textfield(-name=>"ID$i",
				 -value=>"$ID",
				 -size=>'12').br."separate multiples by |")
		 ).
		 Tr(td(a({-href=>$configUrl->dictyBaseHelp.'GOdbxrefs.html'}, "List of DB:ID's"))).
		 Tr(td(b(font({-size=>'+1'}, "---- OR ----")))).
		 Tr(td({-align=>'left'},
		       b("IC from GOid:").
		       textfield(-name=>"ICgoid$i",
				 -value=>"$ICgoid",
				 -size=>'12').br."separate multiples by |")
		 )
	   );

}

########################################################################
sub locusList4goid {
########################################################################
    my ($self, $i, $locusList) = @_;
    return Tr(td({-colspan=>'2'},
		 font({-size=>'-1'},
		      "Enter loci that share this GO annotation; ".
		      "separate multiples by |")).
	      td({-colspan=>'2'},
		 textfield(-name=>"locuslist$i",
			   -value=>"$locusList",
			   -size=>'40'))
	   );
}

########################################################################
sub featureList4goid {
########################################################################
    my ($self, $i, $featList) = @_;
    return Tr(td({-colspan=>'2'},
		 font({-size=>'-1'},
		      "Enter features that share this GO annotation; ".
		      "separate multiples by |")).
	      td({-colspan=>'2'},
		 textfield(-name=>"featlist$i",
			   -value=>"$featList",
			   -size=>'40'))
	   );

}


########################################################################
sub printMoreRows {
########################################################################
    my ($self, $num) = @_;
    my $end;
    if ($num >= 5) {
	$end = $num + 2;
    }
    else {
	$end = $num + 7;
    }
    print $self->headerRow;
    for (my $i = $num; $i <= $end; $i++) {
	print Tr(td($self->ontologyField($i)).
		 td($self->goidField($i)).
		 td($self->goReferenceField($i)).
		 td($self->goEvidenceField($i)).
	         td($self->goWithFromField($i))),
	      $self->locusList4goid($i),
	      $self->featureList4goid($i),
	      $self->rowSeparator;
    }
}

#######################################################################
sub printOneRow {
#######################################################################
    my ($self, $i, $goAspect, $goid, $goTerm, $refNo, $pubmed, 
	$goevCodeRef, $isNot, $locusList, $featList, $deleteAnnot, 
	$source, $ID, $ICgoid, $goevRef4withFrom) = @_;

    print 
	Tr(td($self->ontologyField($i, $goAspect)).
	   td($self->goidField($i, $goid, $goTerm, $isNot)).
	   td($self->goReferenceField($i, $refNo, $pubmed)).
	   td($self->goEvidenceField($i,  $goevCodeRef)).
	   td($self->goWithFromField($i, $source, 
				     $ID, $ICgoid, 
				     $goevRef4withFrom))
	),
	$self->locusList4goid($i, $locusList),
	$self->featureList4goid($i, $featList),
        $self->rowSeparator;
}

########################################################################
sub rowSeparator {
########################################################################
    return Tr(td({-colspan=>'5'},
		 hr));

}

########################################################################
sub printHeaderRow4existingInfo {
########################################################################
    print "<tr><td colspan=8 align = center BGCOLOR='#a4abc2'><b>Existing Annotations</b></td></tr>",
          Tr(td({-align=>'center'},
		b(font({-size=>'-1'},
		  "Ontology"))).
	     td({-align=>'center'},
		b(font({-size=>'-1'},
		  "Goid"))).
	     td({-align=>'center'},
		b(font({-size=>'-1'},
		  "Go Term"))).
	     td({-align=>'center'},
		b(font({-size=>'-1'},
		  "Reference"))).
	     td({-align=>'center'},
		b(font({-size=>'-1'},
		  "Evidence Code"))).
	     td({-align=>'center'},
		b(font({-size=>'-1'},
		  "With"))).
	     td({-align=>'center'},
		b(font({-size=>'-1'},
		  "Delete?"))).
	     td({-align=>'center'},
		b(font({-size=>'-1'},
		  "Shared?"))));
}

########################################################################
sub printOneRow4existingInfo {
########################################################################
    my ($self, $i, $ontology, $goid, $goTerm, $paper, $EvCodeList, 
	$externalId, $source, $deleteAnnot, $shared) = @_;
    if ($shared =~ /yes/i) {
	my $user = $self->user;
	$shared = a({-href=>url."?user=$user&goid=$goid",
		     -target=>'infowin',
		     -onClick=>'open_win()'}, $shared);

    }
    print Tr(td({-align=>'center'},
		font({-size=>'-1'},
		  $ontology)).
	     td({-align=>'center'},
		font({-size=>'-1'},
		  $goid)).
	     td({-align=>'center'},
		font({-size=>'-1'},
		  $goTerm)).
	     td({-align=>'center'},
		font({-size=>'-1'},
		  $paper)).
	     td({-align=>'center'},
		font({-size=>'-1'},
		  $EvCodeList)).
	     td({-align=>'center'},
		font({-size=>'-1'},
		  $source.":".$externalId)).
	     td({-align=>'center'},
		  checkbox(-name=>"deleteAnnot$i",
			  -label=>"delete")).
	     td({-align=>'center'},
		font({-size=>'-1'},
		  $shared)));
    
}

########################################################################
sub err_report {
########################################################################
    my ($self, $err) = @_;
 
    &printStartPage($self->database, $self->title, $self->help);
    
    print b($err);
    
    &printEndPage;

    if ($dbh) { $dbh->disconnect; }
    exit;
}

########################################################################
1;
########################################################################



















