package rup.česky.tvary_5;

import java.util.ArrayList;
import java.util.List;
import java.util.HashMap;
import java.util.Map;


/*******************************************************************************
 * Třída sloužící jako výčtový typ pro 8 hlavních světových stran.
 * Třída je zjednodušenou verzí stejnojmenné třídy z balíčku rup.spolecne.
 *
 * @author     Rudolf Pecinovský
 * @version    2.01, duben 2004
 */
public enum Směr8
{
//== HODNOTY VÝČTOVÉHO TYPU ====================================================
    
    VÝCHOD      (  1,  0, "S",  "VÝCHOD",       "VYCHOD"),  
    SEVEROVÝCHOD(  1, -1, "SV", "SEVEROVÝCHOD", "SEVEROVYCHOD"),
    SEVER       (  0, -1, "S",  "SEVER",        "SEVER"),   
    SEVEROZÁPAD ( -1, -1, "SZ", "SEVEROZÁPAD",  "SEVEROZAPAD"), 
    ZÁPAD       ( -1,  0, "Z",  "ZÁPAD",        "ZAPAD"), 
    JIHOZÁPAD   ( -1,  1, "JZ", "JIHOZÁPAD",    "JIHOZAPAD"), 
    JIH         (  0,  1, "J",  "JIH",          "JIH"), 
    JIHOVÝCHOD  (  1,  1, "JV", "JIHOVÝCHOD",   "JIHOVYCHOD"), ;  
    
    
//== KONSTANTNÍ ATRIBUTY TŘÍDY =================================================
    
    public  static final int SMĚRŮ = 8;
    private static final int MASKA = 7;
    
    private static final Map<String,Směr8> názvy = 
                                        new HashMap<String,Směr8>( SMĚRŮ*3 );
    private static final int[][] posun = new int[SMĚRŮ][2];

    private static final Směr8[] SMĚRY = values();    
    
    static
    {
        for( Směr8 s : SMĚRY )
        {
            posun[s.ordinal()][0] = s.přepravka.dx;
            posun[s.ordinal()][1] = s.přepravka.dy;
            názvy.put( s.přepravka.zkratka, s );
            názvy.put( s.přepravka.název,   s );
            názvy.put( s.přepravka.názevBHC,s );
            s.přepravka = null;
        }
    }
    
//== PROMĚNNÉ ATRIBUTY TŘÍDY ===================================================
//== KONSTANTNÍ ATRIBUTY INSTANCÍ ==============================================
//== PROMĚNNÉ ATRIBUTY INSTANCÍ ================================================
    
    private static class Přepravka
    {
        int    dx, dy;
        String zkratka, název, názevBHC;
    }
    Přepravka přepravka;
    
    
//== PŘÍSTUPOVÉ METODY VLASTNOSTÍ TŘÍDY ========================================
//== OSTATNÍ METODY TŘÍDY ======================================================

//##############################################################################
    
    /**************************************************************************
     * Vytvoří nový směr a zapamatuje si různé verze jeho názvu.
     */
     private Směr8( int dx, int dy, 
                    String zkratka, String název, String názevBHC )
     {
         přepravka = new Přepravka();
         přepravka.dx = dx;
         přepravka.dy = dy;
         přepravka.zkratka = zkratka;
         přepravka.název = název;
         přepravka.názevBHC = názevBHC;
     }
     
     
     
//== KONSTRUKTORY A TOVÁRNÍ METODY =============================================
//== PŘÍSTUPOVÉ METODY ATRIBUTU INSTANCÍ =======================================
//== VLASTNI METODY INSTANCÍ ===================================================

    /**************************************************************************
     * Vráti směr otočený o 180°.
     * Oproti metodě čelemVzad nepotřebuje přetypovávat výsledek na Směr8.
     *
     * @return Směr objektu po vyplněni příkazu čelem vzad
     */
    public Směr8 čelemVzad()
    {
        return SMĚRY[MASKA & (4+ordinal())];
    }


    /**************************************************************************
     * Vráti směr otočený o 90° vlevo.
     * Oproti metodě vlevoVbok nepotřebuje přetypovávat výsledek na Směr8.
     *
     * @return Směr objektu po vyplněni příkazu vlevo v bok
     */
    public Směr8 vlevoVbok()
    {
        return SMĚRY[MASKA & (2+ordinal())];
    }


    /**************************************************************************
     * Vráti směr otočený o 90° vpravo.
     * Oproti metodě vpravoVbok nepotřebuje přetypovávat výsledek na Směr8.
     *
     * @return Směr objektu po vyplněni příkazu vpravo v bok
     */
    public Směr8 vpravoVbok()
    {
        return SMĚRY[MASKA & (-2+ordinal())];
    }


    /**************************************************************************
     * Vráti směr otočený o 45° vlevo.
     * Oproti metodě nalevoVpříč nepotřebuje přetypovávat výsledek na Směr8.
     *
     * @return Směr objektu po vyplneni prikazu nalevo vpric
     */
    public Směr8 nalevoVpříč()
    {
        return SMĚRY[MASKA & (1+ordinal())];
    }


    /**************************************************************************
     * Vráti směr otočený o 45° vpravo.
     * Oproti metodě napravoVpříč nepotřebuje přetypovávat výsledek na Směr8.
     *
     * @return Směr objektu po vyplneni prikazu napravo vpric
     */
    public Směr8 napravoVpříč()
    {
        return SMĚRY[MASKA & (-1+ordinal())];
    }


    /**************************************************************************
     * Vrátí x-vou souřadnici sousedního políčka v daném směru.
     *
     * @param x x-ová souřadnice stávajícího políčka
     *
     * @return x-ová souřadnice sousedního políčka v daném směru
     */
    public int dalšíX( int x )
    {
        return x + posun[ordinal()][0];
    }


    /**************************************************************************
     * Vrátí y-vou souřadnici sousedního políčka v daném směru.
     *
     * @param y y-ová souřadnice stávajícího políčka
     *
     * @return y-ová souřadnice sousedního políčka v daném směru
     */
    public int nextY( int y )
    {
        return y + posun[ordinal()][1];
    }


    /**************************************************************************
     * Vrátí pozici sousedního políčka v daném směru.
     *
     * @param pozice pozice stávajícího políčka
     *
     * @return Pozice sousedního políčka v daném směru
     */
    public Pozice nextPozice( Pozice pozice )
    {
        return new Pozice( pozice.getX() + posun[ordinal()][0],
                           pozice.getY() + posun[ordinal()][1] );
    }


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

