/**
 * @file Widget.h
 * @author apio (cloudapio.eu)
 * @brief Abstract widget class.
 *
 * @copyright Copyright (c) 2023, the Luna authors.
 *
 */

#pragma once
#include <luna/Ignore.h>
#include <luna/Result.h>
#include <ui/Canvas.h>
#include <ui/Point.h>
#include <ui/Rect.h>
#include <ui/ipc/Client.h>

namespace ui
{
    class Window;

    enum class EventResult
    {
        DidHandle,
        DidNotHandle,
    };

    class Widget
    {
      public:
        Widget(Window* window, Widget* parent) : m_window(window), m_parent(parent)
        {
        }

        virtual Result<EventResult> handle_mouse_move(Point position)
        {
            ignore(position);
            return EventResult::DidNotHandle;
        }

        virtual Result<EventResult> handle_mouse_down(Point position, int buttons)
        {
            ignore(position, buttons);
            return EventResult::DidNotHandle;
        }

        virtual Result<EventResult> handle_mouse_up(Point position, int buttons)
        {
            ignore(position, buttons);
            return EventResult::DidNotHandle;
        }

        virtual Result<EventResult> handle_mouse_leave()
        {
            return EventResult::DidNotHandle;
        }

        virtual Result<EventResult> handle_key_event(const ui::KeyEventRequest& request)
        {
            ignore(request);
            return EventResult::DidNotHandle;
        }

        virtual Result<void> draw(Canvas& canvas);

        void set_rect(Rect rect, Badge<Window>)
        {
            m_rect = rect;
        }

        void resize(Rect rect)
        {
            m_preferred_rect = rect;
        }

        Widget* parent()
        {
            return m_parent;
        }

        Window* window()
        {
            return m_window;
        }

        Rect& rect()
        {
            return m_rect;
        }

        Rect pseudo_rect()
        {
            return m_pseudo_rect;
        }

        Rect preferred_rect()
        {
            return m_preferred_rect.value_or({ 0, 0, 50, 50 });
        }

        virtual void recalculate_pseudo_rects()
        {
            m_pseudo_rect = preferred_rect();
            return;
        }

        virtual void recalculate_true_rects()
        {
            return;
        }

        virtual void show_tree(int indent) = 0;

      protected:
        Window* m_window;
        Widget* m_parent { nullptr };

        Option<Rect> m_preferred_rect;

        Rect m_pseudo_rect;
        Rect m_rect { 0, 0, 50, 50 };
    };
}