/**
 * File: draw-boxy-fractal.cpp
 * ---------------------------
 * drawBoxyFractal draws a collection of recursively layered squares
 * to form a fractal in two-dimensional space.
 *
 * (c) Jerry Cain
 * Edits and comments by Cynthia Lee (c) 2014
 *
 */

#include <cmath>
using namespace std;

#include "gwindow.h"
#include "simpio.h"

/* Constants */
static const int    WINDOWHEIGHT = 600;
static const int    WINDOWWIDTH = 800;
static const double STARTDIMENSION = 120;
static const double SCALE_FACTOR = 0.45;

/* Function Prototypes */
static void drawBoxyFractal(GWindow& gw, double cx, double cy, double width, int order);
static void drawSquare(GWindow& gw, double cx, double cy, double dimension);

/* 
 * main()
 *
 * - Sets up graphics window
 * - Prompts user for desired depth of drawing (choose 0 (zero) to QUIT)
 * - Initiates call to recursive fractal drawing
 */
int main() {
    setConsoleFont("Arial-18");
    GWindow gw(WINDOWWIDTH, WINDOWHEIGHT);
    while (true){
        int order = getInteger("Depth to draw (0 to quit): ");
        if (order <= 0) break;
        gw.clear();
        int centerX = WINDOWWIDTH/2;
        int centerY = WINDOWHEIGHT/2;
        drawBoxyFractal(gw, centerX, centerY, STARTDIMENSION, order);
    }
    return 0;
}

/* 
 * drawBoxyFractal
 *
 * - gw: the graphics window
 * - cx, cy: the coordinates of the desired center of the next square to draw
 * - width: the width of the square to draw
 * - order: count of how many more levels deep we should go in the recursion
 *
 * Class notes:
 * To generate fractals like the ones on the "real or photoshop?" slide, you can
 * test order and behave differently based on order. For example, to generate a
 * fractal that alternates between two different patterns on alternating order
 * levels, you can say "if (order%2 == 0) { do one thing } else { do something else }
*/
static void drawBoxyFractal(GWindow& gw, double cx, double cy,
                            double width, int order) {

    if (order == 0) return;
    if (order % 2 == 0) {
    //NW corner
        drawBoxyFractal(gw, cx - width/2, cy - width/2, width * SCALE_FACTOR, order-1);
    }
    //NE corner
    drawBoxyFractal(gw, cx + width/2, cy - width/2, width * SCALE_FACTOR, order-1);
    drawSquare(gw, cx, cy, width);
    //SE corner
    drawBoxyFractal(gw, cx + width/2, cy + width/2, width * SCALE_FACTOR, order-1);
    //SW corner
    drawBoxyFractal(gw, cx - width/2, cy + width/2, width * SCALE_FACTOR, order-1);
}


/* 
 * drawSquare
 *
 * - window: the graphics window
 * - cx, cy: the coordinates of the desired *center* of the next square to draw
 * - dimension: the width of the square to draw
 * - fill: color of the box's fill
 * - border: color of the box's border
 *
 * Class notes:
 * You don't need to worry about this one. You can think of it as effectively part of the
 * graphics library. It just draws a filled rectangle at the specified coordinates/size.
 */
static void drawSquare(GWindow& gw, double cx, double cy, double dimension) {
    GRectangle bounds(cx - dimension/2, cy - dimension/2, dimension, dimension);
    gw.setColor("Gray");
    gw.fillRect(bounds);
    gw.setColor("Black");
    gw.drawRect(bounds);
}
