#pragma once

#include "BaseWindow.h"
#include "File.h"

#include <xcb/xcb.h>
#include <xcb/xinput.h>

namespace ehs
{
    class EHS_LIB_IO Window : public BaseWindow
    {
    protected:
		friend class Input;

        xcb_connection_t* server;
        xcb_screen_t* screen;
        xcb_window_t hdl;
		xcb_atom_t masks[2];
		UInt_8 extOpCode;
    	Vector<xcb_generic_event_t*> events;
    	Serializer<UInt_64> clipboard;

    public:
		~Window() override;

        Window();

		Window(Window&& win) noexcept;

		Window(const Window& win);

		Window& operator=(Window&& win) noexcept;

		Window& operator=(const Window& win);

		void Create_32(const Str_32& title, const Vec2_s32& pos, Vec2_u32 scale) override;

		void Create_16(const Str_16& title, const Vec2_s32& pos, Vec2_u32 scale) override;

		void Create_8(const Str_8& title, const Vec2_s32& pos, Vec2_u32 scale) override;

		void Close() override;

		void Show() override;

		void Hide() override;

		bool Poll() override;

        void ShowCursor(bool toggle) override;

        void ConstrainCursor(bool constrain) override;

    	void SetTitle_32(const Str_32& newTitle) override;

    	Str_32 GetTitle_32() const override;

    	void SetTitle_16(const Str_16& newTitle) override;

    	Str_16 GetTitle_16() const override;

		void SetTitle_8(const Str_8& newTitle) override;

		Str_8 GetTitle_8() const override;

    	void SetPos(const Vec2_s32& newPos) override;

    	Vec2_s32 GetPos() const override;

    	void SetScale(const Vec2_u32& newScale) override;

    	Vec2_u32 GetScale() const override;

    	Serializer<UInt_64> GetClipboard() override;

    	void SetClipboard(Serializer<UInt_64> data) override;

    	void SetCursorImg(CursorImg img) override;

		xcb_connection_t* GetServer();

	private:
    	xcb_generic_event_t* RetrieveEvent();

		xcb_atom_t RetrieveAtom(bool create, const Str_8& name) const;

		xcb_get_property_reply_t* RetrieveProp(xcb_atom_t prop, xcb_atom_t type) const;

    	void QueryPrimaryDevices();

    	Str_8 QueryDeviceName(UInt_16 id);
    };
}