#pragma once

#include "ehs/EHS.h"
#include "ehs/Array.h"
#include "ehs/Str.h"
#include "ehs/Vec4.h"
#include "BaseWindow.h"
#include "HID/InputHandler.h"

#define WM_HIDE (WM_APP + 1)
#define WM_SHOW (WM_APP + 2)
#define WM_HIDE_CURSOR (WM_APP + 3)
#define WM_SHOW_CURSOR (WM_APP + 4)

namespace ehs
{
    class EHS_LIB_IO Window : public BaseWindow
    {
    private:
        UInt_32 owner;
        HINSTANCE instance;
        HWND hdl;

        static Array<Window*> windows;

        static LRESULT CALLBACK WndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam);

    public:
        ~Window() override;

        Window();

        Window(const Window &win);

        Window& operator=(const Window &win);

        bool Poll() override;

        ///Creates the native window.
        void Create_32(const Str_32& title, const Vec2_s32& pos, Vec2_u32 scale) override;

        ///Creates the native window.
        void Create_16(const Str_16& title, const Vec2_s32& pos, Vec2_u32 scale) override;

        ///Creates the native window.
        void Create_8(const Str_8& title, const Vec2_s32& pos, Vec2_u32 scale) override;

        ///Uses an already existing window to render an overlay.
        void Use(HWND windowHdl);

        ///Closes the window.
        void Close() override;

        ///Shows the window.
        void Show() override;

        ///Hides the window.
        void Hide() override;

        void SetTitle_32(const Str_32& title) override;

        Str_32 GetTitle_32() const override;

        void SetTitle_16(const Str_16& title) override;

        Str_16 GetTitle_16() const override;

        void SetTitle_8(const Str_8& title) override;

        Str_8 GetTitle_8() const override;

		void SetIcon(const Str_8& filePath);

        /// Gets the windows native handle for the operating system or other native tasks.
        /// @returns The window's native handle.
        HWND GetHdl() const;

        /// Retrieves the first window handle that has been created using this library.
        /// @returns The window's native handle.
        static HWND GetAvailableHdl();

        HINSTANCE GetInst() const;

        /// Toggles whether the window updates and renders.
        /// @param [in] toggle The new status.
        void ToggleEnabled(bool toggle);

        /// Checks whether the window updates and renders.
        /// @returns The current status.
        bool IsEnabled();

        /// Sets the windows position on the desktop.
        /// @param [in] x The x axis in pixels.
        /// @param [in] y The y axis in pixels.
        void SetPos(const Vec2_s32& newPos) override;

        /// Gets the windows current position on the desktop.
        /// @returns The current value.
        Vec2_s32 GetPos() const override;

        virtual void OnResized(const Vec2<UInt_32>& newSize);

        /// Sets the windows scale which includes the border.
        /// @param [in] w The width in pixels.
        /// @param [in] h The height in pixels.
        void SetScale(const Vec2_u32& newScale) override;

        /// Gets the windows current scale.
        /// @returns The current value.
        Vec2_u32 GetScale() const override;

		void ShowCursor(bool toggle) override;

		void ConstrainCursor(bool toggle) override;

        Serializer<UInt_64> GetClipboard() override;

        void SetClipboard(Serializer<UInt_64> data) override;

        void SetCursorImg(CursorImg img) override;

    protected:
        void SendMsg(UINT msg, WPARAM wParam, LPARAM lParam);

    };
}