#!/usr/bin/perl
package LocusPage;

use strict;

use DBI;

use CGI qw/:all :html3/;
use CGI::Carp qw(fatalsToBrowser);

use lib "/usr/local/dicty/www_dictybase/db/lib/dictyBase/Objects";
use ConfigURLdictyBase;
use ParagraphUI;
 
use lib "/usr/local/dicty/www_dictybase/db/lib/common";
use Login qw (ConnectToDatabase);

use lib "/usr/local/dicty/www_dictybase/db/lib/dictyBase";
use FormatdictyBase qw (FooterReturnEmail Copyright);
use dictyBaseCentralMod qw(:formatPage);
use dictyBaseObject;
use CGI_ARG qw (GetQueryAndType);

{
####################################################################
# Class Globals
####################################################################

    my $separator; 
    my $dbh;

    my $configUrl = ConfigURLdictyBase->new;


    if (!(user_agent() =~/MSIE/ && user_agent() =~/Mac/i)){ # if it's not MAC IE

	$separator = br; # need a separator
    }

    my $newParagraphDisplay = "on";


#############################################################################
sub new {
#############################################################################
# This constructor simply returns a blessed hash.  Three attributes, which
# holds the actual query, the database, and the help page url, are stored

    my $self = {};

    bless $self, shift;

    my (%args) = @_;

    ($self->{'_query'}, $self->{'_type'}) = &GetQueryAndType(%args);
    
    $self->{'_help'}     = $args{'help'};
    $self->{'_database'} = $args{'database'};

    if ($self->{'_database'} eq "dictyBase"){
	
	$self->{'_linker'} = "dictyBase";

    }else{

	$self->{'_linker'} = "dictyBaseDEV";

    }

    return $self;

}

#############################################################################
sub print{
#############################################################################
# This method prints out everything required for the the locus page based on 
# the query

    my ($self) = @_;

    if ($self->{'_query'}=~/\*/){ # it's a wild card search

	$self->{'_title'} = "Search Results for : ".$self->{'_query'};

	if ($self->{'_type'} =~ /^dictyBaseid$/i) {
	    $self->errReport("Wild-card searches do not work for dictyBaseID's.");
	}
	if ($self->{'_query'} =~ /^ *[\*\%]+ *$/) {
	    $self->errReport("Your query has to contain letter(s) or number(s).");
	}

	$self->wildSearch;

    }elsif (!$self->{'_query'}){

	$self->printSearchForm;

    }else{

	$self->printLocusPage;

    }

    $self->pageBottom;

}

#############################################################################
sub errReport {
#############################################################################
    my ($self, $err) = @_;
    
    $self->pageTop;
    print center(h2($err),
    h2("Please try it again."),
    $self->searchFormTable());
    $self->pageBottom;
    exit;
}

#############################################################################
sub printLocusPage{
#############################################################################
# This method prints out a locus page for a given query
	
    my ($self) = @_;

    my $dictyBase;

    $dictyBase = dictyBaseObject->new($self->{'_type'}=>$self->{'_query'},
			  database=>$self->{'_database'});

    # intercept if to more than one

    if ($dictyBase->isMultiple){ # the query maps to more than one entity
	
	$self->{'_title'} = "Search for : ".$self->{'_query'};
	$self->wildSearch;
	return;

    }

    $self->{'_title'} = $dictyBase->title; # get title
    
#    my $JScript = "

#    function switchAddress(list ){
	
#	location.href = list.options[list.selectedIndex].value;
#    }";

#    $self->pageTop(JScript=>$JScript);
    
    $self->pageTop;

    $self->{'_printedHeader'} = 1;

    $dictyBase->_initURLs; # need these for locus page - should rework

    if ($dictyBase->orf || $dictyBase->gene){
	
	if ($dictyBase->featureType =~ /Deleted/){
	    print center(h1("This feature has been deleted from the Dictyostelium Database."));
	}elsif ($dictyBase->featureType =~ /Merged/){
	    print center(h1("This feature has been merged into another feature."));
	}
	print $self->locusTable($dictyBase);

	if ($newParagraphDisplay =~ /on/i ) {

	    my $uiModule = ParagraphUI->new();
	    print $uiModule->displayParagraph(dictyBaseObject=>$dictyBase);
	}

    }elsif ($dictyBase->dictyBaseidType eq "Deleted"){

	$self->deleteddictyBaseID($dictyBase);

    }else{

	print center(h2("Your search for ".font({-color=>'red'}, $self->{'_query'})." did not return any hits."),
		     h2("Wild cards were prepended and appended to your query."));
	$self->{'_query'} = "*".$self->{'_query'}."*";
#	print h4("Search for ".$self->{'_query'}.":");
	$self->wildSearch;

    }

}

#############################################################################
sub pageTop{
#############################################################################
# This simply prints the html at the top of a page

    my ($self, %args) = @_;

    &printStartPage($self->{'_database'}, $self->{'_title'}, 
		    $self->{'_help'});

}

#############################################################################
sub pageBottom{
#############################################################################
# This simply prints out stuff to go at the botttom of the page

    my ($self) = @_;

    print p, hr,
    
    $self->copyright,
    
    hr,
    
    &FooterReturnEmail,
    
    end_html;

}

############################################################################
sub locusTable{
############################################################################
# This subroutine returns the table that contains all the locus info in it

    my ($self, $dictyBase) = @_;

    my $formCell = $self->formCell($dictyBase);
    my $positionWord = "Sequence Coordinates";
    my $nameHead = "Standard Name ";
    my $standardName = $dictyBase->gene;
    if ($dictyBase->isReserved){
	$nameHead = "Reserved Name ";
	$standardName .= br.br.i("This name is reserved with dictyBase according to the ".a({-href=>$configUrl->breadServerRoot."gene_guidelines.html"}, "Gene Naming Guidelines")." agreed upon by the Dictyostelium community.").br."For more information about this reservation please see the ".a({-href=>$dictyBase->history},	"Locus History").".";
    }
    
    my $alias = $dictyBase->alias;
    my $orf   = $dictyBase->orf;
    my $goRow = $self->getGoRow($dictyBase);
    my $pathway = $self->getPathway($dictyBase);
    my $description = $dictyBase->description;
    my $product = join (br, @{$dictyBase->product});
    my $phenotype = $self->phenotype($dictyBase);
    my $positionalInfo = $dictyBase->positionalInfo;
    my $externalLinks = $dictyBase->externalLinks;
    my $primarydictyBaseID = $dictyBase->primarydictyBaseID;
    my $featureType = $dictyBase->featureType;
    my $lastUpdate;

    my $interactionType = $self->relatedInteractors($dictyBase, "forTopLink");

    if ($standardName && $interactionType) {
	$standardName .= " ( see ".a({-href=>'#interactionNote'}, $interactionType)." )";
    }

    if ($featureType =~ /Deleted/){
	$positionWord = "Position prior to deletion";
    }

    my @rows;

    push (@rows, $self->oneRow($nameHead, i($standardName))) if $standardName;
    push (@rows, $self->oneRow("Alias ", i($alias))) if $alias;
    push (@rows, $self->oneRow("Systematic Name ", $orf)) if $orf;
    push (@rows, $self->oneRow("Feature Type ", $featureType)) if $featureType;

    push (@rows, $goRow) if ($goRow);
    push (@rows, $pathway) if ($pathway);
    push (@rows, $self->oneRow("Description ", $description)) if $description;
    push (@rows, $self->oneRow("Gene Product ", $product)) if $product;
    push (@rows, $phenotype) if ($phenotype);
    push (@rows, $self->oneRow($positionWord, $positionalInfo)) if $positionalInfo;
    push (@rows, $self->oneRow("External Links ", $externalLinks)) if $externalLinks;
    push (@rows, $self->oneRow("Primary dictyBaseID ", $primarydictyBaseID));
    push (@rows, $self->oneRow("Last Update ", $lastUpdate)) if $lastUpdate;

    my $rows = @rows;

    $rows[0] .= td({-rowspan=>$rows,
		    -bgcolor=>'#d8d8d8',
		    -valign=>'top'},
		   $formCell) if $formCell;

    my $formHeading;

    if ($formCell){

	$formHeading = td(center(b(font({-color=>'red',
					      -size=>'+1'},
					     $dictyBase->standardName),
					font({-size=>'+1'},
					     " RESOURCES"))));

    }

    unshift (@rows, td({-colspan=>3}, br));

    unshift (@rows, td({-colspan=>2},
			       b(font({-color=>'red',
				       -size=>'+1'},
				      $dictyBase->standardName),
				 font({-size=>'+1'},
				      " BASIC INFORMATION"))).$formHeading);
    

    push (@rows, td({-colspan=>3}, 
		    p, 
		    
		    $self->additionalInfo($dictyBase)));

    push (@rows, td({-colspan=>3},
		    p,
		    $self->communityAnnotation($dictyBase)));

    push (@rows, td({-colspan=>3}, 
		    p, 
		    $self->relatedInteractors($dictyBase)));

    #link to single page format
    my $singlepageUrl = $dictyBase->singlepageUrl;

    return h3(a({-href=>$singlepageUrl}, "Alternative single page format") .
              img({-src=>$configUrl->breadServerRoot.'images/new.gif'})) .p.
           center(table({-border=>0,
			 -cellspacing=>3,
			 -cellpadding=>3},
			Tr(
			   [@rows]
			   )
			));
    
}

##########################################################################################################
sub molFunction{
##########################################################################################################
# This function returns a formatted string for go terms, and their links

    my ($self, $dictyBase) = @_;

    my ($arrayRef, $goidHashRef, $refHashRef) = $dictyBase->molFunction;

    my $string = $self->makeOntologyString($arrayRef, $goidHashRef, $refHashRef, "F");

    my $num = @$arrayRef;
    return ($string, $num);

}

##########################################################################################################
sub cellComponent{
##########################################################################################################
# This function returns a formatted string for go terms, and their links

    my ($self, $dictyBase) = @_;

    my ($arrayRef, $goidHashRef, $refHashRef) = $dictyBase->cellComponent;

    my $string = $self->makeOntologyString($arrayRef, $goidHashRef, $refHashRef, "C");

    my $num = @$arrayRef;
    return ($string, $num);
}

##########################################################################################################
sub bioProcess{
##########################################################################################################
# This function returns a formatted string for go terms, and their links

    my ($self, $dictyBase) = @_;

    my ($arrayRef, $goidHashRef, $refHashRef) = $dictyBase->bioProcess;

    my $string = $self->makeOntologyString($arrayRef, $goidHashRef, $refHashRef, "P");

    my $num = @$arrayRef;
    return ($string, $num);

}

######################################################################
sub getGoRow {
######################################################################
    my ($self, $dictyBase) = @_;

    my ($molFunction, $molFunctionBrNum) = $self->molFunction($dictyBase);
    my ($bioProcess, $bioProcessBrNum) = $self->bioProcess($dictyBase);
    my ($cellComponent, $cellComponentBrNum) = $self->cellComponent($dictyBase);
    
    my ($golist1, $golist2);
    if ($molFunction) {
	$golist1 = "&nbsp;&nbsp;Molecular Function".
		   $self->linebreak($molFunctionBrNum);
	$golist2 = $molFunction.p;
	
    }
    if ($bioProcess) {
	$golist1 .= "&nbsp;&nbsp;Biological Process".
		    $self->linebreak($bioProcessBrNum);
	$golist2 .= $bioProcess.p;
    }
    if ($cellComponent) {
	$golist1 .= "&nbsp;&nbsp;Cellular Component".
		    $self->linebreak($cellComponentBrNum);
	$golist2 .= $cellComponent.p;
    }
    if (!$golist1) { return; }
    my $name;
    if ($dictyBase->locusName) { $name = $dictyBase->locusName; }
    else { $name = $dictyBase->featureName; }
    my $goAnnotUrl = "/cgi-bin/".$self->{'_linker'}."/GO/goAnnotation.pl?locus=".$name;
    return td({-nowrap=>'',
	       -bgcolor=>'#a4abc2',
	       -valign=>'top'},
	       b("GO Annotations").p.
	       $golist1).
	   td({-nowrap=>'',
               -valign=>'top'},
	       a({-href=>"$goAnnotUrl"}, 
		i(b($name." GO evidence and references"))).p.
		$golist2);
}

######################################################################
sub getPathway {
######################################################################
    my ($self, $dictyBase) = @_;

    my $rowAref = $dictyBase->pathwayRow;

    if (! defined @$rowAref) {
	return;
    }

    my $row;
    my $imageUrl = $configUrl->breadServerRoot."images/blackdot.gif";

    my $brCt;
    foreach my $item (@$rowAref) {
        next if (! defined $item);
	$row .= img({-src=>$imageUrl}) ."&nbsp;&nbsp;" .$item .br;
	$brCt++;
    }
    
    return td({-nowrap=>'',
	       -bgcolor=>'#a4abc2',
	       -valign=>'top'},
	       b("Pathways") ).
	   td({-nowrap=>'',
               -Valign=>'top'},
	       $row
	     );
}

######################################################################
sub linebreak {
######################################################################
    my ($self, $num) = @_;
    my $break = p;
    for (my $i = 2; $i <= $num; $i++) {
	$break .= br;
    }	
    return $break;
}

##########################################################################################################
sub makeOntologyString{
##########################################################################################################
# 
    
    my ($self, $arrayRef, $goidHashRef, $refHashRef, $goAspect) = @_;

    my $string;
    my $imageUrl = $configUrl->breadServerRoot."images/blackdot.gif";
    my $goUrl = "/cgi-bin/".$self->{'_linker'}."/GO/go.pl?goid=";

    foreach my $term (@{$arrayRef}){
	my $refNo = $$refHashRef{$term};
	$term = a({-href=>$goUrl.$$goidHashRef{$term}}, $term);
	if ($refNo) {
	    # $refNo =~ s/^([0-9]+)\:\:.+$/$1/;
	    # my $isNot = a({-href=>"/cgi-bin/".$self->{'_linker'}."/reference/reference.pl?refNo=$refNo"}, b(i("NOT")));
	    my $isNot = a({-href=>"/html/help/GO.html#not"}, 
			  b(i("NOT")));
	    if ($goAspect eq "F") {
		$term = $isNot." a ".$term;
	    }
	    elsif ($goAspect eq "P") {
		$term = $isNot." involved in ".$term;
	    }
	    else {
		$term = $isNot." part of ".$term;
	    }
	}
	
	$string .= img({-src=>$imageUrl,
		       -valign=>"MIDDLE",
		       -alt=>"*",
			-border=>0}).

			    "&nbsp;&nbsp;".
			    $term.br;

    }

    $string =~ s/\<br\>$//;

    return $string;

}

###########################
sub phenotype {
##########################################################################################################
# This function returns a formatted string for phenotype 

    my ($self, $dictyBase) = @_;

    my $sacchdbPhenotype = $dictyBase->SacchdbPhenotype;
    my $phenotypeArrayRef = $dictyBase->phenotype;

    my $imageUrl = $configUrl->breadServerRoot."images/blackdot.gif";
    my $phenotypeUrl = "/cgi-bin/".$self->{'_linker'}."/phenotype/phenotype.pl";

    my $string;

    my ($left, $right);

    $left = b("Phenotype").br .br .br .br;

    my ($phenoDetailsLinkText, $lenLimit);
#
# jmc comment out addition of extra br if locusName > 4
# this does not seem to be needed.
#    if (!$dictyBase->locusName || length($dictyBase->locusName) > 4) {
#	$left .= br;
#	$phenoDetailsLinkText = " Phenotype details and".br." references";
#	$lenLimit = 34;
#    }
#    else {
	$phenoDetailsLinkText = " Phenotype details and references";
	$lenLimit = 43;
#    }

    my $preType;
    my $countBreak = 0;
    foreach my $rowRef (@$phenotypeArrayRef) {
	my ($type, $phenotype, $phenotypeNo) = @$rowRef;
      
	if ($type ne $preType) {
                $left .= $self->linebreak($countBreak);
                $left .= "&nbsp;&nbsp;".$type;
                $right .= p;
                $countBreak = 1;
        }
        else {
            $countBreak++;
        }

        # Stan Dong 10-24-02
        # add 'display=no' lead to an intermediate page for #phenotype > 30
	if (length($phenotype) > $lenLimit) {
	    
	    $countBreak++;

	    my @phenoWord = split(/ /, $phenotype);
	    
	    my $rest = pop(@phenoWord);

	    $phenotype = join(' ', @phenoWord);

	    while (length($phenotype) > $lenLimit) {

     		my $word = pop(@phenoWord);

		$phenotype = join(' ', @phenoWord);

		$rest = $word." ".$rest;

	    }

	    # $phenotype .= br."&nbsp;&nbsp;&nbsp;".$rest;
	    # $phenotype .= br.$rest;

	    $phenotype = a({-href=>$phenotypeUrl."?phenotype=".$phenotypeNo. "&display=no"}, $phenotype).br."&nbsp;&nbsp;&nbsp;".
		         a({-href=>$phenotypeUrl."?phenotype=".$phenotypeNo. "&display=no"}, $rest).br;

	}
	else {
	    $phenotype = a({-href=>$phenotypeUrl."?phenotype=".$phenotypeNo. "&display=no"}, $phenotype).br;
	}

	$right .= img({-src=>$imageUrl, -valign=>"MIDDLE", -alt=>"*",
		       -border=>0}) . "&nbsp;&nbsp;" . $phenotype;
	$preType = $type;	
    }

    if ($sacchdbPhenotype) {
        $left .= $self->linebreak($countBreak);
        $left .= "&nbsp;&nbsp;"."Free text";
	$right .= p. img({-src=>$imageUrl,
		      -valign=>"MIDDLE",
		      -alt=>"*",
		      -border=>0})."&nbsp;&nbsp;".
                 $sacchdbPhenotype;    		     
    }

    if ($preType) {
	my ($PTurl, $linkNm);
	if ($dictyBase->locusName) {
	    $linkNm = $dictyBase->locusName;
	    $PTurl =  $phenotypeUrl."?feat=".$linkNm."&type=locus";
        }
	else {
	    $linkNm = $dictyBase->featureName;
	    $PTurl =  $phenotypeUrl."?feat=".$linkNm."&type=feature";
        }

        my $phenoFirstLine = a({-href=>$PTurl}, $linkNm.$phenoDetailsLinkText);

        #add link to open biosystems
        my $openBioUrl = $dictyBase->openBio;
# stan's original
#        $phenoFirstLine .= br. br. a({-href=>$openBioUrl}, "Order mutant strains used in the systematic deletion " .br. "project") if $phenoFirstLine;
        $phenoFirstLine .= br. br. a({-href=>$openBioUrl}, "Order mutant strains used in the systematic deletion project") . br .br if $phenoFirstLine;
        $right = b(i($phenoFirstLine)) .$right;
#        $right = b(i(a({-href=>$PTurl}, $linkNm.$phenoDetailsLinkText))).$right;
    }

    if (!$right) { return; }

    return td({-bgcolor=>'#a4abc2',-valign=>'top'}, 
              $left) .
           td({-valign=>'top'}, $right);

}


##########################################################################################################
sub formCell{
##########################################################################################################
# This subroutine prints returns a cell that contains all the elements of the right hand cell of the table
# on the locus page

    my ($self, $dictyBase) = @_;

    #return if !($self->{'begCoord'}); # don't give this section if there's no associated sequence

    my $cell;
    my $deleted;
    my $merged;
    
    if ($dictyBase->featureType =~ /Deleted/){
	$deleted =1;
    }

    if ($dictyBase->featureType =~ /Merged/){
	$merged =1;
    }

    $cell .= $self->mapSection($dictyBase) if ($dictyBase->begCoord && !$deleted && !$merged);
    $cell .= $self->litSection($dictyBase) if (!$deleted && !$merged);
    $cell .= $self->seqSection($dictyBase) if (!$deleted && !$merged);
    $cell .= $self->analysisSection($dictyBase) if ($dictyBase->begCoord && !$deleted && !$merged);
    $cell .= $self->proteinSection($dictyBase) if ($dictyBase->begCoord && !$deleted && !$merged);
    $cell .= $self->interactionSection($dictyBase) if ($dictyBase->begCoord && !$deleted && !$merged);
    $cell .= $self->displaysSection($dictyBase) if ($dictyBase->begCoord && !$deleted && !$merged);
    $cell .= $self->compSection($dictyBase) if ($dictyBase->begCoord && !$deleted && !$merged);
    $cell .= $self->functionSection($dictyBase) if ($dictyBase->begCoord && !$deleted && !$merged);

    return $cell;

}

##########################################################################################################
sub mapSection{
##########################################################################################################
# This subroutine returns the section of the right hand cell on the locus page that contains the clickable
# mini orf map

    my ($self, $dictyBase) = @_;

    return center(font({-size=>'-1'},
		       "Click on map for expanded view"),
		  br,
		  a({-href=>$dictyBase->orfMap},
		    img({-src=>$dictyBase->miniORFMap,
			 -border=>0,
			 -alt=>'ORFmap'})));
    
}

##########################################################################################################
sub litSection{
##########################################################################################################
# This subroutine returns the section of the right hand cell on the locus page that contains links to do
# with literature for the gene

    my ($self, $dictyBase) = @_;

    my $literatureGuide = $dictyBase->litGuide;
    my $pubMedSearch = $dictyBase->pubMed;
    my $paragraph = $dictyBase->paragraph;
    my $communityAnnotation = $dictyBase->communityAnnotation;
    my $germOnline = $dictyBase->germOnline;

    my @values = ($literatureGuide, $pubMedSearch, $communityAnnotation);

    if ($newParagraphDisplay eq "off") {
	push (@values, $paragraph) if $paragraph;
    }
    else {
	if (defined $paragraph) {
	    $paragraph = "#summaryParagraph";
	    push (@values, $paragraph);
	}
    }

    if (defined $germOnline) {
	push (@values, $germOnline);
    }

    my %lit = (
	       $literatureGuide =>"Literature Guide",
	       $pubMedSearch => "PubMed Search",
	       $communityAnnotation=>"Community Annotation",
	       $paragraph => "Summary Paragraph",
               $germOnline => "GermOnline"
	       );

    return
	start_form.
	    li(b("Literature")).$separator.
		popup_menu(-name=>'lit',
			   -"values"=>\@values,
			   -labels=>\%lit).
			       button(-onClick=>'switchAddress(this.form.lit)',
				      -name=>'View').
					  end_form;

}     

########################################################################################################
sub seqSection{
########################################################################################################
# This subroutine returns the section of the right hand cell on the locus page that contains links to 
# retrieve various sequences associated with the locus

    my ($self, $dictyBase) = @_;

    my $intron   = $dictyBase->intronSeq if $dictyBase->begCoord;
    my $upDownStream = $dictyBase->upDownStreamSeq if $dictyBase->begCoord;
    my $noIntron = $dictyBase->noIntronSeq if $dictyBase->begCoord;
    my $trans    = $dictyBase->translation if $dictyBase->begCoord;
    my $trans6   = $dictyBase->trans6frame if $dictyBase->begCoord;
    my $frags    = $dictyBase->restrict if $dictyBase->begCoord;
    my $genBank  = $dictyBase->genBankSeqs;
    my $seqResources = $dictyBase->seqResources;

    my %seq = (
	       $intron=>"Genomic DNA",
	       $upDownStream=>"DNA + 1 kb up/downstream",
	       $noIntron=>"Coding sequence",
	       $trans=>"ORF Translation",
	       $trans6=>"6-Frame Transl.",
	       $frags=>"Rest. Frag. Sizes",
	       $genBank=>"All Associated Seq",
	       $seqResources=>"Custom Retrieval"
	       );

    my @values;

    push (@values, $intron) if $intron;
    push (@values, $upDownStream) if $upDownStream;
    push (@values, $noIntron) if $noIntron;
    push (@values, $trans) if $trans;
    push (@values, $trans6) if $trans6;
    push (@values, $frags) if $frags;
    push (@values, $genBank) if $genBank;
    push (@values, $seqResources) if $seqResources;

    if (@values){

	return 
	    start_form.
		li(b("Retrieve Sequences")).$separator.
		    popup_menu(-name=>'seq',
			       -"values"=>\@values,
			       -labels=>\%seq).
				   button(-onClick=>'switchAddress(this.form.seq)',
					  -name=>'Retrieve').
					      end_form;

    }else{

	return;

    }
}

########################################################################################################
sub interactionSection{
########################################################################################################
# This subroutine returns the section of the right hand cell on the 
# locus page that contains links to protein interactions pages  
# 

    my ($self, $dictyBase) = @_;

    my $grid = $dictyBase->grid;
    my $bind = $dictyBase->bind;
    my $curagen = $dictyBase->curagen;
    my $dip = $dictyBase->dip;

    my %prot = (
	       $grid=>"Interactions DB (GRID)",
               $bind=>"Interactions DB ( BIND )",
	       $curagen=>"Two Hybrid (Portal PathCalling)",
               $dip=>"DB of Interacting Proteins (DIP)"
    );

    my @values;

    push (@values, $grid) if $grid;
    push (@values, $bind) if $bind;
    push (@values, $curagen) if $curagen;
    push (@values, $dip) if $dip;

    if (@values){

	return 
	    start_form.
		li(b("Interactions")).$separator.
		    popup_menu(-name=>'interact',
			       -"values"=>\@values,
			       -labels=>\%prot).
				   button(-onClick=>'switchAddress(this.form.interact)',
					  -name=>'View').
					      end_form;

    }
    return;

}

#########################################################################################################
sub proteinSection{
########################################################################################################
# This subroutine returns the section of the right hand cell on the 
# locus page that contains links to protein info & structure pages  
# 

    my ($self, $dictyBase) = @_;

    my $pdb = $dictyBase->pdbInfo;
    my $motif = $dictyBase->motifInfo;
    my $ypd = $dictyBase->protInfo;
    my $scop = $dictyBase->scop;

    my %prot = (
	       $motif=>"Motifs",
	       $pdb=>"PDB Homologs",
	       $ypd=>"Protein Info",
               $scop=>"SCOP superfamily (MRC/Stanford)"
    );

    my @values;

    push (@values, $ypd) if $ypd;
    push (@values, $motif) if $motif;
    push (@values, $pdb) if $pdb;
    push (@values, $scop) if $scop;

    if (@values){

	return 
	    start_form.
		li(b("Protein Info & Structure")).$separator.
		    popup_menu(-name=>'prot',
			       -"values"=>\@values,
			       -labels=>\%prot).
				   button(-onClick=>'switchAddress(this.form.prot)',
					  -name=>'View').
					      end_form;

    }
    return;

}


#########################################################################################################
sub analysisSection{
#########################################################################################################
# This subroutine returns the section of the right hand cell on the locus page that contains links to
# various sequence analysis tools.  The links don't yet work, as I haven't come up with a good idea as
# to how to do them
    
    my ($self, $dictyBase) = @_;

    my $blastp = $dictyBase->blastp;
    my $blastn = $dictyBase->blastn;
    my $bpNCBI = $dictyBase->bpNCBI;  #blasp at NCBI
    my $fastan = $dictyBase->fastan;
    my $fastap = $dictyBase->fastap;
    my $restrMap = $dictyBase->restrMap;
    my $primer = $dictyBase->primer;

    my @values;

    push (@values, $blastp) if $blastp;
    push (@values, $blastn) if $blastn;
    push (@values, $bpNCBI) if $bpNCBI;
    push (@values, $fastan) if $fastan;
    push (@values, $fastap) if $fastap;
    push (@values, $restrMap) if $restrMap;
    push (@values, $primer) if $primer;

    my %analysis = (
		    $blastn=>"BLASTN",
		    $blastp=>"BLASTP",
                    $bpNCBI=>"BLASTP at NCBI",
		    $fastan=>"FASTA nt",
		    $fastap=>"FASTA aa",
		    $restrMap=>"Restriction Map",
		    $primer=>"Design Primer"
		    );

    if (@values) {

	return 
	    start_form.
		li(b("Sequence Analysis Tools")).$separator.
		    popup_menu(-name=>'analysis',
			       -"values"=>\@values,
			       -labels=>\%analysis).
				   button(-onClick=>'switchAddress(this.form.analysis)',
					  -name=>'Analyze').
					      end_form;
    }else{

	return;

    }
}

#########################################################################################################
sub displaysSection{
#########################################################################################################
# This subroutine returns the section of the right hand cell on the locus page that contains links to
# various maps and displays

    my ($self, $dictyBase) = @_;

    my $chrFeaturesMap = $dictyBase->chrFeaturesMap;
    my $chrFeaturesTable = $dictyBase->chrFeaturesTable;
    my $physGen = $dictyBase->physGen;
    my $physMap = $dictyBase->physMap;
    my $ratioMap = $dictyBase->ratioMap;

    my @values = ($chrFeaturesTable, $physGen, $physMap, $ratioMap);

    unshift (@values, $chrFeaturesMap) if ($dictyBase->featureType !~ /(Deleted|Merged)/);
    
    my %displays = (
		    $chrFeaturesMap=>"Chr. Features Map",
		    $chrFeaturesTable=>"Chr. Features Table",
		    $physGen=>"Phys/Gen Map",
		    $physMap=>"Physical Map",
		    $ratioMap=>"P/G Map Ratios"
		    );

    return 
	start_form.
	    li(b("Maps and Displays")).$separator.
		popup_menu(-name=>'display',
			   -"values"=>\@values,
			   -labels=>\%displays).
			       button(-onClick=>'switchAddress(this.form.display)',
				      -name=>'View').
					  end_form;

}

#########################################################################################################
sub compSection{
#########################################################################################################
# This subroutine returns the section of the right hand cell on the locus page that contains links to
# various comparison resources

    my ($self, $dictyBase) = @_;

    my $syntenyViewer = $dictyBase->syntenyViewer;
    my $candidaComp = $dictyBase->candidaComp;
    my $wormComp = $dictyBase->wormComp;
    my $mamComp = $dictyBase->mamComp;
    my $fungalAlign = $dictyBase->fungalAlign;
    
    my %comparisons = (
		       $syntenyViewer=>'Synteny Viewer',
		       $fungalAlign=>"Fungal alignments",
		       $candidaComp=>"Candida homologs (CandidaDB)",
		       $mamComp=>"Mammalian Homologs",
		       $wormComp=>"Worm Homologs"
    );

    my @values;

    push (@values, $fungalAlign) if $fungalAlign;
    push (@values, $syntenyViewer) if $syntenyViewer;
    push (@values, $candidaComp) if $candidaComp;
    push (@values, $wormComp) if $wormComp;
    push (@values, $mamComp) if $mamComp;

    if (@values){

	return 
	    start_form.
		li(b("Comparison Resources")).$separator.
		    popup_menu(-name=>'comp',
			       -"values"=>\@values,
			       -labels=>\%comparisons).
				   button(-onClick=>'switchAddress(this.form.comp)',
					  -name=>'View').
					      end_form;
    }else{

	return;

    }
	
}

#########################################################################################################
sub functionSection{
#########################################################################################################
# This subroutine returns the section of the right hand cell on the locus page that contains links to
# various functional resources

    my ($self, $dictyBase) = @_;

    my $cellcycle = $dictyBase->cellcycle;
    my $curagen = $dictyBase->curagen;
    my $triples = $dictyBase->triples;
    my $marcotte = $dictyBase->marcotte;
    my $sporulation = $dictyBase->sporulation;
    my $diauxic = $dictyBase->diauxic;
    my $evolution = $dictyBase->evolution;
    my $alpha_conc = $dictyBase->alpha_conc;
    my $alpha_time = $dictyBase->alpha_time;
    my $histone    = $dictyBase->histone;
    my $stressResponse = $dictyBase->stressResponse;
    my $dnaDamage = $dictyBase->dnaDamage;
    my $ygmv = $dictyBase->ygmv;
    my $zinc = $dictyBase->zinc;
    my $phosphate = $dictyBase->phosphate;

    my %functions = (
		     $cellcycle=>"Stanford Cell Cycle",
		     $diauxic=>"Diauxic Shift",
		     $sporulation=>"Sporulation Time Series",
		     $curagen=>"Two Hybrid (Portal PathCalling)",
		     $triples=>"YGAC Triples",
		     $marcotte=>"UCLA Function Assignment",
		     $evolution=>"Glucose limitation",
                     $zinc=>"Zinc response",
		     $phosphate=>"PHO regulatory pathway",
		     $alpha_conc=>"Alpha Factor Concentration",
		     $alpha_time=>"Alpha Factor Time Series",
		     $histone=>"Histone Depletion",
		     $stressResponse=>"Stress Response",
		     $dnaDamage=>"DNA damage",
		     $ygmv => "Dictyostelium Global Microarray Viewer");
			

    return 
	start_form.
	    li(b("Functional Analysis")).$separator.
		popup_menu(-name=>'funcAn',
			   -"values"=>[$alpha_conc, $alpha_time, 
				       $cellcycle, $diauxic, $histone, 
				       $sporulation, $stressResponse,
				       $dnaDamage, $evolution, $zinc,
				       $phosphate, $curagen, $triples, 
				       $marcotte, $ygmv],
			   -labels=>\%functions).
			       button(-onClick=>'switchAddress(this.form.funcAn)',
				      -name=>'View').
					  end_form;

    
}

#########################################################################################################
sub oneRow{
#########################################################################################################
# This subroutine returns two table cells joined that form the left two columns of the table on the locus
# page

    my ($self, $left, $right) = @_;

    my $cellColor = "#a4abc2";

    return td({-valign=>'top',
	       -bgcolor=>$cellColor,
	       -nowrap=>''},
	      $left).
		  td({-valign=>'top'},			      
		     $right);

}

#######################################################################################################
sub relatedInteractors{
#######################################################################################################
# This subroutine returns a table that contains information about things that interact with the locus
# of interest

    my ($self, $dictyBase, $forPageTopLink) = @_;

    my ($dictyBaseid, $interaction, $description, $object, @rows);

    my @data = $dictyBase->fetchRelatedInteractors;

    my $types;
    my %foundType;
    while (@data){

	$dictyBaseid = shift @data; 
	$interaction = shift @data; 
	$description = shift @data;

	if (!$foundType{$interaction}) {
	    $types .= "/".$interaction;
	}
	$foundType{$interaction}++;

	if (!$forPageTopLink) {
	    $object = dictyBaseObject->new(dictyBaseid=>$dictyBaseid);

	    push (@rows, td(a({-href=>url."?dictyBaseid=$dictyBaseid"},
			      $object->standardName)).
		  td($interaction).
		  td($description));
	}

    }

    $types =~ s/^\///;

    if ($types) { $types .= " Note"; }

    if ($forPageTopLink) {
	return $types;
    }

    if (@rows){

	unshift (@rows, th({-colspan=>3,
			    -align=>'LEFT'},
			   $types),
		 td({-align=>'LEFT',
		     -bgcolor=>"#a4abc2"}, "Name").
		 td({-align=>'LEFT',
		     -bgcolor=>"#a4abc2"}, "Relevance").
		 td({-align=>'LEFT',
		     -bgcolor=>"#a4abc2"}, "Description"));

	return a({-name=>'interactionNote'}).
	       table({-width=>'100%'}, Tr([@rows]));

    }else{

	return "";

    }

}

#######################################################################################################
sub additionalInfo{
#######################################################################################################
# 

    my ($self, $dictyBase) = @_;

    my $bgColor="#b7d8e4";

    my ($paragraphCell, $researchersCell, $mappingCell, $protInfoCell, 
	$structInfoCell, $seqResourcesCell);

    my $paragraph = $dictyBase->paragraph;
    my $researchers = $dictyBase->researchers;
    my $mappingData = $dictyBase->mappingData;
    my $protInfo = $dictyBase->protInfo;
    my $seqResources = $dictyBase->seqResources;
    my $motif = $dictyBase->motifInfo;
    my $pdb = $dictyBase->pdbInfo;

    
    my $locusHistoryCell = td({-bgcolor=>$bgColor,
			       -nowrap=>''},
			      a({-href=>$dictyBase->history},
				"Locus History"));
    my $globalGeneHunterCell = td({-bgcolor=>$bgColor,
				   -nowrap=>''},
				  a({-href=>$dictyBase->globalGH},
				    "Global Gene Hunter"));
    my $funcJuncCell = td({-bgcolor=>$bgColor,
			   -nowrap=>''},
			  a({-href=>$dictyBase->FuncJunc},
			    "Function Junction"));

    
    my $expressionCell = td({-bgcolor=>$bgColor,
			     -nowrap=>''},
			    a({-href=>$dictyBase->exprConn},
			      "Expression Connection"));

    if ($paragraph){
	$paragraphCell = td({-bgcolor=>$bgColor,
			     -nowrap=>''},
			    a({-href=>$paragraph},
			      "Summary Paragraph"));
    }	

    if ($researchers){
	$researchersCell = td({-bgcolor=>$bgColor,
			       -nowrap=>''},
			    a({-href=>$researchers},
			      "Researchers"));
    }

    if ($mappingData){
	$mappingCell = td({-bgcolor=>$bgColor,
			   -nowrap=>''},
			    a({-href=>$mappingData},
			      "Mapping Data"));
    }

    if ($protInfo){
	$protInfoCell = td({-bgcolor=>$bgColor,
			     -nowrap=>''},
			    a({-href=>$protInfo},
			      "Protein Info & Composition"));
    }

    if ($motif || $pdb) {
	my $structCell;
	if ($motif) {
	    $structCell = a({-href=>$motif},
			    "Motifs");
	}
	if ($pdb) {
	    if ($structCell) { $structCell .= " | "; }
	    $structCell .= a({-href=>$pdb},
			    "PDB Homologs");
	}
	$structInfoCell = td({-bgcolor=>$bgColor,
			      -nowrap=>''},
			     $structCell);
    }

    if ($seqResources){
	$seqResourcesCell = td({-bgcolor=>$bgColor,
			     -nowrap=>''},
			    a({-href=>$seqResources},
			      "Gene/Sequence Resources"));
    }

    my ($firstRowNum, $secondRowNum, $thirdRowNum);
    my ($firstRow, $secondRow, $thirdRow);
   
    foreach my $cell ( #$paragraphCell, retired for unnecessity. 
                      $locusHistoryCell, 
		      $globalGeneHunterCell, $funcJuncCell, 
		      $expressionCell, $researchersCell, 
		      $mappingCell, $protInfoCell, $structInfoCell, 
		      $seqResourcesCell) {
	if (!$cell) { next; }
	if ($firstRowNum < 4) {  
	    $firstRow .= $cell; 
	    $firstRowNum++;
	    next;
	}
	if ($secondRowNum < 4) { 
	    $secondRow .= $cell;
	    $secondRowNum++;
	    next;
	}
	$thirdRow .= $cell; 
    }
    my $rows = Tr($firstRow);
    if ($secondRow) { $rows .= Tr($secondRow); }
    if ($thirdRow) { $rows .= Tr($thirdRow); }
	
    return center(table({-border=>0,
			 -cellspacing=>3,
			 -cellpadding=>2,
			 -width=>'100%'},
		 Tr(
		    td(font({-face=>"times",
			     -size=>3},
			    b("ADDITIONAL INFORMATION for ").i($dictyBase->standardName)))
		    )
			).
		  table({-border=>0,
			 -cellspacing=>3,
			 -cellpadding=>2,
			 -width=>'100%'},
			$rows
		  ));

}

#######################################################################
sub communityAnnotation {
#######################################################################
# This print out the community annotation section
    my ($self, $dictyBase) = @_;
    my $topic = $dictyBase->CommunityAnnotationTopics;
    my $bgColor="lightgrey";

    my $submitLink = td( {-align=>'right'},
		         a({-href=>"/cgi-bin/".$self->{'_linker'}."/CommunityAnnotation"}, a({-href=>"/cgi-bin/".$self->{'_linker'}."/CommunityAnnotation"}, "Submit a Community Annotation") . img({-src=>'/html/images/star.gif',
				       -border=>0})));

    if (!$topic) {
	return table({-border=>0, 
		      -cellspacing=>3, 
		      -cellpadding=>2, 
		      -width=>'100%'},
		 Tr(td(font({-face=>"times", -size=>3},
			    b("COMMUNITY ANNOTATION for ").
			    i($dictyBase->standardName))) .
                    $submitLink).
		 Tr(td({-colspan=>'2'}, "No \"Research Hightlight\" Annotations have been entered by the Dictyostelium community")));		

    }

    my $rows = table({-border=>0, -cellspacing=>3, -cellpadding=>2, -width=>'100%'},
		 Tr(
		    td(font({-face=>"times", -size=>3},
		        b("COMMUNITY ANNOTATION for ").i($dictyBase->standardName))
		     . img({-src=>$configUrl->breadServerRoot.'images/new.gif'})) .                $submitLink
                 )
	       );

    my $cells;
    my $count = 0;
    my $annoUrl = "/cgi-bin/".$self->{'_linker'}."/DisplayCommuAnno?dictyBaseid=". $dictyBase->primarydictyBaseID;
    foreach my $top (@$topic) {
        $top =~ /^(\w+)/;
        my $anchor = '#' .$1;
        $cells .= td({-bgcolor=>$bgColor, -nowrap=>'1', -width=>"17%"}, a({-href=>$annoUrl. $anchor }, $top));
	$count++;
    }
    for (my $i=0; $i<(6-$count); $i++) {
	$cells .= td({-width=>"17%"}, "&nbsp");
    }

    $rows .= table({-border=>0, -cellspacing=>3, -cellpadding=>2, -width=>'100%'},
		   Tr($cells));
			     
    return center($rows);

}

#######################################################################################################
sub deleteddictyBaseID{
#######################################################################################################
# This prints out any note associated with a deleted dictyBaseid

    my ($self, $dictyBase) = @_;

    my ($note, $public) = $dictyBase->deletedNote;

    print h4("The dictyBaseID you entered is no longer associated with a locus or a feature.");

    if ($note && $public eq "Y"){

	print h4("The following curator note is associated with that dictyBaseID:"),

        $note;

    }

}

#######################################################################################################
sub copyright{
#######################################################################################################
# this simply returns a copyright spiel

    return &Copyright;
    
}

########################################################################################################
sub wildSearch{
########################################################################################################
# This method takes the query, which has a wild card, and searches for all possible hits, and presents
# them back to the user - can we use the dictyBase object itself to make this a lot easier?

    my ($self) = @_;

    my $dbh = &ConnectToDatabase($self->{'_database'});

    my (@hits, %seenF, %seenL, %name);

    my $query = $self->{'_query'};

    $query=~s/\*/\%/g;
    
    $query = uc($query);

    # first check the features

    my $sth = $dbh->prepare("SELECT FEATURE_NAME, FEATURE_NO
                                 from CGM_DDB.feature
                                 WHERE UPPER(FEATURE_NAME) LIKE ?");
    
    $sth->execute($query);
    
    while (my @data = $sth->fetchrow_array){

	$seenF{$data[1]}=uc($data[0]); # remember what we've seen
	
	push (@data, "featureNo");

	push (@hits, \@data);
	
    }
    
    $sth->finish;
    
    # now check the locus name - locus name is always upper case
    # however, we have to remember that a single locus name can
    # match more than one feature (eg. HXT12), so need to handle
    # this
    
    $sth = $dbh->prepare("SELECT LOCUS_NAME, l.LOCUS_NO, FEATURE_NO
                                    FROM CGM_DDB.LOCUS l, CGM_DDB.FEATURE f
                                    WHERE UPPER(LOCUS_NAME) LIKE ?
                                    AND l.LOCUS_NO = f.LOCUS_NO (+)");
    
    $sth->execute($query);
    
    while (my @data = $sth->fetchrow_array){

	$seenL{$data[1]} = 1;

	next if ($seenF{$data[2]} && $data[0] eq $seenF{$data[2]}); # don't want in the table twice if orf is same as gene

	if ($data[2]){ # it's has a feature, so use that

	    $data[1] = $data[2];
	    $data[2] = "featureNo";

	}else{

	    $data[2] = "locusNo";

	}
	
	push (@hits, \@data); # this is locus name
	
    }
    
    $sth->finish;

    # for the aliases want to get either associated feature no, or locus number
    # so that the resulting link is unambiguous

    # as it is the case that an alias may map to many loci
    
    $sth = $dbh->prepare("SELECT ALIAS_NAME, FEATURE_NO
                                 FROM CGM_DDB.alias 
                                 WHERE UPPER(ALIAS_NAME) LIKE ?
                                 AND FEATURE_NO IS NOT NULL");
    
    $sth->execute($query);
    
    while (my @data = $sth->fetchrow_array){

	next if ($seenF{$data[1]});
	
	push (@data, "featureNo");

	push (@hits, \@data);
	
    }
    
    $sth->finish;

    $sth = $dbh->prepare("SELECT ALIAS_NAME, LOCUS_NO
                                 FROM CGM_DDB.alias a, CGM_DDB.locus_alias la
                                 WHERE UPPER(ALIAS_NAME) LIKE ?
                                 AND a.ALIAS_NO = la.ALIAS_NO");
    
    $sth->execute($query);
    
    while (my @data = $sth->fetchrow_array){
	
	next if ($seenL{$data[1]});

	push (@data, "locusNo");

	push (@hits, \@data);
	
    }
    
    $sth->finish;
    
    $dbh->disconnect;

    $self->wildResults("hits"=>\@hits);

    

}

##############################################################################################
sub wildResults{
##############################################################################################
# This subroutine prints out the results of a wild card search

    my ($self, @args) = @_;

    $self->pageTop if (!$self->{'_printedHeader'});

    $self->printWildTable(@args);

}

###########################################################################################
sub printWildTable{
###########################################################################################
# This subroutine returns a table of the results from a wild card search
# want to have the name in the first column, systematic name in the second, aliases in the third
# chromosome + coordinate in the next, function in the last

    my ($self, %args) = @_;

    my $hitsRef = $args{'hits'};
    my $string = "<B style=\"color:black;background-color:#ffff66\">";

    my ($hit, $gene, $orf, $alias, $pos, $match, $function, $orig, $functionRef, $object);

    my $show;

    my $query = $self->{'_query'};
    $query =~ s/\*//g; # get rid of the wild cards when doing the regex

#
# escape the parenthesis, tRNAs have parenthesis in their name
#
    $query =~ s#\(#\\\(#g;
    $query =~ s#\)#\\\)#g;

    my $hitmax = 100;

    if (@{$hitsRef}){

	my $count = @{$hitsRef};

	my $summaryLine = "";	
	if ($count > $hitmax) {
	    $summaryLine = "The query matches a large number of loci in the database.  Tables are available from the FTP site \<<a href=\"ftp://genome-ftp.stanford.edu/Dictyostelium/data_download/\">ftp://genome-ftp.stanford.edu/Dictyostelium/data_download/</a>\> that provide information from dictyBase.  Check the <a href=\"ftp://genome-ftp.stanford.edu/Dictyostelium/data_download/README\">README</a> file for a description of the available files.  In particular, check out the TAB delimited <a href=\"ftp://genome-ftp.stanford.edu/Dictyostelium/data_download/chromosomal_feature/chromosomal_feature.tab\">chromosomal_feature.tab</a> and its <a href=\"ftp://genome-ftp.stanford.edu/Dictyostelium/data_download/chromosomal_feature/README\">README</a> for a table of all annotated <i>S. discoideum</i> genomic features.  Hint: 1) Press the Control key and then click on the link to download the file to your computer's disk.  2) Change the extension from .tab to .xls to open with MS Excel.\n";
	    $summaryLine .= "<p>Because your query matches so many names, an abbreviated table of the hits is provided below.  The hits below are matches to standard gene names, ORF names, or aliases.  Click on a name to go to that gene's locus page, or explore the files on the FTP site described above to find more information.<p>\n";

	    print STDERR "LocusPage.pm: query = \"$query\" had $count matches, limited to summary page\n";
	}

        $summaryLine .= "Your query ".font({-color=>'#FF0000'},$self->{'_query'})." returned ".font({-color=>'#FF0000'},$count)." hits to the following gene names:";

	print h4($summaryLine);

	my @list;
	my $functionCount;
	my $aliasCount;
	foreach $hit (sort by_Dictyostelium @{$hitsRef}){
	    if ($count <= $hitmax) {

		$object = dictyBaseObject->new($$hit[2]=>$$hit[1],
					 database=>$self->{'_database'});

		$gene = $object->gene;
		$orf  = $object->orf;
		$alias = $object->alias;
		if ($alias) { $aliasCount++; }
		
		$orf=~s/($query)/$string$1<\/B>/i;
		$orf ||= "&nbsp;";
		$gene =~s/($query)/$string$1<\/B>/i;
		$gene ||= "&nbsp;";
		$alias=~s/($query)/$string$1<\/B>/i;
		$alias ||="&nbsp;";
		$pos = $object->positionalInfo || "&nbsp;";
		($functionRef) = $object->molFunction;
		if ($$functionRef[0]) {
		    $functionCount++;
		}
		$function = $$functionRef[0] || "&nbsp;";

		if ($object->primarydictyBaseID){

		    $$hit[0] = a({-href=>url."?dictyBaseid=".$object->primarydictyBaseID},
				 $$hit[0]);

		}else{

		    $$hit[0] = a({-href=>url."?featureNo=".$object->featureNo},
				 $$hit[0]);

		}
	    
	    }

	    push(@list, $$hit[0]."\t".$gene."\t".$orf."\t".$alias."\t".$pos."\t".$function);
	    
	}
	
	if ($count <= $hitmax) {
	    my $rows = th("Match").
		th("Gene Name").
		    th("Systematic Name");
	    if ($aliasCount) {
		$rows .= th("Alias(es)");
	    }
	    $rows .= th("Position Info");	
	    if ($functionCount) {
		$rows .= th("Function");
	    }
	    $rows = Tr($rows);
	    foreach my $list (@list) {
		my ($hit, $gene, $orf, $alias, $pos, $func) = split(/\t/, $list);
		my $row = td(b($hit)).td($gene).td($orf);
		if ($aliasCount) { $row .= td($alias); }
		$row .= td($pos);
		if ($functionCount) { $row .= td($func); }
		$rows .= Tr($row);
	    }
	    print table({-align=>'center',
			 -border=>3},
			$rows), "\n";
	} else {
	    my $rows_count = 1;
	    my $row = "";
	    my $rows = "";
	    foreach my $genename (@list) {

		$genename =~ s/\t//g;
		$row .= td(a({-href=>url."?locus=$genename"},$genename));
		if (($rows_count++ % 5 == 0) && ($rows_count != 0)) {
		    $rows .= Tr($row), "\n";
		    $row = "";
		}
	    }
	    $rows .= Tr($row);
	    print table({-align=>'center',
			 -border=>3},
			$rows), "\n";
	}
    } else {
	
	print center(h2("Your search for ".$self->{'_query'}." did not return any hits."),
		     h2("Please try again."),
		     $self->searchFormTable($self->{'_query'}));
	
    }
    
}

###########################################################################################
sub by_Dictyostelium{
###########################################################################################
# used for sorting of Dictyostelium ORFs/genes

    my ($worda1, $worda2, $wordb1, $wordb2, $number1, $number2);

    if ($$a[0]=~/(\D+)(\d*)(.*)/){

	$worda1=uc($1);

	$number1=$2;

	$worda2=uc($3);

    }

    if ($$b[0]=~/(\D+)(\d*)(.*)/){

	$wordb1=uc($1);

	$number2=$2;

	$wordb2=uc($3);

    }

    return $worda1 cmp $wordb1 || $number1 <=> $number2 || $worda2 cmp $wordb2;

}

############################################################################################
sub printSearchForm{
############################################################################################
# This method prints out a simple search form

    my $self = shift;

    $self->{'_title'} = "Search dictyBase";

    $self->pageTop;

    print center($self->searchFormTable), br, br;

}

#####################################################################
sub searchFormTable{
#####################################################################
# This subroutine returns a table that encompasses the search form

    my ($self, $default) = @_;

    return table({-border=>3,
		  -cellpadding=>4,
		  -cellspacing=>4},
		 
		 Tr({-align=>'LEFT'},
		    [
		     td({-bgcolor=>"#b7d8e4",
			 -width=>300},
			"The search is case insensitive.".br.
			"Include the ".b("wildcard character").
			"(*) at the end or beginning of the item name for a broader search.".br.
			"Wild-card searches do not work for dictyBaseID's.".br.
			table({-border=>0},
			      Tr({align=>'LEFT'},
				 [
				  td(start_form,
				     "Search term : ").
				  td(textfield(-name=>'locus',
					       -size=>16,
					       -default=>$default)),
				  td("&nbsp;").td(submit, reset, end_form)
				  ]))
			)
		     ]));

}

}


1; # to keep require happy

