#ifndef LAYOUT_HPP_
#define LAYOUT_HPP_

#include <list>

#include <Widget/Widget.hpp>

/**
 * @brief Base class for layouts.
 */
class Layout : public Widget
{
public:
    template<int proportion>
    struct WithProportion
    {
        static constexpr int value = proportion;
    };

protected:
    struct ChildNode
    {
        glm::ivec2 pos;
        int proportion;
        Widget *widget;
    };

    std::vector<ChildNode> m_children;

    int m_nextProportion;

    inline void addChildren() {}
    
    template<typename... TChildren>
    inline void addChildren(Widget *child, TChildren... rest)
    {
        ChildNode node;
        node.pos = glm::ivec2(0, 0);
        node.widget = child;
        node.proportion = m_nextProportion;
        m_children.push_back(node);

        m_nextProportion = 0;
        addChildren(rest...);
    }

    template<int proportion, typename... TChildren>
    inline void addChildren(WithProportion<proportion> proportionSetting, TChildren... rest)
    {
        m_nextProportion = proportion;
        addChildren(rest...);
    }

    template<typename... TChildren>
    inline void addChildren(std::list<Widget*> widgets, TChildren... rest)
    {
        std::list<Widget*>::iterator it;
        for (it=widgets.begin(); it!=widgets.end(); ++it)
        {
            ChildNode node;
            node.pos = glm::ivec2(0, 0);
            node.widget = *it;
            node.proportion = m_nextProportion;
            m_children.push_back(node);
        }

        m_nextProportion = 0;
        addChildren(rest...);
    }

    template<typename... TChildren>
    inline void addChildren(std::vector<Widget*> widgets, TChildren... rest)
    {
        for (Widget *child : widgets)
        {
            ChildNode node;
            node.pos = glm::ivec2(0, 0);
            node.widget = child;
            node.proportion = m_nextProportion;
            m_children.push_back(node);
        }

        m_nextProportion = 0;
        addChildren(rest...);
    }

public:
    template<typename... TChildren>
    Layout(TChildren... children) : Widget(), m_nextProportion(0)
    {
        addChildren(children...);
    }

    virtual ~Layout();

    /**
     * @brief Lay out the children.
     * 
     * This method must set the `pos` field of each one to the position the child
     * should end up in (relative to this layout widget).
     */
    virtual void layout() = 0;

    virtual void onResize(glm::ivec2 newSize) override;
    virtual void draw(GraphicsContext &context) override;
    virtual void onMouseMoved(glm::ivec2 pos) override;
    virtual void onMouseDown(Uint8 button) override;
    virtual void onMouseUp(Uint8 button) override;
    virtual void onScroll(int delta) override;
    virtual void getInternalTabOrder(std::vector<Widget*> &tabOrder) override;
};

#endif