=head1 LICENSE

  Copyright (c) 1999-2012 The European Bioinformatics Institute and
  Genome Research Limited.  All rights reserved.

  This software is distributed under a modified Apache license.
  For license details, please see

    http://www.ensembl.org/info/about/code_licence.html

=head1 CONTACT

  Please email comments or questions to the public Ensembl
  developers list at <dev@ensembl.org>.

  Questions may also be sent to the Ensembl help desk at
  <helpdesk@ensembl.org>.

=cut

=head1 NAME

Bio::EnsEMBL::Utils::SchemaConversion - Utility module for Vega schema conversion script

=head1 SYNOPSIS

  my $serverroot = '/path/to/ensembl';
  my $conversion =
    Bio::EnsEMBL::Utils::ConversionSupport->new($serverroot);

  # parse common options
  $conversion->conv_usage->parse_common_options;

  # convert from schema 19 to 20+
  $conversion->do_conversion()

=head1 DESCRIPTION

This module is a helper module for database conversion, for
both vega-vega and ensembl-vega schemas. It provides a wrapper
around SeqStoreConverter::BasicConverter and the species specific
methods therein. Also provides access to helper functions in
Bio::EnsEMBL::Utils::ConversionSupport

=head1 METHODS

=cut

package Bio::EnsEMBL::Utils::SchemaConversion;

use  Bio::EnsEMBL::Utils::ConversionSupport;
use strict;
use warnings;

use Data::Dumper;

=head2 new

  Example     : $conversion->Bio::EnsEMBL::Utils::SchemaConversion->new($serverroot);
  Description : Constructor, including an instance of a Bio::EnsEMBL::Utils::ConversionSupport 
                object. Parses input file and checks input with user
  Return type : Bio::EnsEMBL::Utils::SchemaConversion object 
  Exceptions  : thrown if $Siteroot not passed over
  Caller      : $Siteroot/utils/vega_schema_conversion

=cut

sub new {
    my $class = shift;
    my $support = shift;
    my $self = {};
    bless ($self,$class);
    $self->{config} =  Bio::EnsEMBL::Utils::ConversionSupport->new($support);
    $self->conv_support->parse_common_options;
	$self->conv_support->parse_extra_options('do_vega_sc=s',
											 'do_ens_sc=s',
											 'source_db=s',
											 'core_sql=s',
											 'vega_sql=s',
											 'patch_sql=s',
											 'force=s',
											 'do_features=s');

	#check input and show help
	$self->conv_usage() if ($self->conv_support->param("help"));
	$self->conv_usage("configuration file needed") unless ($self->conv_support->param("conffile"));
	$self->conv_usage("password for database access needed") unless ($self->conv_support->param("pass"));
	$self->conv_usage("can only do conversion to ensembl OR Vega, not both") if ($self->conv_support->param('do_vega_sc') && $self->conv_support->param('do_ens_sc'));
	$self->conv_usage("You need to do vega->veg or ensembl->vega conversion") unless ($self->conv_support->param('do_vega_sc') || $self->conv_support->param('do_ens_sc'));
	
	# ask user to confirm parameters to proceed
	$self->conv_support->allowed_params('conffile',
										'do_vega_sc',
										'do_ens_sc',
										'host',
										'port',
										'user',
										'pass',
										'source_db',
										'dbname',
										'force',
										'do_features',
										'verbose',
										'logpath',
										'logfile',
										'core_sql',
										'vega_sql',
										'patch_sql');										
	$self->conv_support->confirm_params;

    return $self;
}

=head2 conv_support

  Example     : $conversion->conv_support; 
  Description : Provides access to Bio::EnsEMBL::Utils::ConversionSupport methods
  Return type : Bio::EnsEMBL::Utils::ConversionSuppor object
  Exceptions  : none
  Caller      : general

=cut

sub conv_support {
    my $self = shift;
    return $self->{config};
}

=head2 conv_obj

  Example     : $conversion->conv_obj; 
  Description : Provides access to SeqStoreConverter::BasicConverter methods
  Return type : SeqStoreConverter::BasicConverter object
  Exceptions  : none
  Caller      : general

=cut

sub conv_obj {
    my $self = shift;
    return $self->{'converter_object'};
}


=head2 species_alias

  Example     : $self->species_alias
  Description : examines name of source database to determine which conversion module to use
  Return type : string
  Exceptions  : die if wrong species name used
  Caller      : $self

=cut

sub species_alias {
    my $self=shift;
    my $name = shift;
    return 'CanisFamiliaris' if $name =~ /canis/;
    return 'HomoSapiens' if $name =~ /homo/;
    return 'MusMusculus' if $name =~ /mus/;
    return 'DanioRerio' if $name =~ /danio/;
	##hack - should use own modules
    return 'HomoSapiens' if $name =~ /sus/;
    die "invalid name of source database, please check configuration file";
}

=head2 choose_conversion_type

  Example     : $conversion->choose_conversion_type
  Description : compares conversion type (ensembl or vega) and species type with 
                available modules and chooses that to use for the conversion. Stores
                a converter object within the caller
  Return type : none
  Exceptions  : none
  Caller      : $Siteroot/utils/vega_schema_conversion

=cut

