package mnohotvar;

import java.util.LinkedList;
import java.util.List;

import rup.česky.tvary.AHýbací;
import rup.česky.tvary.IHýbací;

import rup.česky.tvary.Barva;
import rup.česky.tvary.Směr8;

import rup.česky.tvary.AktivníPlátno;
import rup.česky.tvary.Čtverec;
import rup.česky.tvary.Obdélník;
import rup.česky.tvary.Elipsa;
import rup.česky.tvary.Trojúhelník;
import rup.česky.tvary.Kruh;
import rup.česky.tvary.Přesouvač;
import rup.česky.tvary.Kompresor;


/*******************************************************************************
 * Třída slouží k demonstraci práce se seznamy.
 * Mnohotvar je postupně skládán z řady jednodušších tvarů, které musejí být
 * instancemi rozhraní IHýbací. Jiné požadavky na ně kladeny nejsou.
 * Při sestavování mnohotvar automaticky mění svoji pozici a rozměr tak,
 * aby pozice byla neustále v levém rohu opsaného obdélníka a rozměr mnohotvaru
 * odpovídal rozměru tohoto obdélníka.
 *
 * Oproti třídě Mnohotvar_13a se změnilo:
 * - Při změně rozměru se čísla typu double nepřetypovávají na int,
 *   ale místo toho se zaokrouhlují.
 *
 * @author    Rudolf Pecinovský
 * @version   0.00.000,  0.0.2003
 */
public class Mnohotvar_13b extends AHýbací
{
//== KONSTANTNÍ ATRIBUTY TŘÍDY =================================================
//== PROMĚNNÉ ATRIBUTY TŘÍDY ===================================================
//== KONSTANTNÍ ATRIBUTY INSTANCÍ ==============================================

    /** Seznam prvků, z nichž se mnohotvar skládá. */
    private final List<IHýbací> seznam = new LinkedList<IHýbací>();



//== PROMĚNNÉ ATRIBUTY INSTANCÍ ================================================
//== PŘÍSTUPOVÉ METODY VLASTNOSTÍ TŘÍDY ========================================
//== OSTATNÍ METODY TŘÍDY ======================================================

//##############################################################################
//== KONSTRUKTORY A TOVÁRNÍ METODY =============================================

    /***************************************************************************
     * Vytvoří prázdný mnohotvar,
     * který převezme název generovaný rodičovskou třídou     .
     */
    public Mnohotvar_13b()
    {
        this( "" );
    }


    /***************************************************************************
     * Definuje prázdný mnohotvar se zadaným názvem.
     *
     * @param název  Název vytvářeného mnohotvaru.
     */
    public Mnohotvar_13b(String název)
    {
        super( 0, 0, 0, 0 );
        if( název != "" )
            this.název = název;
    }



//== PŘÍSTUPOVÉ METODY VLASTNOSTÍ INSTANCÍ =====================================
//== PŘEKRYTÉ METODY IMPLEMENTOVANÝCH ROZHRANÍ =================================
//== PŘEKRYTÉ ABSTRAKTNÍ METODY RODIČOVSKÉ TŘÍDY ===============================

    /***************************************************************************
     * Nakreslí mnohotvar pomocí dodaného kreslítka.
     *
     * @param kreslitko   Kreslítko dodané aktivním plátnem
     */
    public void nakresli(rup.česky.tvary.Kreslítko kreslítko)
    {
        for( IHýbací ih : seznam )
        {
            ih.nakresli( kreslítko );
        }
    }



//== PŘEKRYTÉ KONKRÉTNÍ METODY RODIČOVSKÉ TŘÍDY ================================

    /***************************************************************************
     * Přemístí celý mnohotvar na zadanou pozici.
     * Všechny součásti instance se přemisťují jako celek
     *
     * @param x  Nastavovaná vodorovná souřadnice
     * @param y  Nastavovaná nastavovaná svislá souřadnice
     */
    public void setPozice( int x, int y )
    {
        int dx = x - xPos;
        int dy = y - yPos;
        AP.nekresli();
            for( IHýbací ih : seznam )
            {
                ih.setPozice( dx + ih.getX(), dy + ih.getY() );
            }
            super.setPozice( x, y );
        AP.vraťKresli();
    }


    /***************************************************************************
     * Nastaví nový rozměr mnohotvaru. Upraví rozměry a pozice všech jeho
     * souřástí tak, aby výsledný mnohotvar i při novém rozměru stejný vzhled.
     *
     * @param šířka  Nastavovaná šířka
     * @param výška  Nastavovaná výška
     */
    public void setRozměr( int šířka, int výška )
    {
        //Zapamatuj si poměry změny šířky a výšky celého obrazce
        double ss = (double)šířka / this.šířka;
        double vv = (double)výška / this.výška;

        //Uprav velikosti a pozice jednotlivých částí
        AP.nekresli();
            for( IHýbací ih : seznam )
            {
                //Objekty s nulovými rozměry svou velikost nemění
                if( (ih.getŠířka() == 0)  ||  (ih.getVýška() == 0) )
                    continue;
                ih.setRozměr( (int)Math.round(ss * ih.getŠířka()),
                              (int)Math.round(vv * ih.getVýška()) );
                //Při změně velikosti se podobjekt také posune
                int dhx = (int)Math.round((ih.getX() - xPos) * ss);
                int dhy = (int)Math.round((ih.getY() - yPos) * vv);
                ih.setPozice( (xPos + dhx), (yPos + dhy));
            }
            super.setRozměr( šířka, výška );
        AP.vraťKresli();
    }



//== NOVĚ ZAVEDENÉ METODY INSTANCÍ =============================================

    /***************************************************************************
     * Přidá do mnohotvaru zadaný prvek a příslušně upraví novou
     * pozici a velikost mnohotvaru.
     *
     * @param ih  Přidávaný hýbací tvar
     */
    public void přidej( IHýbací ih )
    {
        if( seznam.contains( ih ) )
            throw new IllegalArgumentException( "V obrazci " + this.název +
                " je přidávaný prvek již zahrnut.\n   Přidáváno: " + ih);

        if( seznam.isEmpty() )  //Přidáváme první
        {
            xPos  = ih.getX();
            yPos  = ih.getY();
            šířka = ih.getŠířka();
            výška = ih.getVýška();
        }
        else                    //Přidáváme další
        {
            int ihx = ih.getX();
            int ihy = ih.getY();
            int ihš = ih.getŠířka();
            int ihv = ih.getVýška();

            if( ihx < xPos )
            {
                šířka += xPos - ihx;
                xPos = ihx;
            }
            if( ihy < yPos )
            {
                výška += yPos - ihy;
                yPos = ihy;
            }
            if( (xPos + šířka) < (ihx + ihš) )
                šířka = ihx + ihš - xPos;
            if( (yPos + výška) < (ihy + ihv) )
                výška = ihy + ihv - yPos;
        }
        AP.nekresli();
            AP.odstraň( ih );
            seznam.add( ih );
        AP.vraťKresli();
    }



//== SOUKROMÉ A POMOCNÉ METODY TŘÍDY ===========================================
//== SOUKROMÉ A POMOCNÉ METODY INSTANCÍ ========================================
//== VNOŘENÉ A VNITŘNÍ TŘÍDY ===================================================
//== TESTY A METODA MAIN =======================================================
}


