package rup.česky.tvary;

import rup.česky.společně.P;

                                                                            /**/
/*******************************************************************************
 * Třída pro prací s trojúhelníkem komunikujícím s aktivním plátnem.
 *
 * Oproti stejnojmenné třídě z projektu
 * 06_Rozhraní se změnilo pouze implementované rozhraní.
 *
 * @author     Rudolf Pecinovský
 * @version    2.01, duben 2004
 */
public class Trojúhelník implements IHýbací
{
//== KONSTANTNÍ ATRIBUTY TŘÍDY =================================================

    /** Počáteční barva nakreslené instance v případě,
     *  kdy uživatel žádnou požadovanou barvu nezadá -
     *  pro trojúhelník Barva.ZELENÁ. */
    public static final Barva IMPLICITNÍ_BARVA = Barva.ZELENÁ;

    /** Počáteční barva nakresleného trojúhelníku v případě,
     *  kdy uživatel žádnou požadovanou barvu nezadá.    */
    public static final Směr8 IMPLICITNÍ_SMĚR = Směr8.SEVER;

    /** Aktivní plátno, které dohlíží na správné vykreslení instance. */
    protected static final AktivníPlátno AP = AktivníPlátno.getPlátno();



//== PROMĚNNÉ ATRIBUTY TŘÍDY ===================================================

    /** Počet vytvořených instancí */
    private static int počet = 0;



//== KONSTANTNÍ ATRIBUTY INSTANCÍ ==============================================

    /** Název sestávající z názvu třídy a pořadí instance */
    private final String název;



//== PROMĚNNÉ ATRIBUTY INSTANCÍ ================================================

    private int    xPos;    //Bodová x-ová souřadnice počátku
    private int    yPos;    //Bodová y-ová souřadnice počátku
    private int    šířka;   //šířka v bodech
    private int    výška;   //Výška v bodech
    private Barva  barva;   //Barva instance
    private Směr8  směr;    //Směr, do nějž je otočen vrchol trojúhelníku



//== PŘÍSTUPOVÉ METODY VLASTNOSTÍ TŘÍDY ========================================
//== OSTATNÍ METODY TŘÍDY ======================================================

//##############################################################################
//== KONSTRUKTORY A TOVÁRNÍ METODY =============================================

    /***************************************************************************
     * Vytvoří novou instanci s implicitními rozměry, umístěním, barvou
     * a natočením.
     * Instance bude umístěna v levém horním rohu plátna
     * a bude mít implicitní barvu,
     * výšku 1 pole, šířku 2 pole a bude natočena vrocholem na sever.
     */
    public Trojúhelník()
    {
        this( 0, 0, 2*AP.getKrok(), AP.getKrok() );
    }


    /***************************************************************************
     * Vytvoří novou instanci se zadanou polohou a rozměry
     * a implicitní barvou a směrem natočení.
     *
     * @param x       x-ová souřadnice počátku, x=0 má levý okraj plátna
     * @param y       y-ová souřadnice počátku, y=0 má horní okraj plátna
     * @param šířka   Šířka vytvářené instance
     * @param výška   Výška vytvářené instance
     */
    public Trojúhelník( int x, int y, int šířka, int výška )
    {
        this( x, y, šířka, výška, IMPLICITNÍ_BARVA, IMPLICITNÍ_SMĚR );
    }


    /***************************************************************************
     * Vytvoří novou instanci se zadanou polohou, rozměry a směrem natočení
     * a s implicitní barvou.
     *
     * @param x       x-ová souřadnice počátku, x=0 má levý okraj plátna
     * @param y       y-ová souřadnice počátku, y=0 má horní okraj plátna
     * @param šířka   Šířka vytvářené instance
     * @param výška   Výška vytvářené instance
     * @param směr    Směr, do nějž bude natočen vrchol trojúhelníku -
     *                je třeba zadat některou z instancí třídy Směr8
     */
    public Trojúhelník( int x, int y, int šířka, int výška, Směr8 směr )
    {
        this( x, y, šířka, výška, IMPLICITNÍ_BARVA, směr );
    }


