#pragma once

#include "DrawingSurface.h"
#include "DisplayState.h"
#include "DrawingContext.h"
#include "Widget.h"

#include <memory>
#include <vector>
#include <cstdint>
#include <string>
#include <functional>

class PaintEvent;
class MouseEvent;
class KeyboardEvent;

class DrawingContext;
class FontsManager;
enum class DrawingMode;

using WidgetPtr = std::unique_ptr<Widget>;
class IPlatformWindow;
using IPlatformWindowPtr = std::unique_ptr<IPlatformWindow>;

namespace mt
{

class Screen;

class Window : public DrawingSurface
{

public:
    using onPopupFunc = std::function<void(mt::Window* parent, std::unique_ptr<Widget> popup)>;

    Window(DrawingMode drawingMode = DrawingMode::GRAPH, FontsManager* fontsManager = nullptr);

    ~Window();

    static std::unique_ptr<Window> Create(DrawingMode drawingMode = DrawingMode::GRAPH, FontsManager* fontsManager = nullptr);

    void addPopup(std::unique_ptr<Widget> popupWidget);

    void clear();

    void clearPlatformWindow();

    void doPaint(mt::Screen* screen);

    IPlatformWindow* getPlatformWindow() const;

    const std::string& getTitle() const;

    Window* getParent() const;

    DrawingContext* getDrawingContent() const;

    WindowState::Display getDisplayState() const;

    bool getIsSizingOnGoing() const;

    bool isDirty() const;

    void map();

    void onPaint(const PaintEvent* event);

    void onMouseEvent(const MouseEvent* event);

    void onResize();

    void onKeyboardEvent(const KeyboardEvent* event);

    void setPlatformWindow(IPlatformWindowPtr window);

    void setPopupHandler(onPopupFunc func);

    void setParent(Window* parent);

    void show();

    void setIsSizingOnGoing(bool sizingOngoing);

    void setSize(unsigned width, unsigned height, bool triggerResize = true) override;

    void setTitle(const std::string& title);

    void setWidget(WidgetPtr widget);

    void setDisplayState(WindowState::Display state);

private:
    WidgetPtr mWidget {nullptr};
    std::string mTitle;
    IPlatformWindowPtr mPlatformWindow {nullptr};
    std::unique_ptr<DrawingContext> mDrawingContext;

    onPopupFunc mPopupFunc;
    Window* mParent{nullptr};

    bool mSizingOngoing{ false };
    WindowState::Display mDisplayState{ WindowState::Display::NORMAL };
};
}

using WindowUPtr = std::unique_ptr<mt::Window>;
