package rup.česky.tvary_5;

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


/*******************************************************************************
 * Třída Přesouvač slouží k pohybu s instancemi tříd
 * implementujicich rozhraní IPosuvný.
 *
 * @author     Rudolf Pecinovský
 * @version    2.01, duben 2004
 */
public class Přesouvač
{
//== KONSTANTNÍ ATRIBUTY TŘÍDY =================================================

    /** Tento atribut je tu pouze pro zjednodušení psaní. */
    private static final AktivníPlátno AP = AktivníPlátno.getPlátno();
    
    /** Oočet milisekund mezi dvěma překresleními objektu. */
    private static final int PERIODA = 50;  



//== 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Í ================================================

    /** Specifikuje rychlost posunu objektu daným posunovačem. */
    private int rychlost;


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

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

    /***************************************************************************
     * Vytvoří přesouvače, který bude přesouvat objekty rychlosti 1.
     */
    public Přesouvač()
    {
        this( 1 );
    }


    /***************************************************************************
     * Vytvoří přesouvače, který bude přesouvat objekty zadanou rychlostí.
     *
     * @param rychlost Rychlost, kterou bude přesouvač pohybovat
     *                 se svěřenými objekty.
     */
    public Přesouvač( int rychlost )
    {
        if( rychlost <= 0 )
            throw new IllegalArgumentException(
                "Zadaná rychlost musí byt nezáporná!" );
        this.rychlost = rychlost;
        this.název    = getClass().getName() + "(ID=" + ++počet + 
                        ",rychlost=" + rychlost + ")";
    }



//== PŘÍSTUPOVÉ METODY VLASTNOSTÍ INSTANCÍ =====================================
//== PŘEKRYTÉ METODY IMPLEMENTOVANÝCH ROZHRANÍ =================================
//== PŘEKRYTÉ ABSTRAKTNÍ METODY RODIČOVSKÉ TŘÍDY ===============================
//== PŘEKRYTÉ KONKRÉTNÍ METODY RODIČOVSKÉ TŘÍDY ================================

    /***************************************************************************
     * Metoda převádí instanci na řetězec -
     * používá se většinou pro účely ladění.
     * Mela by ji definovat každá třída a uvést v ni
     * všechny potřebné informace o vnitřním stavu instance.
     *
     * @return     Řetězec informující o vnitřním stavu instance
     */
    public String toString()
    {
        return název;
    }



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

    /***************************************************************************
     * Přesune zadaný objekt o požadovaný počet bodů.
     *
     * @param objekt    Přesouvaný objekt
     * @param doprava   Počet bodů, o než se objekt přesune doprava
     * @param dolů      Počet bodů, o než se objekt přesune dolů
     * @param přihlásit Má-li objekt před začátkam přesunu přihlásit
     *                  u aktivního plátna.
     */
    public void přesunO( IPosuvný objekt, int doprava, int dolů,
                         boolean přihlásit )
    {
            
        IKreslený ik = (IKreslený)objekt;

        double vzdálenost = Math.sqrt(doprava*doprava + dolů*dolů);
        int    kroků      = (int)(vzdálenost / rychlost);
        double dx = (doprava+.4) / kroků;
        double dy = (dolů   +.4) / kroků;
        double x  = objekt.getX() + .4;
        double y  = objekt.getY() + .4;

        if( přihlásit )
            AP.přidej( ik );
        for(int i=kroků;   i > 0;   i-- )
        {
            x = x + dx;
            y = y + dy;
            AP.nekresli();
            objekt.setPozice( (int)x, (int)y );
            AP.překresli();
            AP.vraťKresli();
            P.čekej(PERIODA);
        }
    }


    /***************************************************************************
     * Přesune zadaný objekt o požadovaný počet bodů.
     *
     * @param objekt  Přesouvaný objekt
     * @param doprava Počet bodů, o než se objekt přesune doprava
     * @param dolů    Počet bodů, o než se objekt přesune dolů
     */
    public void přesunO( IPosuvný objekt, int doprava, int dolů )
    {
        přesunO( objekt, doprava, dolů, true );
    }
    
    
    /***************************************************************************
     * Přesune zadaný objekt do požadované pozice.
     *
     * @param objekt      Přesouvaný objekt
     * @param x           x-ova souřadnice požadované cílové pozice
     * @param y           y-ova souřadnice požadované cílové pozice
     * @param přihlásit   Má-li objekt před začátkam přesunu přihlásit
     *                    u aktivního plátna.
     */
    public void přesunNa( IPosuvný objekt, int x, int y, boolean přihlásit )
    {
        přesunO( objekt, x-objekt.getX(), y-objekt.getY(), přihlásit );
    }

    
    /***************************************************************************
     * Přesune zadaný objekt do požadované pozice.
     *
     * @param objekt  Přesouvaný objekt
     * @param x       x-ova souřadnice požadované cílové pozice
     * @param y       y-ova souřadnice požadované cílové pozice
     */
    public void přesunNa( IPosuvný objekt, int x, int y )
    {
        přesunO( objekt, x-objekt.getX(), y-objekt.getY(), true );
    }


    /***************************************************************************
     * Přesune zadaný objekt do požadované pozice.
     *
     * @param objekt      Přesouvaný objekt
     * @param pozice      Požadované cílové pozice.
     * @param přihlásit   Má-li objekt před začátkam přesunu přihlásit
     *                    u aktivního plátna.
     */
    public void přesunNa( IPosuvný objekt, Pozice pozice, boolean přihlásit )
    {
        přesunO( objekt, pozice.x-objekt.getX(), pozice.y-objekt.getY(),
                 přihlásit );
    }


    /***************************************************************************
     * Přesune zadaný objekt do požadované pozice.
     *
     * @param objekt  Přesouvaný objekt
     * @param pozice  Požadované cílové pozice.
     */
    public void přesunNa( IPosuvný objekt, Pozice pozice )
    {
        přesunO( objekt, pozice.x-objekt.getX(), pozice.y-objekt.getY(), true );
    }



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

