package shapes77.canvasmanager;
/* Saved in UTF-8 codepage: Příliš žluťoučký kůň úpěl ďábelské ódy. ÷ × ¤ */

import shapes77.util.NamedColor;

import java.awt.Color;
import java.awt.Font;
import java.awt.Graphics2D;
import java.awt.Image;
import java.awt.geom.AffineTransform;



/*******************************************************************************
 * Třída {@code Painter} slouží k zprostředkování kreslících schopností
 * objektům přihlášeným u správce plátna – instance třídy {@code CanvasManager}.
 * Jejím hlavím úkolem je zjednodušit tuto komunikaci pro začínající uživatele.
 * Je konstruován jako adaptér instance třídy {@code java.awt.Graphics2D}
 * na české prostředí tvarů.
 *
 * @author  Rudolf PECINOVSKÝ
 * @version 2020-Winter
 */
public class Painter
{
//\CC== CLASS CONSTANTS (CONSTANT CLASS/STATIC ATTRIBUTES/FIELDS) ==============

    /** Pozorovatel obrázků, který ví, že pozorované obrázky
     * se již nebudou měnit, protože jsou celé načtené hned od počátku. */
    public static final ImageObserver IMG_OBSERVER = new ImageObserver();



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



//##############################################################################
//\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) ===============

    /** Adaptovaný grafický kontext. */
    private final Graphics2D g;



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



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

    /***************************************************************************
     * Vytvoří nové kreslítko jako obalový typ
     * kolem zadané instance třídy {@code java.awt.Graphics2D}.
     * Předpokládá, že bude volán pouze ze správce plátna, jehož mateřská
     * třída je ve stejném balíčku &ndash; proto je {@code package private}.
     *<p>
     *
     * @param g Obalovaná instance
     */
    Painter(Graphics2D g)
    {
        this.g = g;
    }



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

    /***************************************************************************
     * Vrátí font, kterým se sází vypisované texty.
     *
     * @return Aktuálně používaný font
     */
    public Font getFont()
    {
        return g.getFont();
    }


    /***************************************************************************
     * Nastaví font, kterým se budou sázet vypisované texty.
     * Všechny následující operace používají tento font.
     * Parametr {@code null} je tiše ignorován.
     *
     * @param font  Nastavované písmo.
     */
    public void setFont(Font font)
    {
        g.setFont(font);
    }


    /***************************************************************************
     * Vrátí aktuálně používanou barvu pozadí.
     *
     * @return Aktuálně používaná barva pozadí
     */
    public NamedColor getBackground()
    {
        Color      awtColor   = g.getBackground();
        NamedColor namedColor = NamedColor.getNamedColor(
                                awtColor.getRed(),  awtColor.getGreen(),
                                awtColor.getBlue(), awtColor.getAlpha());
        return namedColor;
    }


    /***************************************************************************
     * Nastaví barvu pozadí.
     *
     * @param color Nastavovaná barva pozadí
     */
    public void setBackground(NamedColor color)
    {
        g.setBackground(color.getAWTColor());
    }


    /***************************************************************************
     * Vrátí zabalený grafický kontext.
     *
     * @return Zabalený grafický kontext
     */
    public Graphics2D getGraphics()
    {
        return g;
    }



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

    /***************************************************************************
     * Vykreslí zadanou barvou na zadaných souřadnicích nevyplněný ovál
     * zadaného rozměru. Souřadnicí elipsy se přitom rozumí souřadnice
     * levého horního rohu opsaného obdélníku.
     *
     * @param x       x-ová souřadnice instance, x=0 má levý okraj plátna
     * @param y       y-ová souřadnice instance, y=0 má horní okraj plátna
     * @param width   Šířka kresleného oválu
     * @param height  Výška kresleného oválu
     * @param color   Barva kresleného oválu
     */
    public void drawEllipse(int x, int y, int width, int height,
                            NamedColor color)
    {
        g.setColor(color.getAWTColor());
        g.drawOval(x, y, width, height);
    }


    /***************************************************************************
     * Vykreslí zadanou barvou na zadaných souřadnicích vyplněný ovál
     * zadaného rozměru. Souřadnicí elipsy se přitom rozumí souřadnice
     * levého horního rohu opsaného obdélníku.
     *
     * @param x       x-ová souřadnice instance, x=0 má levý okraj plátna
     * @param y       y-ová souřadnice instance, y=0 má horní okraj plátna
     * @param width   Šířka kresleného oválu
     * @param height  Výška kresleného oválu
     * @param color   Barva kresleného oválu
     */
    public void fillEllipse(int x, int y, int width, int height,
                            NamedColor color)
    {
        g.setColor(color.getAWTColor());
        g.fillOval(x, y, width, height);
    }


    /***************************************************************************
     * Vykreslí zadanou barvou na zadaných souřadnicích nevyplněný obdélník
     * zadaného rozměru. Souřadnicí obdélníku se přitom rozumí souřadnice
     * jeho levého horního rohu.
     *
     * @param x       x-ová souřadnice instance, x=0 má levý okraj plátna
     * @param y       y-ová souřadnice instance, y=0 má horní okraj plátna
     * @param width   Šířka kresleného obdélníku
     * @param height  Výška kresleného obdélníku
     * @param color   Barva kresleného obdélníku
     */
    public void drawRectangle(int x, int y, int width, int height,
                              NamedColor color)
    {
        g.setColor(color.getAWTColor());
        g.drawRect(x, y, width, height);
    }


