package Pair;
use strict;
use warnings;
use Carp;

use overload
    '""' => \&string,
    '+' => \&add,
    '-' => \&subtract;

#constructor

sub new {
    my $class = shift;
    croak "Only 2 arguments to $class constructor allowed" unless @_ == 2;
    my ($one, $two) = @_;
    my $obj = { one => $one, two => $two };
    bless $obj, $class;

}

#accessors

#These will serve as both gets and sets.  If there are any arguments
#passed in, it will be shift()'ed off the argument list, and the
#parameter will be set to that argument.  In either case the 
#paramter will be returned.

sub first {
    my $obj = shift;
    $obj->{one} = shift if @_;
    return $obj->{one};
}

sub second {
    my $obj = shift;
    $obj->{two} = shift if @_;
    return $obj->{two};
}

#stringification subroutine - elemements in parens, seperated by comma

sub string {
    my $obj = shift;
    return "($obj->{one}, $obj->{two})";
}

#addition overloading
#if a Pair is added to another pair, the corresponding elements are summed
#if a Pair is added to an integer, the integer is added to each element.


sub add {
    my $obj = shift;
    my $arg = shift;
    my $class = ref $obj;
    if (ref $arg and $arg->isa($class)){
	#if second argument is another Pair:
        return $class->new($obj->{one} + $arg->{one}, $obj->{two} + $arg->{two});
    } else {
	#second argument is not a Pair
	return $class->new($obj->{one} + $arg, $obj->{two} + $arg);
    }
}


#subtraction overloading
#this is more complicated.  If a Pair is subtracted from another pair, the
#corresponding elements are subtracted.
#If an integer is subtracted from a Pair, that integer is subtracted from
#each element of the Pair.
#if a Pair is subtracted from an integer, the resulting Pair's elements
#are the integer minus the first element, and the integer minus the second
#element

sub subtract {
    my ($obj, $arg, $swap) = @_;
    my $class = ref $obj;
    my ($new_one, $new_two);
    if (ref $arg and $arg->isa($class)){
	#if second argument is another Pair:
	$new_one = $obj->{one} - $arg->{one};
        $new_two = $obj->{two} - $arg->{two};
    } else {
	#second argument is an integer (we're assuming)
	if (!$swap){
	    #arguments were not swapped.  It's Pair - Integer
	    $new_one = $obj->{one} - $arg;
            $new_two = $obj->{two} - $arg;
	} else {
	    #arguments were swapped.  It's Integer - Pair
	    $new_one = $arg - $obj->{one};
            $new_two = $arg - $obj->{two};
	}
    }
    return $class->new($new_one, $new_two);
}


1;
