/*
 * This program displays an animated oval sunset that falls until it hits
 * the bottom of the window.
 */
import acm.program.*;
import acm.graphics.*;
import java.awt.*;

public class Sunset extends GraphicsProgram {
    private static final double SUN_DIAMETER = 75;       // radius of the sun
    private static final double HORIZON_HEIGHT = 100;  // height of the horizon
    private static final double SUNSET_VELOCITY = 1.0; // setting velocity
    private static final double PAUSE_TIME = 40;       // MS pause btw. frames

    public void run() {
        setBackground(Color.CYAN);
        GOval sun = makeSun();
        GRect horizon = makeHorizon();
        add(sun);       // add sun then horizon so sun can set behind it
        add(horizon);
        performSunset(sun);
    }

    /* Creates and returns an oval representing the sun. */
    private GOval makeSun() {
        // Center the GOval in the window.
        GOval sun = new GOval((getWidth() - SUN_DIAMETER) / 2.0,
               (getHeight() - SUN_DIAMETER) / 2.0, SUN_DIAMETER, SUN_DIAMETER);
        sun.setFilled(true);
        sun.setColor(Color.YELLOW);
        return sun;
    }

    /* Creates and returns a rectangle representing the horizon. */
    private GRect makeHorizon() {
        // horizon should horizontally fill window and should have height of
        // HORIZON_HEIGHT. It will be aligned to the bottom of the window.
        GRect result = new GRect(0, getHeight() - HORIZON_HEIGHT,
                                 getWidth(), HORIZON_HEIGHT);
        result.setColor(Color.GREEN);
        result.setFilled(true);
        return result;
    }

    /* Simulates a sunset. */
    private void performSunset(GOval sun) {
        // Keep moving the sun downward until it has set.
        while (!hasSunSet(sun)) {
            sun.move(0, SUNSET_VELOCITY);
            pause(PAUSE_TIME);
        }
    }
    /* Given the sun, determine whether or not it has set. */
    private boolean hasSunSet(GOval sun) {
        // The sun has set as soon as its top is below the horizon.
        return sun.getY() > getHeight() - HORIZON_HEIGHT;
    }
}