sub choose_conversion_type {
    my $self = shift;
    my $converter;
    my $species;

    $species = $self->species_alias($self->conv_support->param('source_db'));
    if ($self->conv_support->param('do_vega_sc')) {
        $species = "vega::".$species;
        eval "require SeqStoreConverter::$species";
        if($@) {
            warn("Could not require conversion module SeqStoreConverter::$species\ for vega conversion\n" .
                    "Using SeqStoreConverter::BasicConverter instead:\n$@");
            require SeqStoreConverter::BasicConverter;
            $species = "BasicConverter";
        }
        else {
            warn "Using conversion module SeqStoreConverter::$species for vega conversion\n";
        }
    }
    else {
        eval "require SeqStoreConverter::$species";
        if($@) {
            warn("Could not require conversion module SeqStoreConverter::$species for Ensembl conversion\n" .
                    "Using SeqStoreConverter::BasicConverter instead:\n$@");
            require SeqStoreConverter::BasicConverter;
            $species = "BasicConverter";
        }
        else {
            warn "Using conversion module SeqStoreConverter::$species for Ensembl conversion\n";
        }
        $self->conv_support->param('vega_sql',0);
    }
    $converter = "SeqStoreConverter::$species"->new
        ( $self->conv_support->param('user'), 
          $self->conv_support->param('pass'), 
          $self->conv_support->param('host').':'.$self->conv_support->param('port'), 
          $self->conv_support->param('source_db'), 
          $self->conv_support->param('dbname'), 
          $self->conv_support->param('core_sql'), 
          $self->conv_support->param('vega_sql'), 
          $self->conv_support->param('force'), 
          $self->conv_support->param('verbose'),
          '',
        );

    $self->{'converter_object'} = $converter;
}

=head2 do_conversion

  Example     : $conversion->do_conversion
  Description : does the database conversion 
  Return type : none
  Exceptions  : none
  Caller      : $Siteroot/utils/vega_schema_conversion

=cut


sub do_conversion {
    my $self= shift;
    $self->conv_obj->debug( "\n\n*** converting " . $self->conv_obj->source . " to " . 
            $self->conv_obj->target() . " ***");
    $self->conv_obj->transfer_meta();
    $self->conv_obj->create_coord_systems();
    $self->conv_obj->create_seq_regions();
    $self->conv_obj->create_assembly();
    $self->conv_obj->create_attribs();
    $self->conv_obj->set_top_level();
    $self->conv_obj->transfer_dna();
    $self->conv_obj->back_patch_schema();
    $self->conv_obj->transfer_genes();
    $self->conv_obj->transfer_prediction_transcripts();

    if ($self->conv_support->param('do_features')) {
        $self->conv_obj->transfer_features();
    }
#use this for both ensembl and vega for now,
#but might need changing when vega gets eg transcript modified dates
    $self->conv_obj->transfer_vega_stable_ids();
    $self->conv_obj->copy_other_tables(); 
    $self->conv_obj->copy_repeat_consensus(); 
    $self->conv_obj->create_meta_coord(); 
    if ($self->conv_support->param('do_vega_sc')) { 
        $self->conv_obj->copy_other_vega_tables(); 
        $self->conv_obj->update_clone_info();
        $self->conv_obj->remove_supercontigs(); 
        $self->conv_obj->copy_internal_clone_names(); 
        $self->conv_obj->copy_assembly_exception; 
    } 
}

=head2 make_schema_up_to_date

  Example     : $conversion->make_schema_up_to_date
  Description : patches schema to latest version
  Return type : none
  Exceptions  : none
  Caller      : $conversion

=cut

sub make_schema_up_to_date {
	my $self = shift;
	$self->conv_obj->debug ("\nPatching schema to latest version\n");
	my $user = $self->conv_obj->user;
	my $pass = $self->conv_obj->password;
	my $port = $self->conv_obj->port;
	my $host = $self->conv_obj->host;
	my $target = $self->conv_obj->target;
	my $patch_schema = $self->conv_support->param('patch_sql');
	my $cmd = "/usr/local/mysql/bin/mysql -u $user -p$pass -P $port -h $host $target < $patch_schema";
	system ($cmd);
}



=head2 conv_usage

  Example     : $conversion->conv_usage("message")
  Description : prints usage information and exits
  Return type : none
  Exceptions  : none
  Caller      : $Siteroot/utils/vega_schema_conversion

=cut

sub conv_usage {
	my $self = shift;
	my $msg = shift;

	print STDERR "\nMSG: $msg\n" if($msg);
	
	print STDERR <<EOF;

** Source and target databases must be on the same mysql instance

usage: ./conversion_densities.pl  <options>

options: --conf <conf_file>      configuration file (uses conf/Conversion.ini by default):

                                   fields:
                                      do_vega_sc (do vega conversion: 0 or 1)
                                      do_ens_sc (do ensembl conversion: 0 or 1)
                                      user (a mysql db user with read/write priveleges)
                                      host (eg ecs3f)
                                      port (eg 3310)
                                      source_db (schema 19 source database)
                                      dbname (schema 20+ target database)
                                      force (overwrite existing target database: 0 or 1)
                                      verbose (print out debug statements: 0 or 1)
                                      logpath (location of log file)
                                      do_features (transfer dna- and protein-align features, for debugging: 0 or 1)
                                      core_sql (location of ensembl schema creation script: ensembl/sql/table.sql)
                                      vega_sql (location of creation script for additional vega tables: ensembl/sql/vega_specific_tables.sql)
                                      patch_sql (location of schema patching script: ensembl/sql/vega_latest_schema.sql)
 
         --log                   name of log_file
         --help                  display this message

EOF
  exit;

}

1;



