/*----------------------------------------------------------------------------
 * Klasse:		    Bahn.java
 * Beschreibung:	Eine Spielbahn eines ganzes Spiels, enthält alle Banden,
 *                  Abspielpunkt, Loch und andere Hindernisse
 * Autor:		    Jack Meyer
 * Datum:		    November, 1997
 * ---------------------------------------------------------------------------
 */


import java.awt.*;
import java.util.Vector;


class Bahn {

    /**
     * Ansichtspunkt dieser Bahn, damit die Bahn in die Mitte des Feldes kommt
     * mit default View (0,0)
     */
    private Point itsView = new Point(0,0);

    /**
     * Abspielpunkt dieser Bahn
     */
    private Abspiel itsAbspiel;
    /**
     * Loch dieser Bahn
     */
    private Loch itsLoch;
    /**
     * mehrere Grundböden dieser Bahn
     */
    private Vector itsFairways = new Vector();
    /**
     * mehrere Begrenzungen dieser Bahn
     */
    private Vector itsBanden = new Vector();
    /**
     * Flag ob diese Bahn eine Exception beim Parsen hatte
     */
    private boolean hasException = false;
    private String[] bahnExceptionMessage = new String[3];



    /*
     *  Konstruktor der Bahn
     */
    Bahn (String aStringParameter)
    {
        int indexStart =0;
        int indexEnd;
        String stringOneElement ="";

        try {
            /* skip spaces */
            while (aStringParameter.charAt(indexStart) == ' ') indexStart++;
            /* suche erster Strichpunkt ; */
            indexEnd = aStringParameter.indexOf (';',indexStart);
            /* keinen gefunden -> abbrechen */
            if (indexEnd <=0) indexEnd = aStringParameter.length();
            if (indexEnd ==0) throw new ParsingException ("Keine Parameter gefunden");

            /* Schlaufe über alle Parameter */
            while (indexStart <= indexEnd) {

                /* suche Substring für eine Element */
                stringOneElement = aStringParameter.substring (indexStart, indexEnd);

                /* checke Substring */
                if (stringOneElement.equals("") == false) {
                /* Bearbeite Substring */
                    switch (stringOneElement.charAt(0))
                    {
                        case 'B':
                        {
                            /* füge Bande hinzu */
                            this.addBande (new Bande (stringOneElement));
                            break;
                        };

                        case 'F':
                        {
                            /* füge Fairway hinzu */
                            this.addFairway (new Fairway (stringOneElement));
                            break;
                        };

                        case 'A':
                        {
                            /* test auf Abspielpunkt, nur 1 Abspielpunkt erlaubt */
                            if (itsAbspiel != null) throw new ParsingException ("Nur 1 Abspiel erlaubt");
                            /* füge Abspiel hinzu */
                            this.addAbspiel (new Abspiel (stringOneElement));
                            break;
                        };

                        case 'L':
                        {
                            /* test auf Tee, nur 1 Tee erlaubt */
                            if (itsLoch != null) throw new ParsingException ("Nur 1 Loch erlaubt");
                            /* füge Loch hinzu */
                            this.addLoch (new Loch (stringOneElement));
                            break;
                        };

                        case 'V':
                        {
                            double[] dArgs = Parser.ParseStringToDouble(stringOneElement);
                            /* testen ob genau 2 Parameter vorhanden */
                            if (dArgs.length != 2) throw new ParsingException ("View muss genau 2 Parameter (X,Y) haben");
                            /* füge View hinzu */
                            this.addView (new Point  ((int)dArgs[0],(int)dArgs[1]));
                            break;
                        };


                        default:
                        {
                            throw new ParsingException ("Unbekannter Parameter gefunden");
                        };

                    }; /* switch */
                }; /* not null */

                /* nächstes Element beginnt gleich dahinter */
                indexStart = indexEnd +1;
                /* skip spaces */
                while ((indexStart < aStringParameter.length()) && (aStringParameter.charAt(indexStart) == ' ')) indexStart++;

                indexEnd = aStringParameter.indexOf (';',indexStart);
                /* Achtung: der letzte hat evtl kein ; mehr */
                if (indexEnd <= 0)
                    indexEnd = aStringParameter.length();

            }; /* while */


            /* test auf Loch und Tee beide müssen vorhanden sein */
            stringOneElement ="";
            if (itsLoch == null) throw new ParsingException ("Kein Loch definiert");
            if (itsAbspiel == null) throw new ParsingException ("Kein Abspielpunkt definiert");

        }
        catch (Exception e) {
            /* Bingo we have an Exception */
            //System.out.println("Exception: "+ e);
            //System.out.println("Message: "+ e.getMessage());
            //System.out.println("at: "+ stringOneElement);
            hasException = true;
            bahnExceptionMessage[0] = "Parameter Error: ";
            bahnExceptionMessage[1] = e.getMessage();
            bahnExceptionMessage[2] = "in: " + stringOneElement;
        };

    };



