#pragma once

#include "ui.h"
#include "utils.h"
#include <string>

namespace kek {

enum class TextMode {
	// Draw with y as baseline, disables vertical offset from the origin position specified using setOrigin()
	BASELINE,
	// Draw from the set origin
	ORIGIN
};

enum class TextBounds {
	SMALLEST,
	LINE
};

class TextElement: public UIElement {

  public:
	TextObject *text;

	int sizePixels;
	Color color;
	TextMode textMode;
	TextBounds textBounds;

	TextElement(UIValue x, UIValue y, std::shared_ptr<Font> font);

	TextElement(UIValue x, UIValue y);

	virtual ~TextElement();

	virtual UIElementType getType();

	virtual UIBounds getBounds();

	void setText(std::string text);

	std::string getText();

	virtual void draw(UIPoint screenPos, glm::mat4 projection);
};

class RectangleElement: public UIElement {

  protected:
	unsigned int vao;
	unsigned int vbo;

  public:
	UIValue w, h;

	Color color;

	RectangleElement(UIValue x, UIValue y, UIValue w, UIValue h);

	virtual ~RectangleElement();

	virtual UIElementType getType();

	virtual UIBounds getBounds();

	virtual void draw(UIPoint screenPos, glm::mat4 projection);
};

class ButtonElement: public RectangleElement {

  public:
	TextElement *text;
	Color color;
	Color hoverColor;
	Callable onClick;

	ButtonElement(UIValue x, UIValue y, UIValue w, UIValue h);

	virtual ~ButtonElement();

	virtual UIElementType getType();

	virtual void click(UIPoint pos, UIPoint screenPos, GLFWMouseButton button);

	virtual void draw(UIPoint screenPos, glm::mat4 projection);
};

typedef GenericCallable<std::string> SubmitCallback;

class TextFieldElement: public RectangleElement {

  protected:
	std::string text;

	KeyboardCapture capture;
	float lastCharTyped = 0;
	unsigned int cursorPos = 0; // Cursor offset from the back of the string

	void updateText(std::u32string newText);

  public:
	Color color;
	Color focusColor;

	TextElement *textElement;
	RectangleElement *cursor;

	SubmitCallback onSubmit;

	TextFieldElement(UIValue x, UIValue y, UIValue w, std::shared_ptr<Font> font);

	TextFieldElement(UIValue x, UIValue y, UIValue w);

	virtual ~TextFieldElement();

	virtual UIElementType getType();

	virtual void focusEnter();
	virtual void focusExit();

	virtual void draw(UIPoint screenPos, glm::mat4 projection);

	void setText(std::string text);
};

class UIWindowTitleBar: public RectangleElement {

  public:
	TextElement *text;
	ButtonElement *closeButton;

	UIWindowTitleBar(UIValue height);

	virtual void dragEnter(UIPoint pos, UIPoint screenPos);
	virtual void drag(UIPoint pos, UIPoint screenPos);
	virtual void dragExit(UIPoint pos, UIPoint screenPos);
};

class UIWindow: public UIElement {

  public:
	RectangleElement *background;
	UIWindowTitleBar *titleBar;

	UIValue w, h;

	UIWindow(UIValue x, UIValue y, UIValue w, UIValue h);

	virtual ~UIWindow();

	virtual UIElementType getType();

	virtual UIBounds getBounds();

	virtual void draw(UIPoint screenPos, glm::mat4 projection);
};

}
