#include "Rational.hpp"

// note: the Rational:: in front of the function name indicates it's a member function --
// a member of the Rational class
//Rational::Rational()
//{
//	mNumerator = 0;
//	mDenominator = 1;
//}

// constructors get called implicitly when an object is instantiated
Rational::Rational(int newNumerator, int newDenominator)
{
	mNumerator = newNumerator;
	if (newDenominator == 0) // validate the denominator
	{
		mDenominator = 1;
	}
	else
	{
		mDenominator = newDenominator;
	}
}

// copy constructor - gets implicitly invoked when a Rational object is
// copied either by pass-by-value calls or through object instantiation
Rational::Rational(Rational& r)
{
	mNumerator = r.mNumerator;
	mDenominator = r.mDenominator;
}

Rational& Rational::operator=(const Rational& rhs)
{
	if (this != &rhs)
	{
		//this->
		mNumerator = rhs.mNumerator; // integer assignment
		mDenominator = rhs.mDenominator; // integer assignment setDenominator(rhs);
	}

	// std::cout << "address of instance of object: " << this << std::endl;
	// this // a pointer
	return (*this);
} 

// destructors get called implicilty when an object goes out of scope.
	// we use destructors to clean up resources, i.e. close file streams, free memory, etc.
Rational::~Rational()
{
	std::cout << "Inside the destructor for a Rational object!" << std::endl;
}

int Rational::getNumerator() const
{
	return mNumerator;
}

int Rational::getDenominator() const
{
	return mDenominator;
}

void Rational::setNumerator(int newNumerator)
{
	// validating the data
	mNumerator = newNumerator;
}

void Rational::setDenominator(int newDenominator)
{
	// validating the data
	if (newDenominator != 0)
	{
		mDenominator = newDenominator;
	}
	else
	{
		std::cout << "error trying to set denominator to 0!" << std::endl;
	}
}

// non member operator
Rational operator+ (Rational& lhs, Rational& rhs)
{
	Rational result;

	result.setDenominator(lhs.getDenominator() * rhs.getDenominator());
	result.setNumerator(lhs.getNumerator() * rhs.getDenominator() +
		rhs.getNumerator() * lhs.getDenominator()); // find an easy common denominator

	return result; // implicitly called here - copy constructor
}

std::ostream& operator<< (std::ostream& lhs, const Rational& rhs)
{
	lhs << rhs.getNumerator() << " / " << rhs.getDenominator();

	return lhs;
}