import theater.*;

import java.util.List;
import java.util.Random;


/**
 * Die Klasse stellt eine Repraesentation des Hamster-Territoriums dar. Die
 * Methoden dienen zum Abfragen bestimmter Zustandswerte des aktuellen
 * Territoriums.
 *
 * @author Dietrich Boles (Universitaet Oldenburg)
 * @version 2.0 (07.06.2008)
 *
 */
public class Territorium extends Stage {
    static Object[][] kacheln = null;

    /**
     * Erzeugt ein neues Territorium mit 10x10 Kacheln
     */
    public Territorium() {
        this(10, 10);
    }

    /**
     * Erzeugt ein neues Territorium in der angegebenen Groesse
     *
     * @param reihen
     *            Anzahl an Reihen
     * @param spalten
     *            Anzahl an Spalten
     */
    public Territorium(int reihen, int spalten) {
        super((spalten < 1) ? 10 : spalten, (reihen < 1) ? 10 : reihen, 35);
        this.setBackground("kachel.jpg");
    }

    /**
     * liefert die Anzahl an Reihen im Territorium
     *
     * @return die Anzahl an Reihen im Territorium
     */
    public int getAnzahlReihen() {
        return this.getNumberOfRows();
    }

    /**
     * liefert die Anzahl an Spalten im Territorium
     *
     * @return die Anzahl an Spalten im Territorium
     */
    public int getAnzahlSpalten() {
        return this.getNumberOfColumns();
    }

    /**
     * ueberprueft, ob sich auf der Kachel (reihe/spalte) eine Mauer befindet;
     * es wird genau dann true geliefert, wenn sich auf der angegebenen Kachel
     * eine Mauer befindet oder wenn sich die angegebenen Werte ausserhalb des
     * Territoriums befinden
     *
     * @param reihe
     *            Reihe der Kachel
     * @param spalte
     *            Spalte der Kachel
     * @return true geliefert, wenn sich auf der angegebenen Kachel eine Mauer
     *         befindet oder wenn sich die angegebenen Werte ausserhalb des
     *         Territoriums befinden; sonst false
     */
    public boolean mauerDa(int reihe, int spalte) {
        return this.getComponentsAt(spalte, reihe, Mauer.class).size() > 0;
    }

    /**
     * liefert die Gesamtzahl an Koernern, die im Territorium auf Kacheln
     * herumliegen
     *
     * @return die Gesamtzahl an Koernern, die im Territorium auf Kacheln
     *         herumliegen
     */
    public int getAnzahlKoerner() {
        int anzahl = 0;

        for (int r = 0; r < this.getAnzahlReihen(); r++) {
            for (int s = 0; s < this.getAnzahlSpalten(); s++) {
                anzahl += this.getAnzahlKoerner(r, s);
            }
        }

        return anzahl;
    }

    /**
     * liefert die Anzahl an Koernern auf der Kachel (reihe/spalte) oder 0,
     * falls die Kachel nicht existiert oder durch eine Mauer blockiert ist
     *
     * @param reihe
     *            Reihe der Kachel
     * @param spalte
     *            Spalte der Kachel
     * @return die Anzahl an Koernern auf der Kachel (reihe/spalte) oder 0,
     *         falls die Kachel nicht existiert oder durch eine Mauer blockiert
     *         ist
     */
    public int getAnzahlKoerner(int reihe, int spalte) {
        List<Component> comps = this.getComponentsAt(spalte, reihe, Korn.class);

        if ((comps == null) || (comps.size() == 0)) {
            return 0;
        }

        return ((Korn) comps.get(0)).getAnzahl();
    }

    /**
     * liefert die Gesamtzahl an existierenden Hamstern im Territorium
     *
     * @return die Gesamtzahl an existierenden Hamstern im Territorium
     */
    public int getAnzahlHamster() {
        return this.getComponents(Hamster.class).size();
    }

    /**
     * liefert alle existierenden Hamster im Territorium
     *
     * @return alle existierenden Hamster im Territorium
     */
    public Hamster[] getHamster() {
        return this.getComponents(Hamster.class).toArray(new Hamster[0]);
    }

    /**
     * liefert die Anzahl an Hamstern auf der Kachel (reihe/spalte) oder 0,
     * falls die Kachel nicht existiert oder durch eine Mauer blockiert ist
     *
     * @param reihe
     *            Reihe der Kachel
     * @param spalte
     *            Spalte der Kachel
     * @return die Anzahl an Hamstern auf der Kachel (reihe/spalte) oder 0,
     *         falls die Kachel nicht existiert oder durch eine Mauer blockiert
     *         ist
     */
    public int getAnzahlHamster(int reihe, int spalte) {
        return this.getComponentsAt(spalte, reihe, Hamster.class).size();
    }

    /**
     * liefert alle Hamster, die aktuell auf der Kachel (reihe/spalte) stehen
     * (inkl. dem Standard-Hamster)
     *
     * @param reihe
     *            Reihe der Kachel
     * @param spalte
     *            Spalte der Kachel
     * @return alle Hamster, die aktuell auf der Kachel (reihe/spalte) stehen
     */
    public Hamster[] getHamster(int reihe, int spalte) {
        return this.getComponentsAt(spalte, reihe, Hamster.class)
                   .toArray(new Hamster[0]);
    }

    /**
     * Besetzt das Territorium mit einer festgelegten Population
     */
    public void populationGenerieren() {
        Hamster h1 = new Hamster();
        h1.linksUm();
        h1.linksUm();
        h1.linksUm();
        this.add(h1, 0, 0);

        Hamster h2 = new Hamster();
        h2.linksUm();
        this.add(h2, this.getNumberOfColumns() - 1, this.getNumberOfRows() - 1);

        Hamster h3 = new Hamster();
        this.add(h3, this.getNumberOfColumns() / 2, this.getNumberOfRows() / 2);

        this.koernerGenerieren((this.getNumberOfColumns() * this.getNumberOfRows()) / 2);
    }

    /**
     * Platziert zufaellig eine angegebene Anzahl von Koernern im Territorium
     *
     * @param wieviele
     *            Anzahl der zu platzierenden Koerner
     */
    public void koernerGenerieren(int wieviele) {
        Random random = new Random();

        for (int i = 0; i < wieviele; i++) {
            Korn korn = new Korn();
            int col = random.nextInt(this.getNumberOfColumns());
            int row = random.nextInt(this.getNumberOfRows());
            this.add(korn, col, row);
        }
    }

    public synchronized Object getKachel(int reihe, int spalte) {
        if (Territorium.kacheln == null) {
            Territorium.kacheln = new Object[this.getAnzahlReihen()][this.getAnzahlSpalten()];

            for (int r = 0; r < Territorium.kacheln.length; r++) {
                for (int s = 0; s < Territorium.kacheln[r].length; s++) {
                    Territorium.kacheln[r][s] = new Object();
                }
            }
        }

        return Territorium.kacheln[reihe][spalte];
    }
}
