#!/usr/local/bin/perl -w

# $Id: search_gene,v 1.15 2007/04/04 18:34:43 liya Exp $

=head1 NAME

search_gene

=head1 DESCRIPTION

This script is for searching and display genes

=cut

# -------------------------------------------------------

use strict;
use Apache::Request;
use Template;
use Tie::IxHash;

use Gramene::Page;
use Gramene::Utils 'commify';
use Gramene::Config;
use Gramene::Gene::GeneDB;

use constant DETAIL_TEMPLATE  => 'gene_detail.tmpl';
use constant DISPLAY_TEMPLATE => 'gene_display.tmpl';
use constant ERROR_TEMPLATE   => 'gene_error.tmpl';
use constant SEARCH_TEMPLATE  => 'gene_search.tmpl';
use constant PAGE_SIZE        => 25;
use constant MAX_PAGES        => 10;

my $apr         = Apache::Request->new( Apache->request );
my $page        = Gramene::Page->new($apr);
my $config      = Gramene::Config->new;
my $gene_config = $config->get('genes');

my ( $template, $html, $db, $pager );

my %args = $apr->args;

# for gramene quick search
my $table_only = $apr->param('table');

# field with 1 to 1 mapping to gene 
my $gene_field_tags = [
    ['name' , 'Gene Symbol & Name' ],
    ['accession', 'Gene Accession'],
    ['chromosome', 'Chromosome No.']
];

# gene_gene and gene_gene_synonym table fields
my %search_gene_fields = map { $_->[0] => 1 }  @$gene_field_tags;

my $term_type_field_tags = [
    ['to', 'TO:Trait'],
    ['anatomy' , 'PO:Plant Structure'],
    ['po_growth_stage' , 'PO:Plant Growth Stage'],
    ['growth_stage' , 'GRO:Cereal Plant Growth Stage'],
    ['go_component' , 'GO:Cellular Component'],
    ['go_function' , 'GO:Molecular Function'],
    ['go_process' , 'GO:Biological Process'],
    ['eo' , 'EO:Environment']
];


# search field maps to term_type in database
my %search_term_fields = (
    'to' => 'Trait',
    'anatomy' =>'Plant Structure',
    'po_growth_stage' => 'Plant Growth and Development Stage',
    'growth_stage' => 'Cereal Plant Growth Stage',
    'go_component' => 'Cellular Component',
    'go_function' => 'Molecular Function',
    'go_process' =>  'Biological Process',
    'eo' => 'Enviroment'
);

my @ordered_term_types; # display ontology type in order in gene page
foreach my $term_type_field (@$term_type_field_tags){
    my $term_type = $search_term_fields{$term_type_field->[0]};
    push @ordered_term_types, $term_type;
}



my $xref_field_tags = [
    ['xref_gene', 'GenBank Accession'],
    ['xref_protein', 'Gramene Protein Accession']
];

# search field maps to xref_dbname in database
my %search_xref_fields = (
    'xref_gene' => 'GenBank Nucleotide',
    'xref_protein' => 'Gramene Protein'
);

