package robotcz;
/* Saved in UTF-8 codepage: Příliš žluťoučký kůň úpěl ďábelské ódy. ÷ × ¤
 * Check: «Stereotype», Section mark-§, Copyright-©, Alpha-α, Beta-β, Smile-☺
 */



/*******************************************************************************
 * Třída Instance třídy {@code Karel} představují ...
 *
 * @author  Rudolf PECINOVSKÝ
 * @version 1.05.9267_2023-03-11
 */
public  class       Karel
        implements  IKarel
{
//\CV== CLASS VARIABLES (VARIABLE CLASS/STATIC ATTRIBUTES/FIELDS) ==============

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



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

    /** Rodné číslo instance = pořadí jejího vzniku. */
    private final int ID;

    /** Svět daného robota. */
    private final RobotWorld world;



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

    /***************************************************************************
     * Vytvoří nového robota implicitní barvy otočeného na východ
     * a umístěného v levém spodním rohu dvorku.
     */
    public Karel()
    {
        this(-1, 0);
    }


    /***************************************************************************
     * Vytvoří nového robota implicitní barvy otočeného na východ
     * a umístěného v zadaném řádku a sloupci.
     *
     * @param row   Řádek   = Svislá    pozice vytvářeného robota
     * @param col   Sloupec = Vodorovná pozice vytvářeného robota
     */
    public Karel(int row, int col)
    {
        this(row, col, null, null);
    }


    /***************************************************************************
     * Vytvoří robota zadané barvy otočeného do zadaného směru
     * a umístí jej na dvorek na zadanou pozici.
     *
     * @param row   Řádek   = Svislá    pozice vytvářeného robota
     * @param col   Sloupec = Vodorovná pozice vytvářeného robota
     * @param dir   Směr natočení vytvářeného robota0
     */
    public Karel(int row, int col, Direction dir)
    {
        this(row, col, dir, null);
    }


    /***************************************************************************
     * Vytvoří robota zadané barvy otočeného do zadaného směru
     * a umístí jej na dvorek na zadanou pozici.
     *
     * @param row   Řádek   = Svislá    pozice vytvářeného robota
     * @param col   Sloupec = Vodorovná pozice vytvářeného robota
     * @param dir   Směr natočení vytvářeného robota
     * @param color Barva vytvářeného robota
     */
    public Karel(int row, int col, Direction dir, Color color)
    {
        ID    = ++count;
        world = RobotWorld.activeWorld();
        if (row<0)  { row += world.rows(); }
        if (col<0)  { col += world.cols(); }
        world.addRobot(this, row, col, dir, color);
    }



//\IM== INSTANCE REMAINING NON-PRIVATE METHODS =================================

    /***************************************************************************
     * Posune robota na další políčko ve změru, do nějž je natočen.
     * Je-li na daném políčku robot nebo zeď, ohlásí chybu.
     *
     * @return Odkaz na osloveného robota
     */
    @Override
    public Karel step()
    {
        world.step(this);
        return this;
    }


    /***************************************************************************
     * Otočí robotem o 90° vlevo.
     *
     * @return Odkaz na osloveného robota
     */
    @Override
    public Karel turnLeft()
    {
        world.turnLeft(this);
        return this;
    }


    /***************************************************************************
     * Položí značku na políčko, na němž stojí.
     * Je-li již na něm maximální povolený počet značek, ohlásí chybu.
     *
     * @return Odkaz na osloveného robota
     */
    @Override
    public Karel put()
    {
        world.put(this);
        return this;
    }


    /***************************************************************************
     * Zvedne značku z políčka, na němž stojí.
     * Není-li již na daném políčku žádná značka, ohlásí chybu.
     *
     * @return Odkaz na osloveného robota
     */
    @Override
    public Karel pick()
    {
        world.pick(this);
        return this;
    }


    /***************************************************************************
     * Vrátí informaci o tom, je-li na políčku pod robotem nějaká značka.
     *
     * @return Je-li na pod ním značka, vrátí {@code true},
     *         jinak vrátí {@code false}.
     */
    @Override
    public boolean isMarker()
    {
        return world.isMarker(this);
    }


    /***************************************************************************
     * Vrátí informaci o tom, je-li na políčku před robotem zeď.
     *
     * @return Je-li před ním zeď, vrátí {@code true},
     *         jinak vrátí {@code false}.
     */
    @Override
    public boolean isWall()
    {
        return world.isWallBefore(this);
    }


    /***************************************************************************
     * Vrátí informaci o tom, je-li robot otočen na východ.
     *
     * @return Je-li otočen na východ, vrátí {@code true}.
     *         jinak vrátí {@code false}.
     */
    @Override
    public boolean isEast()
    {
        return world.isTurnedToEast(this);
    }


    /***************************************************************************
     * Je-li na políčku před robotem jiný robot, vrátí odkaz na tohoto robota,
     * jinak vrátí {@code null}.<br>
     * Správně by měla metoda vracet instanci typu {@link IKarel},
     * ale v začátečnických kurzech nepracujeme s jinými typy robotů,
     * a typ návratové hodnoty je proto zúžen.
     *
     * @return Odkaz na robota na políčku před ním, není-li, vrátí {@code null}.
     */
    @Override
    public Karel robotAhead()
    {
        return (Karel)(world.robotAhead(this));
    }


    /***************************************************************************
     * Přestane robota zobrazovat, čímž jeho činnost výrazně zrychlí.
     *
     * @return Odkaz na osloveného robota
     */
    @Override
    public Karel hide()
    {
        return (Karel)world.hide(this);
    }


    /***************************************************************************
     * Vrátí úroveň zobrazování do stavy před posledním skrytím.
     * Byl-li proto již tehdy skrytý (a tím pádem i zrychlený),
     * zůstane skrytý (a zrychlený) i nadále. Byl-li zobrazovaný,
     * začne se opět zobrazovat.
     *
     * @return Odkaz na osloveného robota
     */
    @Override
    public Karel unhide()
    {
        return (Karel)world.unhide(this);
    }


    /***********************************************************************
     * Vrátí textový podpis identifikující daného robota.
     *
     * @return Textový podpis identifikující daného robota
     */
    @Override
    public String toString()
    {
        String description;
        try {  description = world.toString(this);
        }catch (Exception e) {
               description = "{ ??? }";
        }
        return getClass().getSimpleName() + "_" + ID + description;
    }

}
