package surface

import (
	"time"

	"github.com/go-gl/gl/v4.1-core/gl"
	"github.com/go-gl/glfw/v3.3/glfw"
)

var ctx struct {
	fs            int
	x, y          int
	width, height int
	click         time.Time
}

func SizeCallback(window *glfw.Window, width, height int) {
	gl.Viewport(0, 0, int32(width), int32(height))
}

func KeyCallback(window *glfw.Window, key glfw.Key, scancode int, action glfw.Action, mods glfw.ModifierKey) {
	// Save window position
	if ctx.fs == 0 {
		ctx.x, ctx.y = window.GetPos()
		ctx.width, ctx.height = window.GetSize()
	}

	// F
	if key == glfw.KeyF && action == glfw.Press {
		if ctx.fs == 0 {
			// Fallback
			monitor := glfw.GetPrimaryMonitor()

			// Retrieve window's monitor
			monitors := glfw.GetMonitors()
			for _, m := range monitors {
				x, y, width, height := m.GetWorkarea()
				if ctx.x > x && ctx.x < x+width && ctx.y > y && ctx.y < y+height {
					monitor = m
					break
				}
			}

			mode := monitor.GetVideoMode()
			window.SetMonitor(monitor, 0, 0, mode.Width, mode.Height, mode.RefreshRate)
			glfw.SwapInterval(1)
			ctx.fs = 1
		} else {
			window.SetMonitor(nil, ctx.x, ctx.y, ctx.width, ctx.height, 0)
			glfw.SwapInterval(0)
			ctx.fs = 0
		}
	}

	// F1
	if key == glfw.KeyF1 && action == glfw.Press {
		if ctx.fs != 1 {
			monitors := glfw.GetMonitors()
			if len(monitors) > 0 {
				mode := monitors[0].GetVideoMode()
				window.SetMonitor(monitors[0], 0, 0, mode.Width, mode.Height, mode.RefreshRate)
				glfw.SwapInterval(1)
				ctx.fs = 1
			}
		} else {
			window.SetMonitor(nil, ctx.x, ctx.y, ctx.width, ctx.height, 0)
			glfw.SwapInterval(0)
			ctx.fs = 0
		}
	}

	// F2
	if key == glfw.KeyF2 && action == glfw.Press {
		if ctx.fs != 2 {
			monitors := glfw.GetMonitors()
			if len(monitors) > 1 {
				mode := monitors[1].GetVideoMode()
				window.SetMonitor(monitors[1], 0, 0, mode.Width, mode.Height, mode.RefreshRate)
				glfw.SwapInterval(1)
				ctx.fs = 2
			}
		} else {
			window.SetMonitor(nil, ctx.x, ctx.y, ctx.width, ctx.height, 0)
			glfw.SwapInterval(0)
			ctx.fs = 0
		}
	}

	// F3
	if key == glfw.KeyF3 && action == glfw.Press {
		if ctx.fs != 3 {
			monitors := glfw.GetMonitors()
			if len(monitors) > 2 {
				mode := monitors[2].GetVideoMode()
				window.SetMonitor(monitors[2], 0, 0, mode.Width, mode.Height, mode.RefreshRate)
				glfw.SwapInterval(1)
				ctx.fs = 3
			}
		} else {
			window.SetMonitor(nil, ctx.x, ctx.y, ctx.width, ctx.height, 0)
			glfw.SwapInterval(0)
			ctx.fs = 0
		}
	}

	// F4
	if key == glfw.KeyF4 && action == glfw.Press {
		if ctx.fs != 4 {
			monitors := glfw.GetMonitors()
			if len(monitors) > 3 {
				mode := monitors[3].GetVideoMode()
				window.SetMonitor(monitors[3], 0, 0, mode.Width, mode.Height, mode.RefreshRate)
				glfw.SwapInterval(1)
				ctx.fs = 4
			}
		} else {
			window.SetMonitor(nil, ctx.x, ctx.y, ctx.width, ctx.height, 0)
			glfw.SwapInterval(0)
			ctx.fs = 0
		}
	}

	// Escape
	if key == glfw.KeyEscape && action == glfw.Press {
		if ctx.fs != 0 {
			window.SetMonitor(nil, ctx.x, ctx.y, ctx.width, ctx.height, 0)
			glfw.SwapInterval(0)
			ctx.fs = 0
		} else {
			window.SetShouldClose(true)
		}
	}
}

func MouseButtonCallback(window *glfw.Window, button glfw.MouseButton, action glfw.Action, mods glfw.ModifierKey) {
	// Save window position
	if ctx.fs == 0 {
		ctx.x, ctx.y = window.GetPos()
		ctx.width, ctx.height = window.GetSize()
	}

	// Double click
	if button == glfw.MouseButtonLeft && action == glfw.Press {
		now := time.Now()
		if now.Sub(ctx.click) < time.Millisecond*200 {
			if ctx.fs == 0 {
				// Fallback
				monitor := glfw.GetPrimaryMonitor()

				// Retrieve window's monitor
				monitors := glfw.GetMonitors()
				for _, m := range monitors {
					x, y, width, height := m.GetWorkarea()
					if ctx.x > x && ctx.x < x+width && ctx.y > y && ctx.y < y+height {
						monitor = m
						break
					}
				}

				mode := monitor.GetVideoMode()
				window.SetMonitor(monitor, 0, 0, mode.Width, mode.Height, mode.RefreshRate)
				glfw.SwapInterval(1)
				ctx.fs = 1
			} else {
				window.SetMonitor(nil, ctx.x, ctx.y, ctx.width, ctx.height, 0)
				glfw.SwapInterval(0)
				ctx.fs = 0
			}
		}
		ctx.click = now
	}
}
