/**
 * @file App.h
 * @author apio (cloudapio.eu)
 * @brief UI application event loop.
 *
 * @copyright Copyright (c) 2023, the Luna authors.
 *
 */

#pragma once
#include <luna/HashMap.h>
#include <luna/StringView.h>
#include <os/EventLoop.h>
#include <os/IPC.h>
#include <ui/Window.h>

namespace ui
{
    class App
    {
      public:
        App();
        ~App();

        Result<void> init(StringView socket_path = "/tmp/wind.sock");
        Result<int> run();

        Rect screen_rect();

        os::IPC::Client& client()
        {
            return *m_client;
        }

        void set_should_close(bool b)
        {
            m_should_close = b;
            if (b) m_loop.quit();
        }

        void set_main_window(Window* window)
        {
            check(!m_main_window);
            m_main_window = window;
        }

        Window* main_window()
        {
            return m_main_window;
        }

        Result<void> register_window(OwnedPtr<Window>&& window, Badge<Window>);
        void unregister_window(Window* window, Badge<Window>);

        static App& the();

      private:
        static App* s_app;
        OwnedPtr<os::IPC::Client> m_client;
        Window* m_main_window { nullptr };
        HashMap<int, OwnedPtr<Window>> m_windows;
        bool m_should_close { false };
        os::EventLoop m_loop;
        Vector<int> m_window_clear_queue;

        bool process_events();

        Window* find_window(int id);

        Result<void> handle_ipc_event(os::IPC::Client&, u8 id, void*);

        friend void handle_socket_event(int, int);
    };
}