#ifndef CUSTOMBUTTONCONTAINER_HPP
#define CUSTOMBUTTONCONTAINER_HPP

#include <touchgfx/containers/Container.hpp>
#include <touchgfx/widgets/Image.hpp>

namespace touchgfx
{
/**
 * @class CustomButtonTrigger CustomButtonTrigger.hpp
 */
class CustomButtonContainer : public Container
{
public:

    /**
     * @fn CustomButtonContainer::CustomButtonContainer()
     *
     * @brief Default constructor.
     */
    CustomButtonContainer() : pressed(false), alpha(255), up(), down(), action(0)
    {
        setTouchable(true);
        buttonImage.setXY(0, 0);
        add(buttonImage);
    }

    /**
     * @fn virtual CustomButtonContainer::~CustomButtonContainer()
     *
     * @brief Destructor.
     */
    virtual ~CustomButtonContainer() {}

    /**
     * @fn virtual void CustomButtonContainer::setBitmaps(const Bitmap& bmpReleased, const Bitmap& bmpPressed)
     *
     * @brief Sets the bitmaps.
     *
     * @param bmpReleased The bitmap released.
     * @param bmpPressed  The bitmap pressed.
     */
    virtual void setBitmaps(const Bitmap& bmpReleased, const Bitmap& bmpPressed)
    {
        up = bmpReleased;
        down = bmpPressed;
        setWidth(down.getWidth());
        setHeight(down.getHeight());

        handlePressedUpdated();
    }

    /**
     * @fn void CustomButtonContainer::setBitmapXY(uint16_t x, uint16_t y)
     *
     * @brief Sets bitmap xy.
     *
     * @param x An uint16_t to process.
     * @param y An uint16_t to process.
     */
    void setBitmapXY(uint16_t x, uint16_t y)
    {
        buttonImage.setXY(x, y);
    }

    /**
     * @fn Bitmap CustomButtonContainer::getCurrentlyDisplayedBitmap() const
     *
     * @brief Gets currently displayed bitmap.
     *
     * @return The currently displayed bitmap.
     */
    Bitmap getCurrentlyDisplayedBitmap() const
    {
        return (pressed ? down : up);
    }

    /**
     * @fn void CustomButtonContainer::setPressed(bool isPressed)
     *
     * @brief Sets the pressed state.
     *
     * @param isPressed True if is pressed, false if not.
     */
    void setPressed(bool isPressed)
    {
        pressed = isPressed;
        handlePressedUpdated();
    }

    /**
     * @fn bool CustomButtonContainer::getPressed()
     *
     * @brief Gets the pressed state.
     *
     * @return True if it succeeds, false if it fails.
     */
    bool getPressed()
    {
        return pressed;
    }

    /**
     * @fn void CustomButtonContainer::setAlpha(uint8_t newAlpha)
     *
     * @brief Sets an alpha value.
     *
     * @param newAlpha The new alpha.
     */
    void setAlpha(uint8_t newAlpha)
    {
        alpha = newAlpha;
        handleAlphaUpdated();
    }

    /**
     * @fn uint8_t CustomButtonContainer::getAlpha() const
     *
     * @brief Gets the alpha.
     *
     * @return The alpha value.
     */
    uint8_t getAlpha() const
    {
        return alpha;
    }

    /**
     * @fn void CustomButtonContainer::setAction(GenericCallback< const CustomButtonContainer&, bool& >& callback)
     *
     * @brief Sets an action callback.
     *
     * @param callback The callback.
     */
    void setAction(GenericCallback< const CustomButtonContainer&, bool& >& callback)
    {
        action = &callback;
    }

    /**
     * @fn virtual void CustomButtonContainer::handleClickEvent(const ClickEvent& event)
     *
     * @brief Handles the click event described by event.
     *
     * @param event The event.
     */
    virtual void handleClickEvent(const ClickEvent& event)
    {
        bool wasPressed = getPressed();
        bool newPressedValue = (event.getType() == ClickEvent::PRESSED);
        if ((newPressedValue && !wasPressed) || (!newPressedValue && wasPressed))
        {
            setPressed(newPressedValue);
            invalidate();
            if (action->isValid())
            {
                action->execute(*this, pressed);
            }
        }
    }

    
protected:
    bool pressed;        ///< True if pressed
    uint8_t alpha;       ///< The current alpha value. 255 denotes solid, 0 denotes completely transparent.
    Image buttonImage; ///< The button image
    Bitmap  up;        ///< The image to display when button is released.
    Bitmap  down;      ///< The image to display when button is pressed.

    GenericCallback< const CustomButtonContainer&, bool&>* action;  ///< The action

    /**
     * @fn virtual void CustomButtonContainer::handlePressedUpdated()
     *
     * @brief Handles the pressed updated.
     */
    virtual void handlePressedUpdated() 
    {
        buttonImage.setBitmap(pressed ? down : up);
    }

    /**
     * @fn virtual void CustomButtonContainer::handleAlphaUpdated()
     *
     * @brief Handles the alpha updated.
     */
    virtual void handleAlphaUpdated()
    {
        buttonImage.setAlpha(alpha);
    }
};


} // namespace touchgfx

#endif // CUSTOMBUTTONCONTAINER_HPP