    /***************************************************************************
     * Vytvoří novou instanci se zadanými rozměry, polohou a barvou.
     * Směr natočení bude implicitní, tj. na sever.
     *
     * @param x       x-ová souřadnice počátku, x=0 má levý okraj plátna
     * @param y       y-ová souřadnice počátku, y=0 má horní okraj plátna
     * @param šířka   Šířka vytvářené instance
     * @param výška   Výška vytvářené instance
     * @param barva   Barva vytvářené instance
     */
    public Trojúhelník( int x, int y, int šířka, int výška, Barva barva )
    {
        this( x, y, šířka, výška, barva, IMPLICITNÍ_SMĚR );
    }


    /***************************************************************************
     * Vytvoří novou instanci se zadanou polohou a rozměry, barvou a měrem.
     *
     * @param pozice  Pozice vytvářené instance
     * @param rozměr  Rozměr vytvářené instance
     * @param barva   Barva vytvářené instance
     * @param směr    Směr, do nějž je natočen vrchol trojúhelníku -
     *                je třeba zadat některou z instancí třídy Směr8
     */
    public Trojúhelník( Pozice pozice, Rozměr rozměr, Barva barva, Směr8 směr )
    {
        this( pozice.x, pozice.y, rozměr.šířka, rozměr.výška, barva, směr );
    }


    /***************************************************************************
     * Vytvoří novou instanci v zadané oblasti a se zadanou barvou.
     *
     * @param oblast  Oblast, v níž se má instance vytvořit
     * @param barva   Barva vytvářené instance
     * @param směr    Směr, do nějž je natočen vrchol trojúhelníku -
     *                je třeba zadat některou z instancí třídy Směr8
     */
    public Trojúhelník( Oblast oblast, Barva barva, Směr8 směr )
    {
        this( oblast.x, oblast.y, oblast.šířka, oblast.výška, barva, směr );
    }


    /***************************************************************************
     * Vytvoří novou instanci se zadanými rozměry, polohou, barvou,
     * i směrem natočení.
     *
     * @param x       x-ová souřadnice počátku, x=0 má levý okraj plátna
     * @param y       y-ová souřadnice počátku, y=0 má horní okraj plátna
     * @param šířka   Šířka vytvářené instance
     * @param výška   Výška vytvářené instance
     * @param barva   Barva vytvářené instance
     * @param směr    Směr, do nějž bude natočen vrchol trojúhelníku -
     *                je třeba zadat některou z instancí třídy Směr8
     */
    public Trojúhelník( int x, int y, int šířka, int výška, Barva barva, Směr8 směr )
    {
        this.název = P.názevTřídy(this) + "_" + ++počet;
        this.xPos  = x;
        this.yPos  = y;
        this.šířka = šířka;
        this.výška = výška;
        this.barva = barva;
        this.směr  = směr;
    }



//== PŘÍSTUPOVÉ METODY ATRIBUTU INSTANCÍ =======================================

    /***************************************************************************
     * Vrátí x-ovou souřadnici pozice instance.
     *
     * @return  x-ová souřadnice.
     */
    public int getX()
    {
        return xPos;
    }


    /***************************************************************************
     * Vrátí y-ovou souřadnici pozice instance.
     *
     * @return  y-ová souřadnice.
     */
    public int getY()
    {
        return yPos;
    }


    /***************************************************************************
     * Vrátí instanci třídy Pozice s pozicí instance.
     *
     * @return   Pozice s pozicí instance.
     */
    public Pozice getPozice()
    {
        return new Pozice( xPos, yPos );
    }


    /***************************************************************************
     * Nastaví novou pozici instance.
     *
     * @param x   Nová x-ová pozice instance
     * @param y   Nová y-ová pozice instance
     */
    public void setPozice(int x, int y)
    {
        xPos = x;
        yPos = y;
        AP.překresli();
    }


    /***************************************************************************
     * Nastaví novou pozici instance.
     *
     * @param pozice   Nová pozice instance
     */
    public void setPozice(Pozice pozice)
    {
        setPozice( pozice.x, pozice.y );
    }


    /***************************************************************************
     * Vrátí šířku instance.
     *
     * @return  Šířka instance v bodech
     */
     public int getŠířka()
     {
         return šířka;
     }


