/*
 * ll_consolehandler.h
 *
 *  Created on: Nov 7, 2019
 *      Author: abody
 */

#pragma once

#include <f4ll/initialized_singleton.h>
#include <f4ll/ringbuffer.h>
#include <f4ll/usart_core.h>

#include <platform/dma_ll.h>

namespace f4ll {

class console_handler : public usart_core, public initialized_singleton<console_handler>
{
    friend class initialized_singleton<console_handler>;

public:
    using size_type = iringbuffer::size_type;

    class iconsole_input
    {
    public:
        virtual void input_available(size_type len) = 0;
    };

    void print(char const *s);
    void flush();
    size_type append(char const *s);

    iringbuffer &get_rx_buffer() { return m_rx_buffer; }

private:
    console_handler(
        USART_TypeDef *usart, DMA_TypeDef *dma, uint32_t stream_rx, uint32_t stream_tx, uint8_t *rx_buffer, size_type x_buffer_size,
        uint8_t *tx_buffer, size_type tx_buffer_size, iconsole_input *rx_callback);

    void setup_receive(void);

    // LL_UsartCore pure virtual function implementations
    virtual void receiver_idle(void) override;
    virtual void transmission_complete(void) override;
    virtual void framing_error(void) override;
    virtual void overrun(void) override;
    virtual void rx_dma_transfer_complete(void) override;
    virtual void rx_dma_half_transfer(void) override;
    virtual void rx_dma_error(dma_helper::dma_error_type reason) override;
    virtual void tx_dma_transfer_complete(void) override;
    virtual void tx_dma_half_transfer(void) override;
    virtual void tx_dma_error(dma_helper::dma_error_type reason) override;

    ringbuffer_ext m_tx_buffer;
    size_type m_bytes_sent = 0;

    ringbuffer_ext m_rx_buffer;
    size_type m_bytes_requested = 0;
    size_type m_reqd_bytes_registered = 0;
    iconsole_input *m_rx_callback;
};

} /* namespace f4ll */
