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

import shapes77.canvasmanager.Multishape;
import shapes77.canvasmanager.Painter;
import shapes77.geom.Area;
import shapes77.geom.Direction8;
import shapes77.util.NamedColor;

import b77_java_nz2.vehicle.IVehicle4_4;


/*******************************************************************************
 * Instance třídy {@code Robot1E_3} reprezentují na východ otočená vozidla,
 * která znají svůj směr a umějí měnit svoji pozici a velikost.
 * Oproti minulé verzi umožňují zadat hlavní barvu vytvářeného vozidla
 * a znají sdruženou tovární třídu.
 */
public   class Robot4_4
    implements IVehicle4_4
{
//\CC== CLASS CONSTANTS (CONSTANT CLASS/STATIC ATTRIBUTES/FIELDS) ==============

    /** Implicitní hlaní barva vozidla. */
    public static final NamedColor DEFAULT_COLOR = NamedColor.RED;

    /** Implicitní směr výchozího natočení vozidla. */
    public static final Direction8 DEFAULT_DIRECTION = Direction8.EAST;



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

    /** Počet vytořených instancí. */
    private static int instances = 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í (rodné) číslo vytvářené instance. */
    private final int ID = ++instances;

    /** Hlavní barva vozidla. */
    private final NamedColor color;



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

    /** Jednosměrný podobjekt. */
    private ARobot1_4 singledir;

    /** Mnohotvar uchovávající grafickou podobu vytvořeného vozidla. */
    private Multishape multishape;



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

    /***************************************************************************
     * Vytvoří v implicitní pozici [0; 0] vozidlo implicitní velikosti 100
     * a zadané barvy otočené na východ.
     *
     * @param x Vodorovná souřadnice vytvářeného vozidla
     * @param y Svislá souřadnice vytvářeného vozidla
     * @param module Velikost vozidla = čtverce opsaného vytvářenému vozidlu
     * @param color  Hlavní barva vozidla
     * @param dir    Směr natočení vozidla
     */
    public Robot4_4(int x, int y, int module, NamedColor color, Direction8 dir)
    {
        this.color      = color;
        this.singledir  = ARobot1_4.newRobot1(color, dir);
        this.multishape = singledir.multishape();
        multishape.setArea(x, y, module, module);
    }

    /***************************************************************************
     * Vytvoří v implicitní pozici [0; 0] vozidlo implicitní barvy
     * a velikosti políčka plátna otočené na východ.
     */
    public Robot4_4() {
        this(0, 0, CM.getStep(), DEFAULT_COLOR, DEFAULT_DIRECTION);
    }

    /***************************************************************************
     * Vytvoří v zadané pozici vozidlo implicitní barvy
     * a velikosti políčka plátna otočené na východ.
     *
     * @param x Vodorovná souřadnice vytvářeného vozidla
     * @param y Svislá souřadnice vytvářeného vozidla
     */
    public Robot4_4(int x, int y) {
        this (x, y, CM.getStep(), DEFAULT_COLOR, DEFAULT_DIRECTION);
    }

    /***************************************************************************
     * Vytvoří v zadané pozici vozidlo zadané velikosti a implicitní barvy
     * otočené na východ.
     *
     * @param x Vodorovná souřadnice vytvářeného vozidla
     * @param y Svislá souřadnice vytvářeného vozidla
     * @param module Velikost vozidla = čtverce opsaného vytvářenému vozidlu
     */
    public Robot4_4(int x, int y, int module) {
        this(x, y, module, DEFAULT_COLOR, DEFAULT_DIRECTION);
    }

    /***************************************************************************
     * Vytvoří v zadané pozici vozidlo zadané velikosti a implicitní barvy
     * otočené na východ.
     *
     * @param x Vodorovná souřadnice vytvářeného vozidla
     * @param y Svislá souřadnice vytvářeného vozidla
     * @param color  Hlavní barva vozidla
     * @param dir    Směr natočení vozidla
     */
    public Robot4_4(int x, int y, NamedColor color, Direction8 dir) {
        this(x, y, CM.getStep(), color, dir);
    }



//\IA== INSTANCE ABSTRACT METHODS ==============================================
//\IG== INSTANCE GETTERS AND SETTERS ===========================================

    //===== Metody naprogramovatelné nezávisle na aktuálním směru natočení

    /***************************************************************************
     * Vrátí identifikační číslo instance.
     *
     * @return  Identifikační číslo instance
     */
    @Override
    public int ID() {
        return ID;
    }

    /***************************************************************************
     * Vrátí hlavní barvu vozidla.
     *
     * @return  Instance třídy {@link NamedColor} definující
     *          hlavní barvu vozidla
     */
    @Override
    public NamedColor color() {
        return color;
    }


    /***************************************************************************
     * Vrátí x-ovou (vodorovnou) souřadnici pozice instance,
     * tj. vodorovnou souřadnici levého horního rohu opsaného obdélníku.
     *
     * @return  Aktuální vodorovná (x-ová) souřadnice instance,
     *          x=0 má levý okraj plátna, souřadnice roste doprava
     */
    @Override
    public int getX() {
        return multishape.getX();
    }


    /***************************************************************************
     * Vrátí y-ovou (svislou) souřadnici pozice instance,
     * tj. svislou souřadnici levého horního rohu opsaného obdélníku.
     *
     * @return  Aktuální svislá (y-ová) souřadnice instance,
     *          y=0 má horní okraj plátna, souřadnice roste dolů
     */
    @Override
    public int getY() {
        return multishape.getY();
    }


    /***************************************************************************
     * Přemístí instanci na zadanou pozici.
     * Pozice instance je přitom definována jako pozice
     * levého horního rohu opsaného obdélníku.
     *
     * @param x  Nově nastavovaná vodorovná (x-ová) souřadnice instance,
     *           x=0 má levý okraj plátna, souřadnice roste doprava
     * @param y  Nově nastavovaná svislá (y-ová) souřadnice instance,
     *           y=0 má horní okraj plátna, souřadnice roste dolů
     */
    @Override
    public void setPosition(int x, int y) {
        multishape.setPosition(x, y);
    }


    /***************************************************************************
     * Vrátí velikost modulu, tj. délku strany opsaného čtverce.
     *
     * @return   Velikost modulu instance
     */
    @Override
    public int getModule() {
        return multishape.getWidth();
    }


    /***************************************************************************
     * Změní velikost instance, aby měl její nový modul
     * (= délku strany opsaného čtverce) zadanou velikost.
     *
     * @param module    Nově nastavovaný modul
     */
    @Override
    public void setModule(int module) {
        multishape.setSize(module, module);
    }



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

    /***************************************************************************
     * Prostřednictvím dodaného kreslítka vykreslí obraz své instance.
     *
     * @param painter Kreslítko schopné kreslit na plátno ovládané správcem
     */
    @Override
    public void paint(Painter painter) {
        multishape.paint(painter);
    }

    //===== Metody vyžadující k naprogramování znalost aktuálního směru natočení

    /***************************************************************************
     * Vrátí směr, do nějž je vozidlo právě natočeno.
     *
     * @return  Instance třídy {@link Direction8} definující
     *          směr, do nějž je vozidlo právě natočeno
     */
    @Override
    public Direction8 getDirection() {
        return singledir.direction();
    }

    /***************************************************************************
     * Přesune vozidlo o zadanou vzdálenost vpřed.
     *
     * @param distance Vzdálenost, o níž se má vozidlo přesunout
     */
    @Override
    public void forward(int distance) {
        singledir.forward(distance);
    }

    /***************************************************************************
     * Otočí instanci o 180°.
     */
    @Override
    public void turnAbout() {
        conform(singledir.turnedAbout());
    }

    /***************************************************************************
     * Otočí instanci o 90° vlevo.
     */
    @Override
    public void turnLeft() {
        conform(singledir.turnedLeft());
    }

    /***************************************************************************
     * Otočí instanci o 90° vpravo.
     */
    @Override
    public void turnRight(){
        conform(singledir.turnedRight());
    }

    /***************************************************************************
     * Vrátí textový podpis instance sestávající z názvu mateřské třídy
     * náslkedovaným jejími souřadnicemi a velikostí.
     *
     * @return Textový podpis instance
     */
    @Override
    public String toString() {
        return getClass().getSimpleName() + "_" + ID
             + "(x=" + multishape.getX() + ", y=" + multishape.getY()
             + ", size=" + multishape.getWidth() + ", dir=" + getDirection()
             + ")";
    }



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

    /***************************************************************************
     * Přesune obraz otočeného vozidla do správné oblasti
     */
    private void conform(ARobot1_4 newSingle) {
        CM.stopPainting(); {    //Nechceme zobrazovat průběh změn
            //Přestěhujeme otočený tvar na místo původního
            newSingle.multishape().setArea(multishape.getArea());
            singledir  = newSingle;     //Nastavíme nový jednosměrný objekt
            multishape = newSingle.multishape();    //a jeho mnohotvar
        } CM.returnPainting();  //Nyní necháme změnu zobrazit
    }

    /***************************************************************************
     * Otočí instanci do zadaného směru.
     * Druhá možnost definice metody pro otáčení vozidel.
     */
    private void turnTo(Direction8 dir) {
        Area area  = multishape.getArea();  //Zjisti zabranou oblast
        singledir  = ARobot1_4.newRobot1(color, dir);//Vytvoř správně otočeného
        multishape = singledir.multishape();
        multishape.setArea(area);           //Umísti otočeného do oblasti
    }



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