my $search_field_tags = [
    @$gene_field_tags,
    @$term_type_field_tags,
    @$xref_field_tags
];

	
eval {

    $template = Template->new(
        {
            INCLUDE_PATH => $gene_config->{'template_dir'},
            PRE_CHOMP    => 1,
            POST_CHOMP   => 1,
            TRIM         => 1,
            FILTERS      => { commify => \&Gramene::Utils::commify }

        }
    );

    $db = Gramene::Gene::GeneDB->new();
    $db->connect_to_db();

    my $all_species = $db->get_all_species();
    my $all_gene_types = $db->get_all_gene_types();
    
    # for gene search
    my $query_search = $apr->param('query_submit');
    my $query        = $apr->param('query');
    my $order_by     = $apr->param('order_by') || 'symbol';
    my $page_no      = $apr->param('page_no') || 1;

    my ($search_field, $species, $gene_type_id, $has_phenotype );

    # for gene gene detail display
    my $acc = $apr->param('acc');
    my $gene_id = $apr->param('id');

    my @gene_objs;    # for candidate genes by search

    my $gene_obj;    # for gene detail

    if (defined $query) {    # search
        $search_field = $apr->param('search_field');
        $species      = $apr->param('species');
	$gene_type_id = $apr->param('gene_type_id');
	$has_phenotype= $apr->param('has_phenotype');   
	
        my $term_acc = $apr->param('term_acc');

        $query =~ s/^\s+|\s+$//g;


	if($search_field){
	    if ( $search_gene_fields{$search_field} ) {
		@gene_objs = $db->get_genes_by_gene_fields( $query, $search_field, $species, $gene_type_id, $has_phenotype, $order_by );
		    
	    }elsif ($search_xref_fields{$search_field} ) {
		@gene_objs = $db->get_genes_by_xref( $query, $search_xref_fields{$search_field}, $species,$gene_type_id, $has_phenotype, $order_by);
	    }elsif($search_term_fields{$search_field}){
		@gene_objs = $db->get_genes_by_ontology_term_name($query, $search_term_fields{$search_field}, $species, $gene_type_id, $has_phenotype, $order_by );
	    }

	}else{ # search all fields
	    if($apr->param('core')){ # for gramene quick search
		@gene_objs = $db->get_genes_by_core_fields( $query, $species, $gene_type_id, $has_phenotype, $order_by );
	    }else{
		@gene_objs = $db->get_genes_by_all_fields( $query, $species,$gene_type_id, $has_phenotype, $order_by );
	    }
	}

        if (@gene_objs) {
            $pager = Data::Pageset->new(
                {
                    total_entries    => scalar @gene_objs,
                    entries_per_page => PAGE_SIZE,
                    current_page     => $page_no,
                    pages_per_set    => MAX_PAGES,
                }
            );
            @gene_objs = $pager->splice( \@gene_objs );
        }

    }

    # ---------------------------------------------------------------
    # gene gene detail search
    #
    if ($acc || $gene_id ) {
        $gene_id = $db->get_gene_id($acc) if $acc;

        if ($gene_id) {
            $gene_obj = $db->get_gene_general_info($gene_id);

            #an array of synonyms
            $gene_obj->{'synonyms'} = $db->get_gene_synonyms($gene_id);

	    #an array of hashes
	    $gene_obj->{'maps'} = $db->get_gene_map_position($gene_id);

	    my $obj_type = 'gene';

	    $gene_obj->{'images'} = $db->get_object_images($obj_type, $gene_id); 

	    $gene_obj->{'alleles'} = $db->get_gene_related_alleles($gene_id);
	    
	    $gene_obj->{'germplasms'} = $db->get_related_germplasms($obj_type,$gene_id);

	    # a hash of sequence associations 
	    my %seq_xrefs;
	    my %seq_xref_lables = (
		'Nucleotide (DNA)' => [
					'GenBank Nucleotide',
					'Rice Ensembl Gene',
				      ],
		'Protein' => [
				'Gramene Protein'
			    ]
	    );

	    foreach my $lable (keys %seq_xref_lables){
		my $xdbs = $seq_xref_lables{$lable};
		foreach my $xref_db (@$xdbs){
		    my @xrefs = $db->get_gene_xrefs_by_xdb(
			$obj_type, $gene_id, $xref_db
		    );
		    if(@xrefs){
			$seq_xrefs{$lable}->{$xref_db} = \@xrefs;
		    }
		}
	    }


	    $gene_obj->{'sequence_association'} = \%seq_xrefs;

	    # a temporal solution for gene interaction,maybe need update
	    # schema 
	    my $interaction_xref='TIGR rice gene model';
	    my @interactive_genes = $db->get_gene_xrefs_by_xdb($obj_type, $gene_id,$interaction_xref);
	    if(scalar(@interactive_genes)>=1){
		$gene_obj->{'interactions'}->{$interaction_xref} = \@interactive_genes;
	    }


	    # new interaction desing
	    #
	    $gene_obj->{'gene_interactions'} = $db->get_gene_interactions($gene_id);

            #a hash with term_type as key and array of term objs as value
            $gene_obj->{'ontology'} = $db->get_ontology_association($obj_type,$gene_id); 

	    # dbxrefs to other databases
	    my @dbxref_dbs = (
		'Oryzabase',
		'E.C. Number(s)',
		'MaizeGDB',
		'miRBase',
	    );
	    
	    my $dbxrefs;
	    foreach my $dbxref_db (@dbxref_dbs){
		my @xrefs = $db->get_gene_xrefs_by_xdb( $obj_type, $gene_id, $dbxref_db);
		if(@xrefs){
		    $dbxrefs->{$dbxref_db} = \@xrefs;
		}
	    }
	    $gene_obj->{'dbxrefs'} = $dbxrefs;
	    
	    
	    my $xref_db = 'Gramene Literature';
            $gene_obj->{'references'} = $db->get_related_references($obj_type,$gene_id,$xref_db);

        }
    }

    #
    # template processing
    #
    if ($gene_obj) {    # gene gene detail display

        $template->process(
            DETAIL_TEMPLATE,
            {
                gramene_page => $page,
                apr          => $apr,
		search_fields => $search_field_tags,
                species      => $all_species,
		gene_types   => $all_gene_types,
                gene         => $gene_obj,
		ordered_term_types => \@ordered_term_types,
                title        => "Summary for Gene &quot;"
                  . $gene_obj->{'accession'}
                  . "&quot;"
            },
            \$html
          )
          or $html = $template->error;

    }elsif (defined $query) {    # gene search results display

        $template->process(
            DISPLAY_TEMPLATE,
            {
                gramene_page => $page,
                apr          => $apr,
		search_fields => $search_field_tags,
                species      => $all_species,
		gene_types   => $all_gene_types,
                genes        => \@gene_objs,
                pager        => $pager,
                title        => "Search for Gene &quot;$query&quot;" . " by $search_field",
		table_only   => $table_only
            },
            \$html
          )
          or $html = $template->error;

    }else {    # search interface

        $template->process(
            SEARCH_TEMPLATE,
            {
                gramene_page => $page,
                apr          => $apr,
		search_fields => $search_field_tags,
                species      => $all_species,
		gene_types   => $all_gene_types,
                title        => "Gene Search",
                search_page  => "1"
            },
            \$html
          )
          or $html = $template->error;
    }

};

if ( my $err = $@ ) {
    if ($template) {
        $template->process(
            ERROR_TEMPLATE,
            {
                gramene_page  => $page,
                error_message => $err,
                table_only    => $table_only
            },
            \$html
          )
          or $html = $template->error;
    }else {
        $html = "Error: $err";
    }
}

$apr->content_type('text/html');
$apr->send_http_header;
$apr->print($html);

# ------------------------------------------------------------

=pod

=head1 AUTHORS

Liya Ren E<lt>ren@cshl.eduE<gt>

=cut

