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

import shapes77.canvasmanager.Ellipse;
import shapes77.canvasmanager.ICMPaintable;
import shapes77.canvasmanager.Painter;
import shapes77.geom.IChangeable;
import shapes77.util.IO;
import shapes77.util.NamedColor;
import shapes77.util.Repeater;


/*******************************************************************************
 * Instance třídy představují světla, která je možné rozsvítit a zhasnout.
 * Oproti verzi z 15. kapitoly umí nezávisle blikat.
 */
public   class Light
    implements IChangeable, ICMPaintable
{
//\CC== CLASS CONSTANTS (CONSTANT CLASS/STATIC ATTRIBUTES/FIELDS) ==============

    /** Implicitní průměr světla. */
    private static final int        DEFAULT_SIZE  = 50;

    /** Implicitní barva vytvářených instancí. */
    private static final NamedColor DEFAULT_COLOR = NamedColor.RED;

    /** Barva zhasnutého světla. */
    private static final NamedColor OFF_COLOR     = NamedColor.DARK_GRAY;

    /** Počet milisekund, po něž je blikající světlo zhasnuté,
     *  resp. rozsvícené. */
    private static final int PAUSE = 500;



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

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



//##############################################################################
//\CG== CLASS (STATIC) GETTERS AND SETTERS =====================================

    /***************************************************************************
     * Vrátí počet doposud vytvořených instancí.
     *
     * @return  Počet doposud vytvořených instancí
     */
    public static int instances() {
        return instances;
    }



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

    /** Identifikační ("rodné") číslo instance. */
    private final int ID = ++instances;

    /** Elipsa představující žárovku schopnou měnit svoji barvu. */
    private final Ellipse bulb;

    /** Barva rozsvíceného světla. */
    private final NamedColor color;



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

    /** Opakovač – je nastaven pouze po dobu, kdy světlo bliká. */
    private Repeater repeater = null;



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

    /***************************************************************************
     * Vytvoří světlo implicitních rozměrů a barvy
     * umístěné na souřadnicích [0; 0].
     */
    public Light() {
        this(0, 0);
    }

    /***************************************************************************
     * Vytvoří světlo implicitních rozměrů a barvy
     * umístěné na zadaných souřadnicích.
     *
     * @param x  Vodorovná souřadnice vytvářeného světla
     * @param y  Svislá souřadnice vytvářeného světla
     */
    public Light(int x, int y) {
        this(x, y, DEFAULT_SIZE);
    }

    /***************************************************************************
     * Vytvoří světlo zadané velikost a implicitní barvy
     * umístěné na zadaných souřadnicích.
     *
     * @param x     Vodorovná souřadnice vytvářeného světla
     * @param y     Svislá souřadnice vytvářeného světla
     * @param size  Velikost vytvářeného světla
     */
    public Light(int x, int y, int size) {
        this(x, y, size, DEFAULT_COLOR);
    }

    /***************************************************************************
     * Vytvoří světlo zadané velikost a barvy
     * umístěné na zadaných souřadnicích.
     *
     * @param x     Vodorovná souřadnice vytvářeného světla
     * @param y     Svislá souřadnice vytvářeného světla
     * @param size  Velikost vytvářeného světla
     * @param color Barva rozsvíceného světla
     */
    public Light(int x, int y, int size, NamedColor color) {
        this.color = color;
        this.bulb  = new Ellipse(x, y, size, size, color);
    }



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

    /***************************************************************************
     * Vrátí barvu rozsvíceného světla.
     *
     * @return  Barva rozsvíceného světla
     */
    public NamedColor color() {
        return color;
    }

    /***************************************************************************
     * Vrátí informaci o tom, je-li světlo rozsvícené.
     *
     * @return  Je-li světlo rozsvícené, vrátí {@code true},
     *          není-li, vrátí {@code false}
     */
    public boolean isOn() {
        return color == bulb.getColor();
    }

    /***************************************************************************
     * 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 bulb.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 bulb.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) {
        bulb.setPosition(x, y);
    }

    /***************************************************************************
     * Vrátí aktuální šířku instance.
     * Šířka instance jsou přitom definována jako šířka
     * opsaného obdélníku.
     *
     * @return  Aktuální šířka instance
     */
    @Override
    public int getWidth() {
        return bulb.getWidth();
    }

    /***************************************************************************
     * Vrátí aktuální výšku instance.
     * Výška instance jsou přitom definována jako výška
     * opsaného obdélníku.
     *
     * @return  Aktuální výška instance
     */
    @Override
    public int getHeight() {
        return bulb.getHeight();
    }

    /***************************************************************************
     * Nastaví nové rozměry instance.
     * Rozměry instance jsou přitom definovány jako rozměry
     * opsaného obdélníku.
     * Nastavované rozměry musí být nezáporné,
     * místo nulového rozměru se nastaví rozměr rovný jedné.
     *
     * @param width   Nově nastavovaná šířka; šířka &gt;= 0
     * @param height  Nově nastavovaná výška; výška &gt;= 0
     */
    public void setSize(int width, int height) {
        bulb.setSize(width, height);
    }



//\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)
    {
        bulb.paint(painter);
    }


    /***************************************************************************
     * Zhasne dané světlo, tj. vybarví je barvou pro zhasnuté světlo.
     */
    public void switchOff() {
        bulb.setColor(OFF_COLOR);
    }

    /***************************************************************************
     * Rozsvítí dané světlo, tj. vybarví je barvou rozsvíceného světla.
     */
    public void switchOn() {
        bulb.setColor(color);
    }

    /***************************************************************************
     * Vrátí textový podpis instance sestávající z názvu mateřské třídy,
     * "rodného čísla" instance a jejích souřadnic, velikosti a barvy.
     *
     * @return Textový podpis instance
     */
    public String toString() {
        return "Light_" + ID + "(x=" + bulb.getX() + ", y=" + bulb.getY()
             + ", size=" + bulb.getWidth() + ", color=" + color + ")";
    }

    /***************************************************************************
     * Rozbliká světlo nezávisle na ostatních akcích, které zrovna provádí.
     */
    public void blink() {
        Runnable action = () -> {
            switchOn();     IO.pause(PAUSE);
            switchOff();    IO.pause(PAUSE);
        };
        repeater = new Repeater();
        repeater.repeat(0, action);
    };

    /***************************************************************************
     * Ukončí blikání.
     */
    public void stop() {
        repeater.stop();
        repeater = null;
    };



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



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