#ifndef PRINT_H
#define PRINT_H

#include "baselayer.h"

#define EOL "\r\n"
#define BUFLEN 64

/**
 * @file
 * @brief Něco jako ostream.
 * 
 */

/// Základy pro zobrazení čísla.
enum PrintBases {
  BIN=1, OCT=3, DEC=10, HEX=4
};

/**
 * @class Print
 * @brief Třída pro výpisy do Down().
 * 
 * 
 * V main pak přibude jen definice instance této třídy
 * @code
    static  Print             print;
 * @endcode
 * a ukázka, jak se s tím pracuje:
 * @snippet main.cpp Main print example
 * Nic na tom není - operátor << má přetížení pro string, číslo a volbu formátu čísla (enum PrintBases).
 * Výstup je pak do bufferu a aby nám to "neutíkalo", tedy aby se vypsalo vše,
 * zavedeme blokování, vycházející z toho, že spodní třída vrátí jen počet bytů,
 * které skutečně odeslala. Při čekání spí, takže nepoužívat v přerušení.
 * @snippet src/print.cpp Block example
 * Toto blokování pak není použito ve vrchních třídách stacku,
 * blokovaná metoda je BlockDown(). Pokud bychom použili přímo Down(), blokování by pak
 * používaly všechny vrstvy nad tím. A protože mohou Down() používat v přerušení, byl by problém.
 *
 * Metody pro výpisy jsou sice dost zjednodušené, ale zase to nezabere
 * moc místa - pro ladění se to použít dá. Délka vypisovaného stringu není omezena
 * délkou použitého buferu.
 * 
 */

class Print : public BaseLayer {
  public:
    /// Konstruktor @param b Default decimální výpisy.
    Print     (PrintBases b = DEC);
    /// Blokování výstupu
    /// @param buf Ukazatel na data
    /// @param len Délka přenášených dat
    /// @return Počet přenesených bytů (rovno len)
    uint32_t  BlockDown   (const char * buf, uint32_t len);
    /// Výstup řetězce bytů
    /// @param str Ukazatel na řetězec
    /// @return Odkaz na tuto třídu kvůli řetězení.
    Print &    operator << (const char * str);
    /// Výstup celého čísla podle base
    /// @param num Číslo
    /// @return Odkaz na tuto třídu kvůli řetězení.
    Print &    operator << (const int   num);
    /// Změna základu pro výstup čísla
    /// @param num enum PrintBases
    /// @return Odkaz na tuto třídu kvůli řetězení.
    Print &    operator << (const PrintBases num);
    void out (const void* p, uint32_t l);
  private:
    PrintBases base;    //!< Základ pro výstup čísla.
    char  buf[BUFLEN];  //!< Buffer pro výstup čísla.
};

#endif // PRINT_H