import schule.ngb.zm.Zeichenmaschine;
import schule.ngb.zm.shapes.Text;

import java.awt.Font;

public class Raindrops extends Zeichenmaschine {

	//@formatter:off
	// Einstellungen für das Spiel

	// Breite / Höhe des Spielfensters.
	public static final int GAME_WIDTH = 400;
	public static final int GAME_HEIGHT = 600;
	// Breite des Randes (dort werden keine Tropfen erstellt).
	public static final int GAME_BORDER = 10;

	// Anzahl Tropfen zu Beginn des Spiels.
	public static final int GAME_START_DROPS = 5;
	// Maximale Anzahl Tropfen im Spiel.
	public static final int GAME_MAX_DROPS = 12;
	// Anzahl gefangenere Tropfen, ab der ein neuer Level anfängt.
	public static final int GAME_NEXT_LEVEL_AT = 10;
	// Anzahl Tropfen, die fallen gelassen werden dürfen,
	// bevor das Spiel vorbei ist.
	public static final int GAME_MAX_DROPPED = 13;
	//@formatter:on

	public static void main( String[] args ) {
		new Raindrops();
	}

	/**
	 * Array der Tropfen-Objekte.
	 */
	private Drop[] drops;

	/**
	 * Das Eimer-Objekt.
	 */
	private Bucket bucket;

	/**
	 * Anzahl Tropfen, die aktuell im Spiel sind.
	 */
	private int noOfDrops = GAME_START_DROPS;

	/**
	 * Anzahl gefangener / fallen gelassener Tropfen.
	 */
	private int dropped = 0, catched = 0;

	/**
	 * Text-Objekte für die Anzeige der gefangenen / fallen gelassenen Tropfen.
	 */
	private Text textDropped, textCatched;

	public Raindrops() {
		super(GAME_WIDTH, GAME_HEIGHT, "ZM: Raindrops");
	}

	/**
	 * Initialisierung des Spiels und der benötigten Objekte.
	 */
	public void setup() {
		hideCursor();

		// Hintergrund blaugrau
		background.setColor(129, 174, 206);

		// Hintergrundbild zeichnen (DrawingLayer)
		drawing.setFillColor(0, 144, 81);
		drawing.noStroke();
		drawing.rect(0, height - 40, width, 40, NORTHWEST);

		// Eimer-Objekt erstellen
		bucket = new Bucket(width / 2, height - 60);
		bucket.scale(.25);
		shapes.add(bucket);

		// Tropfen-Objekte erstellen
		// Die maximale Anzahl Tropfen kann durch GAME_MAX_DROPS eingestellt werden
		// Es werden alle Tropfen erstellt, anber nur die ersten noOfDrops
		// Objekt im Spiel angezeigt.
		drops = new Drop[GAME_MAX_DROPS];
		for( int i = 0; i < drops.length; i++ ) {
			drops[i] = new Drop();
			drops[i].scale(.1);
			shapes.add(drops[i]);
		}

		// Die ersten noOfDrops Tropfen zu Beginn anzeigen.
		// Die Tropfen werden mit zufälliger x-Koordinate etwas versetzt
		// übereinander positioniert, damit sie nicht alle gleichzeitig fallen.
		for( int i = 0; i < noOfDrops; i++ ) {
			drops[i].moveTo(
				random(GAME_BORDER, GAME_WIDTH - GAME_BORDER),
				Drop.START_Y - i * (2 * Drop.START_Y) - random(-10, 10)
			);
			drops[i].activate();
			drops[i].show();
		}

		// Erstellen der Text-Objekte für dei Zähler.
		textCatched = new Text(10, 60, "0");
		textCatched.setFontsize(64);
		textCatched.setAnchor(NORTHWEST); //linksbündig
		shapes.add(textCatched);
		textDropped = new Text(width - 10, 60, "0");
		textDropped.setFontsize(64);
		textDropped.setAnchor(NORTHEAST); // rechtsbündig
		shapes.add(textDropped);
	}

	/**
	 * Hier passiert die Spiel-Logik. Die Position des Eimers und der Tropfen
	 * wird aktualisiert. Es wird geprüft, ob ein Tropfen mit dem Eimer
	 * kollidiert oder den Boden erreicht hat.
	 *
	 * @param delta
	 */
	public void update( double delta ) {
		// Position des Eimers auf Mausposition setzen.
		if( mouseX < 0 ) {
			// Stopp am linken Rand
			bucket.setX(0);
		} else if( mouseX > width ) {
			// Stopp am rechten Rand
			bucket.setX(width);
		} else {
			bucket.setX(mouseX);
		}

		// Die Position der Tropfen aktualisieren und Kollisionen prüfen.
		for( int i = 0; i < noOfDrops; i++ ) {
			drops[i].update(delta);

			if( drops[i].getY() >= height - 40 ) {
				// Tropfen hat Boden erreicht!
				dropped += 1;
				textDropped.setText("" + dropped);
				drops[i].reset();
			} else if( bucket.contains(drops[i]) ) {
				// Tropfen wurde gefangen!
				catched += 1;
				textCatched.setText("" + catched);
				drops[i].reset();

				// Wurde ein Tropfen gefangen (und nur dann) wird geprüft, ob
				// das nächste Level erreicht wurde.
				if( catched > 0 && (catched % GAME_NEXT_LEVEL_AT) == 0 ) {
					// Falls noch nicht alle Tropfen im Spiel, aktiviere einen
					// weiteren.
					if( noOfDrops < drops.length ) {
						noOfDrops += 1;
						drops[noOfDrops - 1].activate();
						drops[noOfDrops - 1].reset();
					}

					// Geschwindigkeit aller Tropfen erhöhen.
					for( int j = 0; j < drops.length; j++ ) {
						drops[j].increaseSpeed();
					}
				}
			}
		}

		// Prüfen, ob das Spiel verloren wurde.
		if( dropped >= GAME_MAX_DROPPED ) {
			stop(); // Stoppt den Game-Loop und ruft dann teardown() auf.
		}
	}

	/**
	 * Wird aufgerufen, nachdem das Spiel gestoppt wurde und zeigt den Game Over
	 * Bildschirm an.
	 */
	public void teardown() {
		// Alle Formen (Eimer, Tropfen, Texte) entfernen.
		shapes.removeAll();

		// "Game Over" Text
		Text gameOver = new Text(width / 2, 300, "Game Over");
		gameOver.setFontsize(64);
		shapes.add(gameOver);

		// Ergebnis anzeigen (Anzahl gefangener Tropfen, Spielzeit in Sekunden).
		Font f = new Font(Font.SANS_SERIF, Font.PLAIN, 32);
		shapes.add(new Text(width / 2, 360, "Catched: " + catched, f));
		shapes.add(new Text(width / 2, 360 + f.getSize(), "Time: " + (runtime / 1000.0), f));

		redraw();
	}

}