    /***************************************************************************
     * Vykreslí zadanou barvou na zadaných souřadnicích vyplněný obdélník
     * zadaného rozměru. Souřadnicí obdélníku se přitom rozumí souřadnice
     * jeho levého horního rohu.
     *
     * @param x       x-ová souřadnice instance, x=0 má levý okraj plátna
     * @param y       y-ová souřadnice instance, y=0 má horní okraj plátna
     * @param width   Šířka kresleného obdélníku
     * @param height  Výška kresleného obdélníku
     * @param color   Barva kresleného obdélníku
     */
    public void fillRectangle(int x, int y, int width, int height,
                              NamedColor color)
    {
        g.setColor(color.getAWTColor());
        g.fillRect(x, y, width, height);
    }


    /***************************************************************************
     * Zadanou barvou nakreslí nevyplněný mnohoúhelník se zadanými vrcholy.
     * Vrcholy jsou definovány odpovídajícími páry souřadnic v polích
     * <b>{@code x}</b> e <b><code>y</code></b>.
     *
     * @param x     Pole x-ových souřadnic vrcholů, x=0 má levý okraj plátna
     * @param y     Pole y-ových souřadnic vrcholů, y=0 má horní okraj plátna
     * @param color Barva kresleného polygonu
     */
    public void drawPolygon(int[] x, int[] y, NamedColor color)
    {
        g.setColor(color.getAWTColor());
        g.drawPolygon(x, y, Math.min(x.length, y.length));
    }


    /***************************************************************************
     * Zadanou barvou nakreslí vyplněný mnohoúhelník se zadanými vrcholy.
     * Vrcholy jsou definovány odpovídajícími páry souřadnic v polích
     * <b>{@code x}</b> e <b><code>y</code></b>.
     *
     * @param x     Pole x-ových souřadnic vrcholů, x=0 má levý okraj plátna
     * @param y     Pole y-ových souřadnic vrcholů, y=0 má horní okraj plátna
     * @param color Barva kresleného polygonu
     */
    public void fillPolygon(int[] x, int[] y, NamedColor color)
    {
        g.setColor(color.getAWTColor());
        g.fillPolygon(x, y, Math.min(x.length, y.length));
    }


    /***************************************************************************
     * Zadanou barvou nakreslí úsečku se zadanými krajními body.
     *
     * @param x1    x-ová souřadnice počátku, x=0 má levý okraj plátna
     * @param y1    y-ová souřadnice počátku, y=0 má horní okraj plátna
     * @param x2    x-ová souřadnice konce
     * @param y2    y-ová souřadnice konce
     * @param color Barva kreslené úsečky
     */
    public void drawLine(int x1, int y1, int x2, int y2, NamedColor color)
    {
        g.setColor(color.getAWTColor());
        g.drawLine(x1, y1, x2, y2);
    }


    /***************************************************************************
     * Vykreslí přednastaveným písmem zadaný trext na zadaných souřadnicích
     * a zadanou barvou.
     *
     * @param text  Zobrazovaný text
     * @param x     Vodorovná souřadnice levého horního rohu opsaného obdélníku
     * @param y     Svislá souřadnice levého horního rohu opsaného obdélníku
     * @param color Barva vykreslovaného textu
     */
    public void drawText(String text, int x, int y, NamedColor color)
    {
        g.setColor(color.getAWTColor());
        g.drawString(text, x, y);
    }


    /***************************************************************************
     * Nakreslí zadaný obrázek na zadané souřadnice.
     *
     * @param x     Vodorovná souřadnice levého horního rohu
     * @param y     Svislá souřadnice levého horního rohu
     * @param image Kreslený obrázek
     * @param at    Afinní transformace použitá při změně rozměru obrázku
     */
    public void drawPicture(int x, int y, Image image,
                            AffineTransform at)
    {
        if (at == null) {
            g.drawImage(image, x, y, IMG_OBSERVER);
        }
        else {
            g.drawImage(image, at, IMG_OBSERVER);
        }
    }



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



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

    /***************************************************************************
     * Instance třídy ImageObserver slouží k předání informací o tom,
     * že požadovaný obrázek je již načten.
     */
    public static class ImageObserver implements java.awt.image.ImageObserver
    {
        /***********************************************************************
         * Metoda je volaná v okamžiku, kdy jsou k dispozici infomrace o před
         * tím požadovaném obrázku.
         * {@inheritDoc}
         * @param img       Pozorovaný obrázek
         * @param infoflags Bitový OR několika příznaků
         * @param x         Vodorovná souřadnice
         * @param y         Svislá souřadnice
         * @param width     Šířka
         * @param height    Výška
         * @return {@code true} bude-li se obrázek ještě v budnoucnu měnit
         *         (není ještě celý načten),
         *         {@code false} je-li definitivní
         */
        @Override
        public boolean imageUpdate(Image img, int infoflags,
                       int x, int y, int width, int height)
        {
            //Obrázek se již nebude měnit tím, že by se donačetl
            return false;
        }
    }

}
