local ecs = require 'honey.ecs'

local module = {}
local glfw = honey.glfw
setmetatable(module, {__index=_G})
setfenv(1, module)


Window = {}
Window.__index = Window


function Window.new(_, width, height, title, monitor, share)
	local monitor = monitor or glfw.monitor_NULL
	local share = share or glfw.window_NULL

	local self = {}
	setmetatable(self, Window)

	self.win = glfw.CreateWindow(width, height, title, monitor, share)
	self.__gc = honey.util.gc_canary(function()
		glfw.DestroyWindow(self.win)
	end)

	return self
end
setmetatable(Window, {__call=Window.new})


function Window.shouldClose(self)
	return glfw.WindowShouldClose(self.win) == glfw.TRUE
end
function Window.setShouldClose(self, state)
	glfw.SetWindowShouldClose(self.win, state)
end


function Window.setTitle(self, title)
	glfw.SetWindowTitle(self.win, title)
end


function Window.getPos(self)
	return glfw.GetWindowPos(self.win)
end
function Window.setPos(self, x, y)
	glfw.SetWindowPos(self.win, x, y)
end


function Window.getSize(self)
	return glfw.GetWindowSize(self.win)
end
function Window.setSizeLimits(self, minwidth, minheight, maxwidth, maxheight)
	glfw.SetWindowSizeLimits(self.win, minwidth, minheight, maxwidth, maxheight)
end
function Window.setAspectRatio(self, numerator, denominator)
	glfw.SetWindowAspectRatio(self.win, numerator, denominator)
end
function Window.setSize(self, width, height)
	glfw.SetWindowSize(self.win, width, height)
end


function Window.getFramebufferSize(self)
	return glfw.GetFramebufferSize(self.win)
end
function Window.getFrameSize(self)
	return glfw.GetWindowFrameSize(self.win)
end

function Window.getContentScale(self)
	return glfw.GetWindowContentScale(self.win)
end


function Window.getOpacity(self)
	return glfw.GetWindowOpacity(self.win)
end
function Window.setOpacity(self, opacity)
	return glfw.SetWindowOpacity(self.win, opacity)
end


function Window.iconify(self)
	return glfw.IconityWindow(self.win)
end
function Window.restore(self)
	return glfw.RestoreWindow(self.win)
end
function Window.maximize(self)
	return glfw.MaximizeWindow(self.win)
end
function Window.show(self)
	return glfw.ShowWindow(self.win)
end
function Window.hide(self)
	return glfw.HideWindow(self.win)
end
function Window.focus(self)
	return glfw.FocusWindow(self.win)
end
function Window.requestAttention(self)
	return glfw.RequestWindowAttention(self.win)
end


function Window.getMonitor(self)
	return glfw.GetWindowMonitor(self.win)
end
function Window.setMonitor(self, monitor, xpos, ypos, width, height, refreshRate)
	return glfw.SetWindowMonitor(self.win, monitor, xpos, ypos, width, height, refreshRate)
end


function Window.getAttrib(self, attrib)
	return glfw.GetWindowAttrib(self.win, attrib)
end
function Window.setAttrib(self, attrib, value)
	return glfw.SetWindowAttrib(self.win, attrib, value)
end


function Window.setPositionCallback(self, cb)
	return glfw.SetWindowPosCallback(self.win, cb)
end
function Window.setSizeCallback(self, cb)
	return glfw.SetWindowSizeCallback(self.win, cb)
end
function Window.setCloseCallback(self, cb)
	return glfw.SetWindowCloseCallback(self.win, cb)
end
function Window.setRefreshCallback(self, cb)
	return glfw.SetWindowRefreshCallback(self.win, cb)
end
function Window.setFocusCallback(self, cb)
	return glfw.SetWindowFocusCallback(self.win, cb)
end
function Window.setIconifyCallback(self, cb)
	return glfw.SetWindowIconifyCallback(self.win, cb)
end
function Window.setMaximizeCallback(self, cb)
	return glfw.SetWindowIconifyCallback(self.win, cb)
end
function Window.setFramebufferSizeCallback(self, cb)
	return glfw.SetFramebufferSizeCallback(self.win, cb)
end
function Window.setContentScaleCallback(self, cb)
	return glfw.SetContentScaleCallback(self.win, cb)
end

function Window.setKeyCallback(self, cb)
	return glfw.SetKeyCallback(self.win, cb)
end
function Window.setCursorPosCallback(self, cb)
	return glfw.SetCursorPosCallback(self.win, cb)
end
function Window.setScrollCallback(self, cb)
	return glfw.SetScrollCallback(self.win, cb)
end


function Window.setInputMode(self, mode, value)
	return glfw.SetInputMode(self.win, mode, value)
end


function Window.swapBuffers(self)
	glfw.SwapBuffers(self.win)
end


function Window.bindEvents(self, db)
	self:setCursorPosCallback(function(_, xpos, ypos)
		ecs.script.dispatch(db, "onCursorPos", {window=self, xpos=xpos, ypos=ypos})
	end)
	self:setKeyCallback(function(_, key, scancode, action)
		ecs.script.dispatch(db, "onKey", {window=self, key=key, scancode=scancode, action=action})
	end)
	self:setFramebufferSizeCallback(function(_, width, height)
		ecs.script.dispatch(db, "onFramebufferSize", {window=self, width=width, height=height})
	end)
	self:setScrollCallback(function(_, xoffset, yoffset)
		ecs.script.dispatch(db, "onScroll", {window=self, xoffset=xoffset, yoffset=yoffset})
	end)
end


return module.Window