// Distance.cpp
// Source file for Distance class

#include "Distance.h"    // Gotta include the header file

//initialize static class data
int Distance::inUnits = Distance::Inches;
void Distance::setUnits(const int& units) {
    inUnits = units;
}

// Constructors--use initializer list when possible
// --Default ctor
Distance::Distance(const int& ft, const float& in) : feet(0), inches(0.0F) {
    setDist(ft, in);
}

// --Overloaded ctor (1-arg) can be used to automatically convert from float
Distance::Distance(const float& in) {
    setDist(0, in);
}

// set and get methods
void Distance::setDist(const int& ft, const float& in) {
    feet = ft;
    inches = in;
    // Verify that inches < 12.
    while (inches >= 12.0F)    {
        inches -= 12.0F;
        feet++;
    }
}

const float Distance::getDist() const {
    if (inUnits == Feet)
        return (float)feet + inches/12.0;
    else
        return feet * 12 + inches;
}
// Convert to a float, anyone?
Distance::operator float() {
    return getDist();
}

const float Distance::getInches() const {
    return inches;
}

const int Distance::getFeet() const {
    return feet;
}

// Prompt user and set data.
void Distance::prompt() {
    cout << "Enter feet: ";
    cin >> feet;
    cout << "Enter inches: ";
    cin >> inches;
    setDist(feet, inches);        // Validate new data
}

// Display Distance object data.
void Distance::display(ostream& out) const {
    // Displays something like: 14' 4.5"
    out << feet << '\'' << " " << inches << '\"';
}

ostream& operator<<(ostream& out, const Distance& D) {
    D.display(out);
    return out;
}

// Operator Overloads!
Distance Distance::operator + (const Distance& d) const {
    return (Distance(feet + d.feet, inches + d.inches));
}
Distance Distance::operator - (const Distance& d) const {
    return (Distance(feet - d.feet, inches - d.inches));
}
Distance operator*(const float& f) const {
    return (Distance((feet/12 + inches)*f));
}
Distance operator*(const int& i) const {
    return (Distance((feet/12 + inches)*i));
}
Distance operator/(const float& f) const {
    return (Distance((feet/12 + inches)/f));
}
Distance operator/(const int& i) const{
    return (Distance((feet/12 + inches)/i));
}

//  Incrementers
Distance& Distance::operator ++ () { // Prefix
    setDist(feet, ++inches);    // Increment inches and validate
    return (*this);                // Return self
}
Distance Distance::operator ++ (int) { // Postfix
    int tempFeet = feet;
    float tempInches = inches; 
    setDist(feet, ++inches);    // Increment inches and validate
    // Return temp nameless obj with old values.
    return(Distance(tempFeet, tempInches));
}

//  Addition assignment
Distance& Distance::operator += (const Distance& d) {
    setDist(feet + d.feet, inches + d.inches); // Add and validate
    return (*this);        // Return self
}

// Conditional Operator Overloads!
bool Distance::operator == (const Distance& d) const {
    // A nifty one-line test--returns true if conditon inside
    //        the return parens is true!
    return ( (feet*12 + inches) == (d.feet*12 + d.inches) );
}
bool Distance::operator != (const Distance& d) const {
    // Return opposite of what == returns!
    return ( !(*this == d) );
}
bool Distance::operator >  (const Distance& d) const {
    return ( (feet*12 + inches) > (d.feet*12 + d.inches) );
}
bool Distance::operator <= (const Distance& d) const {
    return ( !(*this > d) );
}
bool Distance::operator <  (const Distance& d) const {
    return ( !(*this > d) && !(*this == d) );
}
bool Distance::operator >= (const Distance& d) const {
    return ( !(*this < d) );
}