import java.text.DecimalFormat;
import java.text.NumberFormat;
import java.math.RoundingMode;

public class QuadraticDriver {
    //attributes: not ivars: instance variables
    public static final boolean SHOULD_SHOW_BREADCRUMBS = false;   // final: cannot be reassigned
    public static final DecimalFormat DF = decimalFormatManager(3); // final: shared formatter
    public static final double EPSILON = 1E-9;                      // final: safe double comparison

    public static void main(String[] args){
        System.out.println("=== Quadratic Driver ===\n");

        System.out.println("--- Default: f(x) = x\u00B2 ---");
        Quadratic q1 = new Quadratic();
        System.out.println(q1);
        System.out.println("f(3) = " + q1.f(3));
        System.out.println(q1.summary());

        System.out.println(
            "\n--- Two real roots: x\u00B2 - 5x + 6 ---");
        Quadratic q2 = new Quadratic(1, -5, 6);
        System.out.println(q2.summary());

        System.out.println(
            "\n--- One repeated root: x\u00B2 - 6x + 9 ---");
        Quadratic q3 = new Quadratic(1, -6, 9);
        System.out.println(q3.summary());

        System.out.println(
            "\n--- Complex roots: x\u00B2 + 2x + 5 ---");
        Quadratic q4 = new Quadratic(1, 2, 5);
        //System.out.println(q4.summary());
        q4.printSummary();   // utility calling a utility

        System.out.println("\n--- Setter side effects ---");
        Quadratic q5 = new Quadratic(1, 0, -4);
        System.out.println("Before: " + q5.summary());
        q5.setB(-4);
        q5.setC(9);
        System.out.println("\nAfter setB(-4), setC(9): " + q5.summary());

        System.out.println("\n--- Copy constructor ---");
        Quadratic q6 = new Quadratic(q2);   // 'new' allocates separate memory
        System.out.println("Copy of q2: " + q6);
        System.out.println(q6.summary());
        //DWR: use 'equals' with Strings, not ==
        if(q2.getMemoryAddress().equals(q6.getMemoryAddress())){
            System.out.println("q2 and q6 are the same object!");
        }else{
            System.out.println("q2 and q6 are different objects");
        }

        System.out.println("\n--- DWR! Aliases! ---");
        //DWR! 'new' is not being used — q7 is just another name for q2!
        Quadratic q7 = q2;
        System.out.println("Alias of q2: " + q7);
        System.out.println(q7.summary());
        if(q2.getMemoryAddress().equals(q7.getMemoryAddress())){
            System.out.println("q2 and q7 are the same object!");
        }else{
            System.out.println("q2 and q7 are different objects");
        }
        System.out.println("...setting 'c' on q7...");
        q7.setC(666);
        System.out.println("q7 = " + q7);
        System.out.println("q2, the 'original' was changed too!!!");
        System.out.println("q2 = " + q2);
        
        System.out.println("\n--- Testing Various Methods ---");
        //test 1
        int x = 5;
        System.out.println("before tryToInflate: x = " + x);   // 5
        Quadratic.tryToInflate(x);
        System.out.println("after  tryToInflate: x = " + x);   // still 5
        
        //test 2
        Quadratic qa = new Quadratic(1, -5, 6);
        System.out.println("qa = " + qa);
        System.out.println("qa address: " + qa.getMemoryAddress());
        System.out.println("before zapC:  qa = " + qa);        // ...c=6
        Quadratic.zapC(qa);
        System.out.println("after  zapC:  qa = " + qa);        // ...c=0  ← MUTATED
        
        //test 3
        Quadratic qb = new Quadratic(1, -5, 7);
        System.out.println("qb = " + qb);
        System.out.println("qb address: " + qb.getMemoryAddress());
        System.out.println("before tryToReplace: qb = " + qb); // ...c=7
        Quadratic.tryToReplace(qb);
        System.out.println("after  tryToReplace: qb = " + qb); // ...c=7  ← unchanged

        System.out.println("\n--- Degenerate Quadratic ---");
        Quadratic q8 = new Quadratic(0, 3, 2);
        System.out.println("q8 = " + q8);

        System.out.println(
            "\n--- Thanks for using our program! ---");
    }//end main

    //the method below was courtesy of Gemini
    public static DecimalFormat decimalFormatManager(int numPlaces){
        //DWR! a single command in an if can be on the same line
        if(SHOULD_SHOW_BREADCRUMBS){
            System.out.println("...decimalFormatManager: " + numPlaces + "...");
        }
        //notice: we are using casting
        DecimalFormat df = (DecimalFormat) NumberFormat.getInstance();
        df.setMaximumFractionDigits(numPlaces);
        df.setMinimumFractionDigits(0);
        df.setRoundingMode(RoundingMode.HALF_UP);
        return df;
    }//end decimalFormatManager

}//end class QuadraticDriver