package shapes77.canvas_4;
// Příliš žluťoučký kůň úpěl ďábelské ó - PŘÍLIŠ ŽLUŤOUČKÝ KŮŇ ÚPĚL ĎÁBELSKÉ Ó

import shapes77.util.IO;


/*******************************************************************************
 * Instances of class {@code Mover} works as servants
 * continuously moving the served instances implementing the interface
 * {@link IMovable}.
 */
public class Mover
{
//\CC== CLASS CONSTANTS (CONSTANT CLASS/STATIC ATTRIBUTES/FIELDS) ==============

    /** Počet milisekund mezi dvěma překresleními objektu. */
    private static final int PERIOD = 50;



//\CV== CLASS VARIABLES (VARIABLE CLASS/STATIC ATTRIBUTES/FIELDS) ==============

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



//##############################################################################
//\CI== CLASS (STATIC) INITIALIZER (CLASS CONSTRUCTOR) =========================
//\CF== CLASS (STATIC) FACTORY METHODS =========================================
//\CG== CLASS (STATIC) GETTERS AND SETTERS =====================================
//\CM== CLASS (STATIC) REMAINING NON-PRIVATE METHODS ===========================
//\CP== CLASS (STATIC) PRIVATE AND AUXILIARY METHODS ===========================



//##############################################################################
//\IC== INSTANCE CONSTANTS (CONSTANT INSTANCE ATTRIBUTES/FIELDS) ===============

    /** Identifikační kód (rodné číslo) instance. */
    private final int ID = ++countCreated;

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



//\IV== INSTANCE VARIABLES (VARIABLE INSTANCE ATTRIBUTES/FIELDS) ===============

    /** Specifikuje rychlost posunu objektu daným posunovačem, tj. počet
     *  jednotek vzdálenosti, o něž bude objekt přesunut v jednom kroku. */
    private int speed;



//##############################################################################
//\II== INSTANCE INITIALIZERS (CONSTRUCTORS) ===================================

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


    /***************************************************************************
     * Vytvoří přesouvače, který bude přesouvat objekty zadanou rychlostí.
     *
     * @param speed Rychlost, kterou bude přesouvač pohybovat
     *              se svěřenými objekty
     */
    public Mover(int speed)
    {
        if (speed <= 0) {
            throw new IllegalArgumentException(
                "The given speed must be positive!");
        }
        this.speed = speed;
        this.name  = getClass().getSimpleName() +
                     "[ID=" + ID + ", speed=" + speed + "]";
    }



//\IA== INSTANCE ABSTRACT METHODS ==============================================
//\IG== INSTANCE GETTERS AND SETTERS ===========================================
//\IM== INSTANCE REMAINING NON-PRIVATE METHODS =================================

    /***************************************************************************
     * Plynule přesune zadaný objekt o zadaný počet jednotek vzdálenosti.
     *
     * @param right   Počet bodů, o než se objekt přesune doprava
     * @param down    Počet bodů, o než se objekt přesune dolů
     * @param object  Přesouvaný objekt
     */
    public void moveBy(int right, int down, IMovable object)
    {
        double distance = Math.sqrt(right*right + down*down);
        int    steps    = (int)(distance / speed); //Počet potřebných přesunů
        double dx = (right+.4) / steps; //Velikost mikropřesunu vodorovně
        double dy = (down +.4) / steps; //Velikost mikropřesunu svisle
        int    px = object.getX();      //Výchozí pozice objektu
        int    py = object.getY();
        double x  = px + .4;    //Výchozí pozice upravená pro zaokrouhlení
        double y  = py + .4;
        //Vlastní realizace přesunu jako posloupnosti mikropřesunů
        for (int i=steps;   i > 0;   i--) {
            x += dx;
            y += dy;
            object.setPosition((int)x, (int)y); //Argumenty musí být int
            IO.pause(PERIOD);
        }
    }

//
//    /***************************************************************************
//     * Plynule přesune zadaný objekt o zadaný počet jednotek vzdálenosti.
//     *
//     * @param distance  Velikost posunu v jednotlivých směrech
//     * @param object    Přesouvaný objekt
//     */
//    public void moveBy(Position distance, IMovable object)
//    {
//        moveBy(distance.x(), distance.y(), object);
//    }
//

    /***************************************************************************
     * Plynule přesune zadaný objekt do požadované pozice.
     *
     * @param x       x-ová souřadnice požadované cílové pozice
     * @param y       y-ová souřadnice požadované cílové pozice
     * @param object  Přesouvaný objekt
     */
    public void moveTo(int x, int y, IMovable object)
    {
        int currentX = object.getX();
        int currentY = object.getY();
        moveBy(x-currentX, y-currentY, object);
    }

//
//    /***************************************************************************
//     * Plynule přesune zadaný objekt do požadované pozice.
//     *
//     * @param position  Cílová pozice
//     * @param object    Přesouvaný objekt
//     */
//    public void moveTo(Position position, IMovable object)
//    {
//        moveTo(position.x(), position.y(), object);
//    }
//

    /***************************************************************************
     * Převádí instanci na řetězec - používá se pro účely ladění.
     * Vrácený řetězec obsahuje název třídy následovaný identifikačním číslem
     * dané instance, které určuje pořadí dané instance mezi instancemi této
     * třídy, a nastavenou rychlostí přesunu.
     *
     * @return  Řetězec charakterizující instanci
     */
    @Override
    public String toString()
    {
        return name;
    }



//\IP== INSTANCE PRIVATE AND AUXILIARY METHODS =================================



//##############################################################################
//\NT== NESTED DATA TYPES ======================================================
}
