# Copyright (c) 2006-2008 Stanford University
# This file is part of Disperse.
#
# Disperse is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
#
# Disperse is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with Disperse; if not, write to the Free Software
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
package Bio::Disperse::Utils;

use strict;

# input:
#	coords: Array of arrays containing [start coord, end coord]
#	margin: Threshold distance between two coordinates to merge
sub merge_coords
{

	my ($coords, $margin) = @_;
	if (!defined($margin))
	{
		$margin = 0;
	}
	
	my $sorted_coords = [sort {$a->[0] <=> $b->[0]} @$coords];
	my @merged_coords = ();
	
	my $i = 0;
	while ($i < @$sorted_coords)
	{
		my $start_coord = $sorted_coords->[$i]->[0];
		my $end_coord = $sorted_coords->[$i]->[1];
		#print $start_coord . ", " . $end_coord . "\n";
		while ($i+1 < @$sorted_coords  && $sorted_coords->[$i+1]->[0] <= $end_coord + $margin + 1)
		{
			my $next_start_coord = $sorted_coords->[$i+1]->[0];
			my $next_end_coord = $sorted_coords->[$i+1]->[1];
			$end_coord = $end_coord > $next_end_coord ? $end_coord : $next_end_coord;
			$i++;
		}
		push @merged_coords, [$start_coord, $end_coord];
		$i++;
	}
	return \@merged_coords;
}


# input:
#	coords: Array of hashes containing {'coords' => [start coord, end coord], 'ids'=>[coordinate id] }
#	margin: Threshold distance between two coordinates to merge
sub track_merged_coords
{

	my ($coords, $margin) = @_;
	if (!defined($margin))
	{
		$margin = 0;
	}
	
	my $sorted_coords = [sort {$a->{'coords'}->[0] <=> $b->{'coords'}->[0]} @$coords];
	my @merged_coords = ();
	
	my $i = 0;
	while ($i < @$sorted_coords)
	{
		my $coord_hash = $sorted_coords->[$i];
		my $start_coord = $coord_hash->{'coords'}->[0];
		my $end_coord = $coord_hash->{'coords'}->[1];
		my $id_ary = [@{$coord_hash->{'ids'}}];
		#print $start_coord . ", " . $end_coord . "\n";
		while ($i+1 < @$sorted_coords  && $sorted_coords->[$i+1]->{'coords'}->[0] <= $end_coord + $margin + 1)
		{
			my $next_coord_hash = $sorted_coords->[$i+1];
			my $next_start_coord = $next_coord_hash->{'coords'}->[0];
			my $next_end_coord = $next_coord_hash->{'coords'}->[1];
			$end_coord = $end_coord > $next_end_coord ? $end_coord : $next_end_coord;
			push @$id_ary, @{$next_coord_hash->{'ids'}};
			$i++;
		}
		my $merged_coord_hash = { 'ids'=> $id_ary, 'coords'=> [$start_coord, $end_coord] };
		push @merged_coords, $merged_coord_hash;
		$i++;
	}
	return \@merged_coords;
}

sub chr_num_from_g_accession
{
	my ($g_accession) = @_;
	$g_accession =~ /NC_(\d+)\./;
	return int($1);
}

# Takes in a config file
sub parse_config
{
	my ($config_file, $logger) = @_;
	
	# Create config file filehandle
	my $config_fh = new FileHandle($config_file);
	if (!defined($config_fh))
	{
		if ($logger) {
			$logger->error( "Could not open file: $config_file!");
		}
    	print "Could not open file: $config_file!\n";		
		exit(1);
	}
		
	# Create hash for config key and value pairs using config file
	my $config_hash = {};
	while (<$config_fh>) {
		chomp;
		if (/(.*)=(.*)/) {
			$config_hash->{$1} = $2;
		}
	}
	
	$config_fh->close;
	
	return $config_hash;

}

# Return an absolute file name for a config entry.
# If config entry is absolute, return it.
# If relative, resolve it using the supplied file. 
sub get_abs_config_entry {
  	my ($entry,$abs_base) = @_;
	if (File::Spec->file_name_is_absolute($entry)) {
  		return $entry;
  	}  	
	my ($base_vol,$base_dir,$base_file) = File::Spec->splitpath($abs_base);
	my ($entry_vol,$entry_dir,$entry_file) = File::Spec->splitpath($entry);
	my $catdir = File::Spec->catdir($base_dir,$entry_dir);	
	return File::Spec->catpath($base_vol,$catdir,$entry_file);    
}

1;