    /***************************************************************************
     * Vrátí výšku instance.
     *
     * @return  Výška instance v bodech
     */
     public int getVýška()
     {
         return výška;
     }


    /***************************************************************************
     * Vrátí instanci třídy Rozměr s rozměry instance.
     *
     * @return   Rozměr s rozměry instance.
     */
    public Rozměr getRozměr()
    {
        return new Rozměr( šířka, výška );
    }


    /***************************************************************************
     * Nastaví nový "čtvercový" rozměr instance -
     * na zadaný rozměr se nastaví výška i šířka.
     *
     * @param rozměr  Nově nastavovaný rozměr v obou směrech; rozměr>0
     */
    public void setRozměr(int rozměr)
    {
        setRozměr( rozměr, rozměr );
    }


    /***************************************************************************
     * Nastaví nové rozměry instance.
     *
     * @param šířka    Nově nastavovaná šířka; šířka>0
     * @param výška    Nově nastavovaná výška; výška>0
     */
    public void setRozměr(int šířka, int výška)
    {
        this.šířka = šířka;
        this.výška = výška;
        AP.překresli();
    }


    /***************************************************************************
     * Nastaví nové rozměry instance.
     *
     * @param rozměr    Nově nastavovaný rozměr.
     */
    public void setRozměr(Rozměr rozměr)
    {
        setRozměr( rozměr.šířka, rozměr.výška );
    }


    /***************************************************************************
     * Vrátí instanci třídy Oblast s informacemi o pozici a rozměrech instance.
     *
     * @return   Oblast s informacemi o pozici a rozměre instance.
     */
    public Oblast getOblast()
    {
        return new Oblast( xPos, yPos, šířka, výška );
    }


    /***************************************************************************
     * Nastaví novou polohu a rozměry instance.
     *
     * @param o    Nově nastavovaná oblast zaujímaná instancí.
     */
    public void setOblast(Oblast o)
    {
        AP.nekresli();
        setPozice( o.x,     o.y     );
        setRozměr( o.šířka, o.výška );
        AP.vraťKresli();
    }


    /***************************************************************************
     * Vrátí barvu instance.
     *
     * @return  Instance třídy Barva definující nastavenou barvu.
     */
    public Barva getBarva()
    {
        return barva;
    }


    /***************************************************************************
     * Nastaví novou barvu instance.
     *
     * @param nová   Požadovaná nová barva.
     */
    public void setBarva(Barva nová)
    {
        barva = nová;
        AP.překresli();
    }


    /***************************************************************************
     * Vrátí směr instance. tj. směr, co nějž je otočen vrchol.
     *
     * @return  Instance třídy Směr8 definující nastavený směr.
     */
    public Směr8 getSměr()
    {
        return směr;
    }


    /***************************************************************************
     * Nastaví nový směr instance.
     *
     * @param nový  Požadovaný nový směr.
     */
    public void setSměr(Směr8 nový)
    {
        směr = nový;
        AP.překresli();
    }


    /***************************************************************************
     * Vrátí název instance, tj. název její třídy následovaný pořadím.
     *
     * @return  Řetězec s názvem instance.
     */
     public String getNázev()
     {
        return název;
     }



//== PŘEKRYTÉ METODY IMPLEMENTOVANÝCH ROZHRANÍ =================================

    /***************************************************************************
     * Za pomoci dodaného kreslítka vykreslí obraz své instance
     * na animační plátno.
     *
     * @param kreslítko   Kreslítko, kterým se instance nakreslí na plátno.
     */
    public void nakresli( Kreslítko kreslítko )
    {
        int[][] points = getVrcholy();
        kreslítko.vyplňPolygon( points[0], points[1], barva );
    }



//== PŘEKRYTÉ ABSTRAKTNÍ METODY RODIČOVSKÉ TŘÍDY ===============================
//== PŘEKRYTÉ KONKRÉTNÍ METODY RODIČOVSKÉ TŘÍDY ================================

