import java.awt.Graphics2D;


/**
 * Trida Smrk slouzi k demonstraci zakladu prace se zdrojovym kodem.
 * Je soucasti projektu Tvary, ktery slouzi k demonstraci moznosti
 * vyuky objektove orientovaneho programovani.
 *
 * @author     Rudolf Pecinovsky
 * @version    1.06, 16.1.2003
 */
public class Smrk implements IKresleny, IPosuvny, INafukovaci
{
//== VEREJNE KONSTANTY =========================================================
//== SOUKROME KONSTANTY ========================================================
//== ATRIBUTY TRIDY ============================================================

    private static int krok = 50;
    private static int pocet = 0;


//== ATRIBUTY INSTANCI =========================================================

    private Trojuhelnik horni;
    private Trojuhelnik stredni;
    private Trojuhelnik dolni;
    private final int poradi = ++pocet;
    private String nazev = "Smrk_" + pocet;


//== PRISTUPOVE METODY ATRIBUTU TRIDY ==========================================

    /**
     * Vraci velikost kroku, o kterou se posune obrazek smrku
     * pri volani bezparametrickych posunovych metod.
     *
     * @return   velikost kroku v bodech
     */
    public static int getKrok()
    {
        return krok;
    }//public int getKrok()


    /**
     * Nastavi novou velikost kroku, o kterou se posune obrazek
     * smrku pri volani bezparametrickych posunovych metod.
     *
     * @param krok  nastavovana velikost kroku v bodech
     */
    public static void setKrok( int krok )
    {
        Smrk.krok = krok;
    }//public void setKrok( int krok )


//== OSTATNI METODY TRIDY ======================================================

//== KONSTRUKTORY ==============================================================

    /**
     * Konstruktor pro objekty tridy Smrk, ktery umozni nastavit
     * souradnice a rozmery vytvareneho obrazce.
     * Souradnicemi objektu se pritom rozumi souradnice
     * leveho horniho rohu ctverce trojuhelniku.
     * @param x   x-ova souradnice, x>=0, x=0 ma levy okraj platna
     * @param y   y-ova souradnice, y>=0, y=0 ma horni okraj platna
     * @param sirka   sirka obdelniku,  sirka > 0
     * @param vyska   vyska obdelniku,  vyska > 0
     */
    public Smrk( int x, int y, int sirka, int vyska )
    {
        horni = new Trojuhelnik( x+sirka/5,  y,          3*sirka/5, 3*vyska/7 );
        stredni=new Trojuhelnik( x+sirka/10, y+vyska/7,  4*sirka/5, 4*vyska/7 );
        dolni = new Trojuhelnik( x,          y+2*vyska/7,  sirka,   5*vyska/7 );
    }//public Smrk( int x, int y, int sirka, int vyska )


    /**
     * Konstruktor pro objekty tridy Smrk, ktery umi nastavit
     * pocatecni pozici objektu. Velikost je implicitni.
     * Souradnicemi objektu se pritom rozumi souradnice
     * leveho horniho rohu opsanohu ctverce.
     * @param x   x-ova souradnice, x>=0, x=0 ma levy okraj platna
     * @param y   y-ova souradnice, y>=0, y=0 ma horni okraj platna
     * @param w   sirka obdelniku,  w > 0
     * @param h   vyska obdelniku,  h > 0
     */
    public Smrk( int x, int y )
    {
        this( x, y, 50, 70 );
    }//public Smrk( int x, int y )


    /**
     * Bezparametricky konstruktor pro objekty tridy Smrk.
     * Nakresli objekt standardni velikosti se souradnicemi [0;0].
     */
    public Smrk()
    {
        this( 0, 0, 50, 70 );
    }//public Smrk()


//== PRISTUPOVE METODY ATRIBUTU INSTANCI =======================================

    /**
     * Vraci x-vou souradnici celeho smrku.
     *
     * @return     x-ova souradnice smrku
     */
    public int getX()
    {   //x-ova souradnice spodniho trojuhelniku
        //je zaroven x-vou souradnici celeho smrku
        return dolni.getX();
    }//public int getX()


    /**
     * Vraci y-vou souradnici celeho smrku.
     *
     * @return     y-ova souradnice smrku
     */
    public int getY()
    {   //y-ova souradnice horniho trojuhelniku
        //je zaroven y-vou souradnici celeho smrku
        return horni.getY();
    }//public int getY()


    /**
     * Nastavi novou pozici stromku na platne.
     *
     * @param x  nova x-ova souradnice smrku
     * @param y  nova y-ova souradnice smrku
     */
    public void setPozice( int x, int y )
    {
        //Aby se platno neprekreslovalo po zmenach jednotlivych casti stromku,
        //zakazeme po dobu prekreslovani stomku platnu jeho prekresleni.
        AnimPlatno platno = AnimPlatno.getPlatno();
        platno.nekresli();

        //Pripravime si casto pouzivane hodnoty
        int x0 = getX();
        int y0 = getY();

        //Protoze se velikost stromku nezvetsila, muzeme za posuny
        //jednotlivych trojuhelniku od leveho horniho rohu smrku
        //jedoduse dosadit jejich stavajici posuny
        horni.setPozice  ( x + horni.getX()-x0,   y );
        stredni.setPozice( x + stredni.getX()-x0, y + stredni.getY()-y0 );
        dolni.setPozice  ( x + dolni.getX()-x0,   y + dolni.getY()-y0 );

        platno.vratKresli();
    }//public void getY( int x, int y )