    /**
     * Methode um abzufragen ob Exception
     */
    boolean hasException () {
        return hasException;
    };
    String[] getExceptionMessage () {
        return bahnExceptionMessage;
    };


    /**
     * Methode um Sicht punkt zu setzten
     */
    void addView (Point aPoint)
    {
        itsView = aPoint;
    };

    /**
     * Methode um den einzigen Abspielpunkt der Bahn zu definieren
     */
    void addAbspiel (Abspiel anAbspiel)
    {
        itsAbspiel = anAbspiel;
    };

    /**
     * Methode um das einzige Loch der Bahn zu definieren
     */
    void addLoch (Loch aLoch)
    {
        itsLoch = aLoch;
    };

    /**
     * Methode um mehrere Fairways der Bahn zu definieren
     */
    void addFairway (Fairway aFairway)
    {
        itsFairways.addElement(aFairway);
    };

    /**
     * Methode um mehrere Banden der Bahn zu definieren
     */
    void addBande (Bande aBande)
    {
        itsBanden.addElement(aBande);
    };



    /**
     * Reset Ball: Ball in Ausgangsposition
     */
    void resetBall (Ball aBall)
    {
        itsAbspiel.setBallPosition(aBall);
        /* korrektur um itsView */
        Point ballPos;
        ballPos = aBall.getPos();
        ballPos.x -= itsView.x;
        ballPos.y -= itsView.y;
        aBall.setPos(ballPos);
    };


    /**
     * Bewegung des Balls: Test ob Kollision
     */
    void collisionDetection (Ball aBall, int posX, int posY)
    {
//        System.out.println("Collision Detection in Bahn");
        // verschiebung aller Elemente, damit die Banh in die Mitte des Playfield kommt
        if (itsView != null) {
            posX -= itsView.x;
            posY -= itsView.y;
        };
        // test auf Grundböden, für Geschwindigkeit
        for (int i=0; i<itsFairways.size(); i++)
        {
            Fairway aFairway = (Fairway) itsFairways.elementAt(i);
            if (aFairway != null) { aFairway.collisionDetection (aBall, posX, posY);};
        };

        // teste auf Banden, für Reflexion
        for (int i=0; i<itsBanden.size(); i++)
        {
            Bande aBande = (Bande) itsBanden.elementAt(i);
            if (aBande != null) { aBande.collisionDetection (aBall, posX, posY);};
        };

        // teste auf Loch, für Ziel
        if (itsLoch != null) {
            itsLoch.collisionDetection (aBall, posX, posY);};
    };





    /**
     * Zeichenmethode für die Laufbahn
     */
    void draw (Graphics g, int posX, int posY)
    {
        // verschiebung aller Elemente, damit die Banh in die Mitte des Playfield kommt
        if (itsView != null) {
            posX -= itsView.x;
            posY -= itsView.y;
        };

        // zeichne zuerst Grundböden
        for (int i=0; i<itsFairways.size(); i++)
        {
            Fairway aFairway = (Fairway) itsFairways.elementAt(i);
            if (aFairway != null) { aFairway.draw (g, posX, posY);};
        };
        // dann die Ränder und Hindernisse
        for (int i=0; i<itsBanden.size(); i++)
        {
            Bande aBande = (Bande) itsBanden.elementAt(i);
            if (aBande != null) { aBande.draw (g, posX, posY);};
        };
        // dann den Abspielpunkt
        if (itsAbspiel != null) {
            itsAbspiel.draw (g, posX, posY); };
        // dann das Loch
        if (itsLoch != null) {
            itsLoch.draw (g, posX, posY); };
    };



    /**
     * gibt die Verschiebung itsView zurück
     */
    Point itsView ()
    {
        return itsView;
    };


};