    /***************************************************************************
     * Převede instanci na řetězec. Používá se především při ladění.
     *
     * @return Řetězcová reprezentace dané instance.
     */
    public String toString()
    {
        return název + ": x=" + xPos + ", y=" + yPos +
               ",šířka=" + šířka + ",výška=" + výška +
               ", barva=" + barva + ", směr=" + směr;
    }



//== NOVĚ ZAVEDENÉ METODY INSTANCÍ =============================================

    /***************************************************************************
     * Přesune instanci o zadaný počet bodů vpravo,
     * při záporné hodnotě parametru vlevo.
     *
     * @param vzdálenost Vzdálenost, o kterou se instance přesune.
     */
    public void posunVpravo(int vzdálenost)
    {
        setPozice( xPos+vzdálenost, yPos );
    }


    /***************************************************************************
     * Přesune instanci o krok bodů vpravo.
     */
    public void posunVpravo()
    {
        posunVpravo( AP.getKrok() );
    }


    /***************************************************************************
     * Přesune instanci o krok bodů vlevo.
     */
    public void posunVlevo()
    {
        posunVpravo( -AP.getKrok() );
    }


    /***************************************************************************
     * Přesune instanci o zadaný počet bodů dolů,
     * při záporné hodnotě parametru nahoru.
     *
     * @param vzdálenost    Počet bodů, o které se instance přesune.
     */
    public void posunDolů(int vzdálenost)
    {
        setPozice( xPos, yPos+vzdálenost );
    }


    /***************************************************************************
     * Přesune instanci o krok bodů dolů.
     */
    public void posunDolů()
    {
        posunDolů( AP.getKrok() );
    }


    /***************************************************************************
     * Přesune instanci o krok bodů nahoru.
     */
    public void posunVzhůru()
    {
        posunDolů( -AP.getKrok() );
    }



//== SOUKROMÉ A POMOCNÉ METODY TŘÍDY ===========================================
//== SOUKROMÉ A POMOCNÉ METODY INSTANCÍ ========================================

    /***************************************************************************
     * Vrátí matici se souřadnicemi vrcholů daného trojúhelníku.
     *
     * @return Požadovaná matice
     */
    private int[][] getVrcholy()
    {
        int[] xpoints = null;
        int[] ypoints = null;

        switch( směr )
        {
            case VÝCHOD:
                xpoints = new int[]{ xPos,  xPos + (šířka),    xPos };
                ypoints = new int[]{ yPos,  yPos + (výška/2),  yPos + výška };
                break;

            case SEVEROVÝCHOD:
                xpoints = new int[]{ xPos,  xPos + šířka,  xPos + šířka };
                ypoints = new int[]{ yPos,  yPos,          yPos + výška };
                break;

            case SEVER:
                xpoints = new int[]{ xPos,         xPos + (šířka/2), xPos + šířka };
                ypoints = new int[]{ yPos + výška, yPos,             yPos + výška };
                break;

            case SEVEROZÁPAD:
                xpoints = new int[]{ xPos,          xPos,  xPos + šířka };
                ypoints = new int[]{ yPos + výška,  yPos,  yPos         };
                break;

            case ZÁPAD:
                xpoints = new int[]{ xPos,             xPos + šířka, xPos + šířka };
                ypoints = new int[]{ yPos + (výška/2), yPos,         yPos + výška };
                break;

            case JIHOZÁPAD:
                xpoints = new int[]{ xPos,  xPos,          xPos + šířka };
                ypoints = new int[]{ yPos,  yPos + výška,  yPos + výška };
                break;

            case JIH:
                xpoints = new int[]{ xPos,  xPos + (šířka/2),  xPos + šířka };
                ypoints = new int[]{ yPos,  yPos + výška,      yPos,        };
                break;

            case JIHOVÝCHOD:
                xpoints = new int[]{ xPos,          xPos +šířka,   xPos + šířka };
                ypoints = new int[]{ yPos + výška,  yPos + výška,  yPos         };
                break;

            default:
                throw new IllegalStateException(
                    "Instance ukazuje do nedefinovaného směru" );
        }
        return new int[][] { xpoints, ypoints };
    }



//== VNOŘENÉ A VNITŘNÍ TŘÍDY ===================================================
//== TESTY A METODA MAIN =======================================================
}

