# -*-Perl-*- 
#######################################################################
# This software has been created by Genome Research Limited (GRL).    # 
# GRL hereby grants permission to use, copy, modify and distribute    # 
# this software and its documentation for non-commercial purposes     # 
# without fee at the user's own risk on the basis set out below.      #
# GRL neither undertakes nor accepts any duty whether contractual or  # 
# otherwise in connection with the software, its use or the use of    # 
# any derivative, and makes no representations or warranties, express #
# or implied, concerning the software, its suitability, fitness for   #
# a particular purpose or non-infringement.                           #
# In no event shall the authors of the software or GRL be responsible # 
# or liable for any loss or damage whatsoever arising in any way      # 
# directly or indirectly out of the use of this software or its       # 
# derivatives, even if advised of the possibility of such damage.     #
# Our software can be freely distributed under the conditions set out # 
# above, and must contain this copyright notice.                      #
#######################################################################
# 
# $Id: Cover.pm,v 1.6 1997/06/24 12:11:51 dn1 Exp $ 
# 
# $Log: Cover.pm,v $
# Revision 1.6  1997/06/24  12:11:51  dn1
# Rewritten.
#
# Revision 1.5  1997/06/10  08:21:39  sd
# Moved copyright.
#
# Revision 1.4  1997/04/24  09:20:19  dn1
# Added Copyyright
#
# Revision 1.3  1996/04/04  16:08:37  dmh
# Fixed councoverToCover to handle empty arrays
#
# Revision 1.2  1996/03/21  10:17:56  dmh
# Some cosmetic changes
#
#
#
#

package Cover;



############################################################
# $new = Cover->new()
#
# Create a new object instance
#
############################################################
sub new {
    my($this) = shift;

    my $self = {
	"min"  => 0,
	"max"  => 0,
	"data" => [],
    };

    ($self->{"min"},$self->{"max"}) = @_;
    if ($self->{"min"} > $self->{"max"}) {
	($self->{"min"} , $self->{"max"}) = ( $self->{"max"} > $self->{"min"});
    } 
    
    $self->{"data"}->[0] = [$self->{"min"},$self->{"max"}];

    bless $self;
    $self;
}


############################################################
#
# Method Cover->set()
#
# Set the value of a instance variable or variables.
#
############################################################

sub set {
    my($self) = shift;
    local($key,$value);

    while($#_>=0) {
        ($key,$value) = (shift,shift);
	if ($key eq $chromosome) { $value =~ s/^Chr_//g; }
        $self->{$key} = $value;
    }

    $self;
}


############################################################
#
# Method Cover->get()
#
# Return the current value of a instance variable.
#
############################################################

sub get {
    my($self,$key) = @_;

    $self->{$key};
}




############################################################
# Cover->copy($cover_instance)
#
# Create a new object instance
#
############################################################
sub copy{
    my($other) = shift;

    my $self = {
	"min"  => 0,
	"max"  => 0,
	"data" => [],
    };

    $self->{"min"} = $other->{"min"};
    $self->{"max"} = $other->{"max"};

    foreach ( @{$other->{"data"}} ) {
	push(@{$self->{"data"}},[@{$_}]);
    }


    bless $self;
    $self;
}



############################################################
# Cover->dump();
#
# Dumps out a coverage array to STDERR
#
############################################################

sub dump {

    my($self) = @_;
    my $i;

    warn $#{$self->{"data"}}+1," uncovered regions\n";

    for ($i = 0; $i <= $#{$self->{"data"}}; $i++) {
	 warn $self->{"data"}->[$i]->[0], "->", $self->{"data"}->[$i]->[1], "\n";
    }

    $self;
}



############################################################
# Cover->cover($from, $to);
#
# Mask out region $from..$to from array.
# Function: Subtract
#
############################################################
sub cover {

    my ($self, $c1 , $c2 ) = @_;
    my $i;

    if ($c1 > $c2) { ($c1, $c2) = ($c2, $c1); }

    for ($i = 0; $i <= $#{$self->{"data"}}; $i++) {
	# Does $c1..$c2 cover $self->{"data"}->[$i]->[0]..$self->{"data"}->[$i]->[1] ???
	# Consider all 6 actions
	if ($c2 < $self->{"data"}->[$i]->[0]) {
	    last;
	} elsif ($c1 <= $self->{"data"}->[$i]->[0] && $c2 < $self->{"data"}->[$i]->[1]) {
	    $self->{"data"}->[$i]->[0] = $c2+1;
	} elsif ($c1 <= $self->{"data"}->[$i]->[0]) {
	    splice(@{$self->{"data"}},$i,1); $i--;
	} elsif ($c2 < $self->{"data"}->[$i]->[1]) {
	    splice(@{$self->{"data"}},$i,0,[$self->{"data"}->[$i]->[0],$self->{"data"}->[$i]->[1]]);
	    $self->{"data"}->[$i]->[1] = $c1-1;
	    $i++;
	    $self->{"data"}->[$i]->[0] = $c2+1;
	} elsif ($c1 <= $self->{"data"}[$i]->[1]) {
	    $self->{"data"}->[$i]->[1] = $c1-1;
	} else {
	    # no action
	}
    }

    $self;
}

#########################################################
# Cover->complement();
#
# Function: Negate
# 
#########################################################
sub complement {

    my ($self)=@_;
    my ($i);

    if ($#{$self->{"data"}} == -1) {
	$self->{"data"} = [[$self->{"min"}, $self->{"max"}]];
	return $self;
    }

    my $newdata=[];

    if ($self->{"data"}->[0]->[0] > $self->{"min"}) {
	push(@{$newdata},[$self->{"min"},$self->{"data"}->[0]->[0]-1]);
    }
    
    for($i=0 ;$i< $#{$self->{"data"}} ; $i++) {
	push(@{$newdata},[$self->{"data"}->[$i]->[1]+1,$self->{"data"}->[$i+1]->[0]-1]);
    }

    if ($self->{"data"}->[$i]->[1] < $self->{"max"}) {
	push(@{$newdata},[$self->{"data"}->[$i]->[1]+1,$self->{"max"}]);
    }

    $self->{"data"} = $newdata;

    $self;
}

sub exclude {
    my ($self,$other) = @_;
    my ($i);
    my ($otherdata) = $other->get("data");


    for($i=0;$i<=$#{$otherdata};$i++) {
	$self->cover($otherdata->[$i]->[0],$otherdata->[$i]->[1]);
    }

    $self;
}




1;
