/**
 * @author Ivan Zelenkov
 * @version 1.0
 * @since Feb 11, 2021
 *
 * ComplexNumber abstract superclass
 */
public abstract class ComplexNumber {
    private float realNumber;
    private float imaginaryNumber;

    /**
     * Create a complex number by float variables a and b
     *
     * @param realNumber real number
     * @param imaginaryNumber imaginary number
     */
    public ComplexNumber(float realNumber, float imaginaryNumber) {
        this.realNumber = realNumber;
        this.imaginaryNumber = imaginaryNumber;
    }

    /**
     * Addition method
     *
     * @param complexNumber object of ComplexNumber, contain two numbers of type float
     * @return complex number after adding
     */
    public abstract RealNumber add(RealNumber complexNumber);

    /**
     * Subtraction method
     *
     * @param complexNumber object of ComplexNumber, contain two numbers of type float
     * @return complex number after subtracting
     */
    public abstract RealNumber subtract(RealNumber complexNumber);

    /**
     * Multiplication method
     *
     * @param complexNumber object of ComplexNumber, contain two numbers of type float
     * @return complex number after multiplication
     */
    public abstract RealNumber multiply(RealNumber complexNumber);

    /**
     * Division method
     *
     * @param complexNumber object of ComplexNumber, contain two numbers of type float
     * @return complex number after dividing
     */
    public abstract RealNumber divide(RealNumber complexNumber);

    /**
     * Accessor which return a representation of the float realNumber
     *
     * @return a representation of the float variable, which we got by accessing a get method of RealNumber class
     */
    public float getRealNumber() {
        return realNumber;
    }

    /**
     * Accessor which return a representation of the float imaginaryNumber
     *
     * @return a representation of the float variable, which we got by accessing a get method of RealNumber class
     */
    public float getImaginaryNumber() {
        return imaginaryNumber;
    }

    /**
     * Override method, to check if the object is an instance of ComplexNumber class
     * {@inheritDoc}
     *
     * @return boolean result if the object is an instance of ComplexNumber class
     */
    @Override
    public boolean equals(Object o) {
        if (this == o) return true;
        if (!(o instanceof ComplexNumber)) return false;
        ComplexNumber that = (ComplexNumber) o;
        return Float.compare(that.getRealNumber(), getRealNumber()) == 0 &&
                Float.compare(that.getImaginaryNumber(), getImaginaryNumber()) == 0;
    }

    /**
     * Return a string representing the complex number in formatted style
     *
     * @return return a string representing the complex number.
     */
    @Override
    public String toString() {
        // return a formatted string and at the end add i to represent complex number
        return String.format("%.1f + %.1fi", realNumber, imaginaryNumber);
    }
/**
 * Class represents a real number and imaginary number which can be written as a real number multiplied by the imaginary unit i
 */
public class RealNumber extends ComplexNumber {
    public RealNumber(float realNumber, float imaginaryNumber) {
        super(realNumber, imaginaryNumber);
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public RealNumber add(RealNumber otherNumber) {
        // formula (a + c) + (b + d)
        float newA = super.getRealNumber() + otherNumber.getRealNumber();
        float newB = super.getImaginaryNumber() + otherNumber.getImaginaryNumber();
        return new RealNumber(newA, newB);
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public RealNumber subtract(RealNumber otherNumber) {
        // formula to get a complex number (a - c) + (b - d)
        float newA = super.getRealNumber() - otherNumber.getRealNumber();
        float newB = super.getImaginaryNumber() - otherNumber.getImaginaryNumber();
        return new RealNumber(newA, newB);
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public RealNumber multiply(RealNumber otherNumber) {
        // formula to get a complex number (a*c + b*d) + (b*c + a*d)
        float newA = (super.getRealNumber() * otherNumber.getRealNumber() - super.getImaginaryNumber() * otherNumber.getImaginaryNumber());
        float newB = (super.getImaginaryNumber() * otherNumber.getRealNumber() + super.getRealNumber() * otherNumber.getImaginaryNumber());
        return new RealNumber(newA, newB);
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public RealNumber divide(RealNumber otherNumber) {
        // formula to get a complex number (a*c + b*d)/(c^2 + d^2) + (b*c + a*d)/(c^2+d^2)
        float newA = ((super.getRealNumber() * otherNumber.getRealNumber() + super.getImaginaryNumber() * otherNumber.getImaginaryNumber())/
                (otherNumber.getRealNumber()*otherNumber.getRealNumber() + otherNumber.getImaginaryNumber()*otherNumber.getImaginaryNumber()));

        float newB = ((super.getImaginaryNumber() * otherNumber.getRealNumber() - super.getRealNumber() * otherNumber.getImaginaryNumber())/
                (otherNumber.getRealNumber()*otherNumber.getRealNumber() + otherNumber.getImaginaryNumber()*otherNumber.getImaginaryNumber()));
        return new RealNumber(newA, newB);
    }
}