/*
  Copyright (c) 2021 Alex Diener
  
  This software is provided 'as-is', without any express or implied
  warranty. In no event will the authors be held liable for any damages
  arising from the use of this software.
  
  Permission is granted to anyone to use this software for any purpose,
  including commercial applications, and to alter it and redistribute it
  freely, subject to the following restrictions:
  
  1. The origin of this software must not be misrepresented; you must not
     claim that you wrote the original software. If you use this software
     in a product, an acknowledgment in the product documentation would be
     appreciated but is not required.
  2. Altered source versions must be plainly marked as such, and must not be
     misrepresented as being the original software.
  3. This notice may not be removed or altered from any source distribution.
  
  Alex Diener alex@ludobloom.com
*/

#ifndef __UIWindowView_H__
#define __UIWindowView_H__

typedef struct UIWindowView UIWindowView;
#define UIWindowView_superclass UIContainer

#include "gamemath/Vector2i.h"
#include "uitoolkit/UIContainer.h"
#include "uitoolkit/UIGraphicalButton.h"
#include "uitoolkit/UIWindowRoot.h"

#define WINDOW_HIT_TEST_PRIORITY 20
#define WINDOW_HIT_TEST_PRIORITY_DELTA 5
#define WINDOW_UNFOCUS_HIT_TEST_PRIORITY 8
#define WINDOW_RESIZE_AREA_HIT_TEST_PRIORITY 50

typedef void (* UIWindowView_callback)(UIWindowView * window, void * context);
// newBounds is a proposed content rect. Return it from this callback, or an adjusted version if constraining the size.
// resizeDirection specifies the corner or side of the window being resized (x -1 = left, x 1 = right, y -1 = bottom, y 1 = top).
typedef Rect4f (* UIWindowView_resizeCallback)(UIWindowView * window, Rect4f newBounds, Vector2i resizeDirection, void * context);

#define UIWindowView_ivars \
	UIContainer_ivars \
	\
	String title; \
	UIWindowView_callback closeCallback; \
	UIWindowView_resizeCallback resizeCallback; \
	void * callbackContext; \
	UIWindowRoot * windowRoot; \
	Color4f titleColorTop; \
	Color4f titleColorBottom; \
	Color4f titleTextColor; \
	Color4f backgroundColor; \
	UIGraphicalButton * closeButton; \
	bool draggingView; \
	Vector2f dragOffset; \
	bool resizingView; \
	Vector2i resizeDirection; \
	Rect4f initialResizeBounds; \
	Rect4f lastUIBounds; \
	bool firstDraw; \
	int hitTestPriority; \
	Vector2f lastUnadjustedPosition;

#define UIWindowView_vtable(self_type) \
	UIContainer_vtable(self_type) \
	\
	void (* showWindow)(self_type * self); \
	void (* hideWindow)(self_type * self); \
	void (* bringToFront)(self_type * self); \
	bool (* isModal)(self_type * self); \
	void (* clampPositionToMaxDragBounds)(self_type * self); \
	void (* sizeToFitScreen)(self_type * self); \
	void (* setTitle)(self_type * self, String title); \
	void (* adjustUIBounds)(self_type * self, Rect4f oldBounds, Rect4f newBounds); \
	Rect4f (* getContentAreaBounds)(self_type * self); \
	Rect4f (* getAbsoluteContentAreaBounds)(self_type * self);

stemobject_declare(UIWindowView)

// Newly created UIWindowViews are not visible by default. Call showWindow to make it appear.
// If closeCallback is defined, window will include a close button. If NULL, closing is disabled.
// If resizeCallback is defined, window is resizable. If NULL, resizing is disabled.
UIWindowView * UIWindowView_create(Vector2f position, Vector2f outerRelativeOrigin, Vector2f innerRelativeOrigin, Vector2f size, String title, UIWindowView_callback closeCallback, UIWindowView_resizeCallback resizeCallback, void * callbackContext, UIWindowRoot * windowRoot, UIAppearance appearance);
bool UIWindowView_init(UIWindowView * self, Vector2f position, Vector2f outerRelativeOrigin, Vector2f innerRelativeOrigin, Vector2f size, String title, UIWindowView_callback closeCallback, UIWindowView_resizeCallback resizeCallback, void * callbackContext, UIWindowRoot * windowRoot, UIAppearance appearance);
void UIWindowView_dispose(UIWindowView * self);

bool UIWindowView_hitTest(UIWindowView * self, float x, float y, UIHitTestType type, int * outPriority, bool * outForwardNext);
void UIWindowView_hitTestList(UIWindowView * self, float x, float y, UIHitTestType type, int priorityOffset, UIHitTestResultIO * resultIO);
UIEventResponse UIWindowView_mouseDown(UIWindowView * self, unsigned int buttonNumber, unsigned int buttonMask, float x, float y, unsigned int modifiers, bool isFinalTarget, double referenceTime);
bool UIWindowView_mouseUp(UIWindowView * self, unsigned int buttonNumber, unsigned int buttonMask, float x, float y, unsigned int modifiers, double referenceTime);
bool UIWindowView_mouseDragged(UIWindowView * self, unsigned int buttonMask, float x, float y, float deltaX, float deltaY, unsigned int modifiers, double referenceTime);
UIEventResponse UIWindowView_scrollWheel(UIWindowView * self, float x, float y, int scrollDeltaX, int scrollDeltaY, unsigned int buttonMask, unsigned int modifiers, bool isFinalTarget, double referenceTime);
UIEventResponse UIWindowView_keyDown(UIWindowView * self, unsigned int charCode, unsigned int keyCode, unsigned int modifiers, bool isRepeat, bool isFinalTarget, double referenceTime);
UIElement * UIWindowView_getFocusedElement(UIWindowView * self);
bool UIWindowView_acceptsFocus(UIWindowView * self, bool finalTargetOnly);
Rect4f UIWindowView_getBounds(UIWindowView * self);
Rect4f UIWindowView_getClipBounds(UIWindowView * self);
Rect4f UIWindowView_getContentAreaBounds(UIWindowView * self);
Rect4f UIWindowView_getAbsoluteContentAreaBounds(UIWindowView * self);
void UIWindowView_draw(UIWindowView * self, Vector2f offset, UIDrawingInterface * drawingInterface, VertexIO * vertexIO);
void UIWindowView_listRenderables(UIWindowView * self, RenderableIO * renderableIO, int drawOrderOffset, Rect4i clipBounds);
ShellCursorID UIWindowView_getCursorAtPosition(UIWindowView * self, float x, float y);

void UIWindowView_showWindow(UIWindowView * self);
void UIWindowView_hideWindow(UIWindowView * self);
void UIWindowView_bringToFront(UIWindowView * self);
bool UIWindowView_isModal(UIWindowView * self);
void UIWindowView_setPosition(UIWindowView * self, Vector2f position);
void UIWindowView_clampPositionToMaxDragBounds(UIWindowView * self);
void UIWindowView_sizeToFitScreen(UIWindowView * self);
void UIWindowView_setTitle(UIWindowView * self, String title);
void UIWindowView_adjustUIBounds(UIWindowView * self, Rect4f oldBounds, Rect4f newBounds);

void UIWindowView_enforceMinimumWindowSize(Vector2f sizeMin, Rect4f * ioNewBounds, Vector2i resizeDirection);
void UIWindowView_enforceMaximumWindowSize(Vector2f sizeMax, Rect4f * ioNewBounds, Vector2i resizeDirection);

#endif