    /**
     * Vrati sirku celeho obrazce.
     *
     * @return   sirka smrku
     */
    public int getSirka()
    {   //Sirka spodniho trojuhelniku
        //je zaroven sirkou celeho stromku
        return dolni.getSirka();
    }//public int getSirka()


    /**
     * Vrati vysku celeho obrazce.
     *
     * @return   vyska smrku
     */
    public int getVyska()
    {   //Vysku spoctu jako rozdil y-vych souradnic
        //spicky a spodni hrany smrku
        return dolni.getY()+dolni.getVyska() - horni.getY();
    }//public int getVyska()


    /**
     * Nastavi novy rozmer stromku na platne.
     *
     * @param s  nova sirka smrku
     * @param v  nova vyska smrku
     */
    public void setRozmer( int s, int v )
    {
        //Aby se platno neprekreslovalo po zmenach jednotlivych casti stromku,
        //zakazeme po dobu prekreslovani stomku platnu jeho prekresleni.
        AnimPlatno platno = AnimPlatno.getPlatno();
        platno.nekresli();

        //Zmenou velikosti celeho smrku se meni i pozice
        //jeho jednotlivych casti - je treba nastavit obe
        //Pri nastavovani muzeme vyjit z definice kontruktoru

        //Pripravime si casto pocitane vyrazy
        int s5 = s/5;
        int v7 = v/7;
        int x = getX();
        int y = getY();

        //Spocteme a nastavime novou pozici jednotlivych casti
        horni.setPozice  ( x + s5,   y );
        stredni.setPozice( x + s/10, y + v7 );
        dolni.setPozice  ( x,        y + v7*2 );

        //Spocteme a nastavime definitivni podobu casti
        horni.setRozmer  ( 3 * s5,   3 * v7 );
        stredni.setRozmer( 4 * s5,   4 * v7 );
        dolni.setRozmer  (     s,    5 * v7 );

        platno.vratKresli();
    }//public void setRozmer( int s, int w )


//== OSTATNI METODY INSTANCI ===================================================

    /**
     * Nakresli stromek na platno.
     */
    public void kresli( Graphics2D g )
    {
        //Aby se platno neprekreslovalo po zmenach jednotlivych casti stromku,
        //zakazeme po dobu prekreslovani stomku platnu jeho prekresleni.
        AnimPlatno platno = AnimPlatno.getPlatno();
        platno.nekresli();

        horni.kresli( g );
        stredni.kresli( g );
        dolni.kresli( g );

        platno.vratKresli();
    }//public void kresli( Graphics2D g )


    /**
     *  Posune stromek o zadany pocet bodu vpravo,
     *  pri zapornem parametru vlevo.
     *
     *  @param n   pocet bodu, o ktere se smrcek posune
     */
    public void posunVpravo( int n )
    {
        //Aby se platno neprekreslovalo po zmenach jednotlivych casti stromku,
        //zakazeme po dobu prekreslovani stomku platnu jeho prekresleni.
        AnimPlatno platno = AnimPlatno.getPlatno();
        platno.nekresli();

        dolni.posunVpravo( n );
        stredni.posunVpravo( n );
        horni.posunVpravo( n );

        platno.vratKresli();
     }//public void posunVpravo( int n )


    /**
     * Posune obraek smrku o krok bodu vpravo.
     */
    public void posunVpravo()
    {
        this.posunVpravo( krok );
    }//public void posunVpravo()


    /**
     * Posune obraek smrku o krok bodu vlevo.
     */
    public void posunVlevo()
    {   //Pro posun vlevo musime zadat zapornou hodnotu
        this.posunVpravo( -krok );
    }//public void posunVlevo()


    /**
     *  Posune stromek o zadany pocet bodu dolu,
     *  pri zapornem parametru nahoru.
     *
     *  @param n  pocet bodu, o ktere se smrcek posune
     */
    public void posunDolu( int n )
    {
        //Aby se platno neprekreslovalo po zmenach jednotlivych casti stromku,
        //zakazeme po dobu prekreslovani stomku platnu jeho prekresleni.
        AnimPlatno platno = AnimPlatno.getPlatno();
        platno.nekresli();

        horni.posunDolu( n );
        stredni.posunDolu( n );
        dolni.posunDolu( n );

        platno.vratKresli();
     }//public void posunDolu( int n )


    /**
     * Posune obraek smrku o krok bodu nahoru.
     */
    public void posunNahoru()
    {   //Pro posun nahoru musime zadat zapornou hodnotu
        this.posunDolu( -krok );
    }//public void posunNahoru()


    /**
     * Posune obraek smrku o krok bodu dolu.
     */
    public void posunDolu()
    {
        this.posunDolu( krok );
    }//public void posunDolu()


    /**
     * Metoda prevadi instanci na retezec -
     * pouziva se vetsinou pro ucely ladeni.
     * Mela by ji definovat kazda trida a uvest v ni
     * vsechny potrebne informace o vnitrnim stavu instance.
     *
     * @return     retezec informujici o vnitrnim stavu instance
     */
    public String toString()
    {
        return "Smrk na pozici [" + getX() + ";" + getY() +
            "], sirka=" + getSirka() + ", vyska=" + getVyska();
    }//public String toString()


//== SOUKROME A POMOCNE METODY =================================================
//== VNORENE A VNITRNI TRIDY ===================================================

}//public class Smrk implements IKresleny