-----------------------------------------------------------
-- SCRIPTS PANEL
-----------------------------------------------------------
function editor_defineScriptsPanel()
	return
{

		name = "Scripts",
		height = 20,
		hide = true,
		open = true,
		docked = true,
		y = 0,
		remove = 0,
		alpha = 1,
		fontSize = config.fontSize or 8,
		minFontSize = 8,
		maxFontSize = 16,

		currentB = 1,
		id = "NONE",
		object = {},
		events = {},
		selected = {},
		delete = {},
		spacing = 3,

		row = config.row,

		oldY = 0,

		update = editor_scriptsPanelUpdate,
	}
end

function editor_scriptsPanelUpdate(panel)
	panel.visible = not (animatePanel.open or pathsPanel.open or anySelectedSimple or not editor.coding or not room)

	if not panel.visible then
		panel.focused = false
		return
	end

	editor_togglePanelWithSelected(panel, true)

	--trace(panel.buffer.x,panel.buffer.y,panel.focused)

	if not panel.open then
		panel.focused = false
		editor.coding = false
		return
	end

	if not panel.focused then
		--shaders.alpha:send 		("alpha",panel.alpha/2)
	end

	if editor.coding then
		panel.drag = true
		gfx.fontSize(panel.fontSize)
		if not panel.docked then
			panel.x = mc(16, panel.x, screenW - panel.width - 16)
		end
		panel.width = easeTo(panel.width, panel.buffer and panel.buffer.maxw or panel.width, 2)
		panel.y = mc(16, panel.y, screenH - panel.height)
		panel.height = mc(128, easeTo(panel.height, (panel.setHeight or 0) + panel.fontSize * 1.7, 2), screenH - 32)
		panel.buffer = panel.buffer or { x = panel.x, y = panel.y, w = panel.width, h = 8, c = gfx.getFont()
			:getWidth("a"), d = 13 }

		panel.scroll = panel.scroll
				and mc(-panel.setHeight + panel.height, panel.scroll + (mouse_in(panel) and mouse.scroll.y or 0) * 10, 0)
			or 0
		scrolledMouse = mouse.y - panel.scroll - (panel.buffer.d or 12) / 2
		panel.buffer.em = gfx.getFont():getWidth("a")
		panel.buffer.x = panel.x + 4
		panel.buffer.y = panel.y + panel.fontSize * 1.7 - 6
		panel.buffer.w = panel.width - 16
		panel.buffer.h = panel.height
		panel.buffer.gutterWidth = #panel.b.lines < 10 and panel.fontSize
			or (#panel.b.lines < 100 and panel.fontSize * 2 or panel.fontSize * 3)
		local alpha = panel.focused and 1 or 0
		local buffer = panel.buffer
		panel.border = { x = buffer.x, y = buffer.y - panel.fontSize * 1.7 + 6, w = buffer.w + 16, h = buffer.h }
		buffer.alpha = alpha
		buffer.gutterColor = { 90, 90, 90, 75 }
		buffer.cursorColor = { 190, 190, 255, (math.sin(time * 5) + 1.2) * 120 * alpha }
		buffer.markColor = { 255, 190, 190, (math.sin(time * 5) + 1.2) * 120 * alpha }
		buffer.outlineColor = { 190, 190, 255, (math.sin(time * 5) + 2) * 5 * alpha }
		buffer.fillColor = { 33 * 2, 39 * 2, 51 * 2, (math.sin(time * 5) + 3) * 20 * alpha }

		if panel.focused then
			gfx.draw(
				load_imageTex("ContextShadow"),
				buffer.x + buffer.w / 2,
				buffer.y + buffer.h / 1.8,
				0,
				(buffer.w / 512) * 1.3,
				(buffer.h / 512) * 1.2,
				512 / 2,
				512 / 2
			)
		end

		--gfx.setColor255(panel.focused and 33-5 or room.sky.color.r,panel.focused and 39-5 or room.sky.color.g,panel.focused and 51-5 or room.sky.color.b,255)
		gfx.setColor(0.1, 0.13, 0.18)
		gfx.rectangle(
			"fill",
			panel.border.x - buffer.gutterWidth,
			panel.border.y,
			panel.border.w + buffer.gutterWidth,
			panel.border.h,
			4
		)

		if panel.b.needs_save then
			gfx.setColor255(150, 150, 50, 100)
			gfx.circle("line", buffer.x - buffer.gutterWidth / 3, panel.y + 12, 2 + math.abs(math.sin(time) ^ 2), 16)
		end

		gfx.setColor255(190, 190, 190, 255)
		gfx.printf(panel.title, buffer.x, panel.y + 6, buffer.w - buffer.gutterWidth * 2, "center")
		gfx.push()
		--gfx.setScissor(0,0,1,1)
		gfx.setScissor(panel.buffer.x - 32, panel.buffer.y + 8, panel.buffer.w, panel.buffer.h - panel.buffer.d * 2)
		gfx.translate(0, panel.scroll)
		polywell.draw()
		gfx.setScissor()
		gfx.pop()
		panel.setHeight = math.clamp(0, 9999, (#buffer.lines + 4 or 2) - 2) * buffer.d

		if panel.alpha == 0 then
			editor.coding = false
		end

		if mouse_in(panel) then
			editor.stageHovered = false
			if not panel.focused then
				mouse_pushClick(function()
					panel.focused = true
				end)
			end
		end

		if panel.focused then
			if mouse_in(lume.merge(panel.border, { y = panel.buffer.y + 12, h = panel.buffer.h - 24 })) and panel.b then
				mouse_setCursor(mouse_getSystemCursor("ibeam"))
				editor.stageHovered = false
				mouse_set(function()
					if not shiftDown then
						editor_deselectCode()
					end
					buffer.preselect = true
					local line =
						mc(1, mf((scrolledMouse + sidebar.titleH - 8 - buffer.y - buffer.d) / buffer.d), #panel.b.lines)
					local char = mc(0, mf((mouse.x - buffer.x - buffer.c * 1.5) / buffer.c), #panel.b.lines[line])
					if shiftDown then
						if not panel.b.mark then
							panel.b.mark_line = panel.b.point_line
							panel.b.mark = panel.b.point
						end
						panel.b.point_line = line
						panel.b.point = char

						buffer.preselect = false
						buffer.selecting = true
						buffer.ends = {
							math.min(panel.b.point_line, panel.b.mark_line),
							dir == 1 and panel.b.point
								or (dir == 2 and panel.b.mark or math.min(panel.b.point, panel.b.mark)),
							math.max(panel.b.point_line, panel.b.mark_line),
							dir == 1 and panel.b.mark
								or (dir == 2 and panel.b.point or math.max(panel.b.point, panel.b.mark)),
						}
					else
						panel.b.point_line = line
						panel.b.point = char
						if mouse.double then
							polywell.backward_word()
							polywell.forceMark = true
							polywell.forward_word()
							polywell.forceMark = false
						end
						if mouse.triple then
							polywell.beginning_of_line()
							polywell.forceMark = true
							polywell.end_of_line()
							polywell.forceMark = false
						end
					end
				end)
			end
			local newLine =
				mc(1, mf((scrolledMouse + sidebar.titleH - 8 - buffer.y - buffer.d) / buffer.d), #panel.b.lines)
			local newPoint = mc(0, mf((mouse.x - buffer.x - buffer.c * 1.5) / buffer.c), #panel.b.lines[newLine])
			if not mouse_isDown(1) then
				buffer.preselect = false
				buffer.selecting = false
			end
			if buffer.preselect then
				if
					math.dist(mouse.x, scrolledMouse, editor.mouseStored.x, editor.mouseStored.y - panel.scroll) > 8
					and (newPoint ~= panel.b.point or newLine ~= panel.b.point_line)
				then
					buffer.preselect = false
					buffer.selecting = true
					panel.b.mark = panel.b.point
					panel.b.mark_line = panel.b.point_line
				end
				mouse_pushRelease(function()
					buffer.preselect = false
					buffer.ends = nil
				end)
			end

			if buffer.selecting then
				panel.b.point_line = newLine
				panel.b.point = newPoint
				local dir = panel.b.point_line < panel.b.mark_line and 1
					or panel.b.point_line > panel.b.mark_line and 2
					or 0
				buffer.ends = {
					math.min(panel.b.point_line, panel.b.mark_line),
					dir == 1 and panel.b.point or (dir == 2 and panel.b.mark or math.min(panel.b.point, panel.b.mark)),
					math.max(panel.b.point_line, panel.b.mark_line),
					dir == 1 and panel.b.mark or (dir == 2 and panel.b.point or math.max(panel.b.point, panel.b.mark)),
				}

				mouse_pushRelease(function()
					if buffer.ends and buffer.ends[1] == buffer.ends[3] and buffer.ends[2] == buffer.ends[4] then
						editor_deselectCode()
					end
					buffer.preselect = false
					buffer.selecting = false
				end)
			end

			if not buffer.selecting and not (panel.b.mark == nil or panel.b.mark_line == nil) then
				local dir = panel.b.point_line < panel.b.mark_line and 1
					or panel.b.point_line > panel.b.mark_line and 2
					or 0
				buffer.ends = {
					math.min(panel.b.point_line, panel.b.mark_line),
					dir == 1 and panel.b.point or (dir == 2 and panel.b.mark or math.min(panel.b.point, panel.b.mark)),
					math.max(panel.b.point_line, panel.b.mark_line),
					dir == 1 and panel.b.mark or (dir == 2 and panel.b.point or math.max(panel.b.point, panel.b.mark)),
				}
				if buffer.ends and buffer.ends[1] == buffer.ends[3] and buffer.ends[2] == buffer.ends[4] then
					editor_deselectCode()
				end
			end
		end
	else
		panel.height = sidebar.titleH
		panel.name = "Scripts"
		editor_updateScriptsPanel(panel)
		editor_newScriptButton(panel)
	end
end

function editor_deselectCode()
	local panel = scriptsPanel
	panel.buffer.ends = nil
	panel.buffer.selecting = false
	panel.b.mark = nil
	panel.b.mark_line = nil
end

function editor_openScript(key, external)
	local path = PROJ_DIR .. "scripts" .. "/" .. key
	local file = path .. ".lua"

	scripts[key].dateModified = os.time()

	if external then
		os.execute('open "' .. file .. '"')
	else
		gfx.fontSize(10)
		editor.coding = true
		scriptsPanel.script = scripts[key]
		scriptsPanel.editing = true
		scriptsPanel.name = ""
		scriptsPanel.title = scripts[key].name
		scriptsPanel.file = file
		scriptsPanel.key = key
		scriptsPanel.height =
			mc(128, (scriptsPanel.b and #scriptsPanel.b.lines + 4 or 8) * gfx.getFont():getHeight(), screenH - 16)
		polywell.open(polywell.fs, file)

		scriptsPanel.focused = true
		scriptsPanel.stayFloat = true
		scriptsPanel.x = contextMenu.x
		scriptsPanel.y = mc(16, contextMenu.y, screenH - scriptsPanel.height - 16)

		editor_floatPanel(scriptsPanel, scriptsPanel)
	end
end

function countLines(file)
	local file = lfs.newFile(file)
	file:open("r")
	local l = 1
	for c in file:lines(1) do
		l = l + 1
	end
	file:close()
	return l
end

function editor_removeScript(target, script)
	local v, i = lume.match(target.scripts, function(x)
		return x.key == script.key
	end)
	table.remove(target.scripts, i)
end

function editor_updateScriptsPanel(panel)
	gfx.fontSize(10)
	panel.scripts = editor.selectedEntities[1].scripts
	local xoffset = panel.x

	for i, script in lume.ripairs(panel.scripts) do
		if script.delete or not scripts[script.key] then
			editor_removeScript(editor.selectedEntities[1], script)
			panel.selected = {}
			table.remove(panel.scripts, i)
		end
	end

	for i, script in ipairs(panel.scripts) do
		local b = scripts[script.key]
		-- script
		-----------------------------------------------------------
		local scriptItem = {
			w = panel.row + panel.spacing + gfx.currentFont:getWidth(b.name) + 4,
			h = panel.row,
			x = xoffset,
			y = panel.y + panel.height,
			name = b.name,
			col = b.public and { r = 1, g = 1, b = 1, a = 1 } or { a = 100 },
			tcol = b.public and { r = 0, g = 0, b = 0, a = 1 } or nil,
			align = "left",
			selected = multicheckOR(script.key, panel.selected),
		}
		script.selected = scriptItem.selected
		if scriptItem.x + scriptItem.w + panel.spacing > panel.x + panel.width then
			xoffset = panel.x + scriptItem.w
			scriptItem.x = panel.x
			panel.height = panel.height + panel.row + panel.spacing
			scriptItem.y = panel.y + panel.height
		else
			xoffset = xoffset + scriptItem.w + panel.spacing
		end
		scriptItem.hovered = mouse_in(scriptItem)
		editor_drawEventTools(scriptItem)

		if scriptItem.hovered then
			editor_setToolTip((b.lines and tostring(b.lines) or "no") .. " lines")
			mouse_set(function()
				if cmdDown then
					if scriptItem.selected and #panel.selected > 1 then
						lume.remove(panel.selected, script.key)
					else
						table.insert(panel.selected, script.key)
					end
				else
					panel.selected = { script.key }
				end
			end)
			mouse_setR(function()
				if #panel.selected <= 1 then
					panel.selected = { script.key }
				else
					table.insert(panel.selected, script.key)
				end

				local allAbled = lume.all(panel.scripts, function(x)
					return (not x.selected or x.enabled)
				end) or lume.all(panel.scripts, function(x)
					return (not x.selected or x.enabled == false)
				end)

				local allPublic = lume.all(panel.selected, function(x)
					return scripts[x].public
				end) or lume.all(panel.selected, function(x)
					return (scripts[x].public == false)
				end)

				editor_openContextMenu({
					{
						name = "Open",
						func = function(x)
							editor_processScripts(function(x)
								editor_openScript(x.key)
							end)
						end,
					},
					allAbled and {
						name = script.enabled and "Disable" or "Enable",
						func = function(x)
							editor_processScripts(function(x)
								x.enabled = not x.enabled
							end)
						end,
					} or {
						{
							name = "Enable",
							col = { r = 1, g = 0.9, b = 0.4, a = 0.2 },
							func = function(x)
								editor_processScripts(function(x)
									x.enabled = true
								end)
							end,
						},
						{
							name = "Disable",
							col = { r = 0.3, g = 0.5, b = 0.8, a = 0.2 },
							func = function(x)
								editor_processScripts(function(x)
									x.enabled = false
								end)
							end,
						},
					} or 1,
					allPublic and {
						name = b.public and "Make Private" or "Make Public",
						func = function(x)
							editor_processScripts(function(x)
								scripts[x.key].public = not scripts[x.key].public
							end)
						end,
					} or {
						{
							name = "Private",
							col = { r = 0.5, g = 0.6, b = 1, a = 0.2 },
							func = function(x)
								editor_processScripts(function(x)
									scripts[x.key].public = false
								end)
							end,
						},
						{
							name = "Public",
							col = { r = 0.8, g = 0.5, b = 0.7, a = 0.2 },
							func = function(x)
								editor_processScripts(function(x)
									scripts[x.key].public = true
								end)
							end,
						},
					} or 1,
					#panel.selected == 1 and {
						name = "Rename",
						func = function()
							namer_typeString(
								"script name",
								b.name,
								{ x = scriptItem.x + scriptItem.w / 2, y = scriptItem.y },
								function(x)
									b.name = x
								end
							)
						end,
					} or 1,
					{
						name = "Delete",
						col = { r = 0.8, g = 0.2, b = 0.2, a = 0.4 },
						func = function(x)
							editor_processScripts(function(x)
								x.delete = true
							end)
						end,
					},
				})
			end, true)
		end

		-- CHECKBOX
		-----------------------------------------------------------
		local checkButton = {
			x = scriptItem.x + scriptItem.w - panel.row,
			y = scriptItem.y + 2,
			w = panel.row * 0.8,
			h = panel.row * 0.8,
			col = { r = 0, b = 0, g = 0, a = 0.8 },
			text = script.enabled and "ticked" or "unticked", -- untickedticked,
			func = function()
				script.enabled = not script.enabled
			end,
		}
		editor_queueButton(checkButton)
	end

	panel.height = panel.height + (#panel.scripts > 0 and panel.row + panel.spacing or 0)
end

function editor_processScripts(func)
	for i, b in ipairs(scriptsPanel.scripts) do
		if b.selected then
			func(b)
		end
	end
end

function editor_contextScripts(target)
	local settings = not noSettings
	return {
		name = "Scripts",
		subWidth = 220,
		subHeight = 220,
		sameY = true,
		sub = "Current",
		items = lume.concat({
			{
				ctx.viewport and {
					name = "Current",
					subitems = editor_contextScriptsList(target, true),
					scroll = 0,
					align = "center",
					func = returnTrue,
				} or nil,
				{
					name = "Library",
					subitems = editor_contextScriptsList(target, false),
					scroll = 0,
					align = "center",
					func = returnTrue,
				},
			},
		}),
	}
end

function editor_contextScriptsList(target, current)
	local subitems = {}
	for s, script in lume.ripairs(current and target.scripts or sortBy(scripts, "public", "dateUsed")) do
		if scripts[script.key] then --and (current or scripts[script.key].public) then
			local scriptAdded = lume.match(target.scripts, function(x)
				return x.key == script.key
			end)
			local items = {
				{
					name = current and "-" or "-x",
					align = "center",
					size = 1,
					col = { r = 0.8, g = 0.4, b = 0.25, a = 0.4 },
					warning = "open",
					func = function()
						(current and editor_removeScript or editor_deleteScript)(target, script)
						return "remove"
					end,
				},
				{
					name = "",
					size = (current or not scriptAdded) and 6 or 7,
					func = function()
						editor_openScript(script.key)
					end,
					update = function(x)
						x.name = scripts[script.key].name
						x.tcol = (script.enabled == false) and { a = 0.5 } or nil
					end,
				},
				{
					name = "»",
					align = "center",
					size = 1,
					col = { r = 0, g = 0, b = 0, a = 0.5 },
					func = function()
						editor_openScript(script.key, true)
					end,
				},
				{
					name = "···",
					align = "center",
					size = 1,
					col = { r = 0, g = 0, b = 0, a = 0.5 },
					func = function()
						namer_typeString("script name", scripts[script.key].name, mouse_getCoords(), function(x)
							scripts[script.key].name = x
						end)
						return "rename"
					end,
				},
				{
					name = "",
					align = "center",
					size = 1,
					col = { r = 0, g = 0, b = 0, a = 0.5 },
					func = function()
						scripts[script.key].public = not scripts[script.key].public
						return "toggle"
					end,
					update = function(x)
						x.name = scripts[script.key].public and "↑" or "↓"
						x.col = scripts[script.key].public and { r = 0.5, g = 0.5, b = 1, a = 0.2 }
							or { r = 0.8, g = 0.5, b = 0.7, a = 0.2 }
					end,
				},
				current and {
					name = "",
					align = "center",
					size = 1,
					col = { r = 0, g = 0, b = 0, a = 0.5 },
					func = function()
						script.enabled = not script.enabled
						return "toggle"
					end,
					update = function(x)
						x.name = script.enabled and "ticked" or "unticked"
					end,
				} or nil,
			}
			if not scriptAdded then
				table.insert(items, 3, {
					name = "",
					align = "center",
					size = 1,
					col = colors.green,
					func = function()
						table.insert(target.scripts, { key = script.key, enabled = true })
						return "toggle"
					end,
					update = function(x)
						x.name = "+"
					end,
				})
			end
			table.insert(subitems, items)
		else
			table.remove(target.scripts, s)
		end
	end
	table.insert(subitems, {
		name = "New Script",
		col = colors.green,
		func = function()
			editor_newScript(target, true)
			return "new"
		end,
	})
	return subitems
end

function editor_deleteScript(target, script)
	lfs.remove("scripts/" .. script.key .. ".lua")
	scripts[script.key] = nil
end

-----------------------------------------------------------
-- OTHER SCRIPT PANEL FUNCTIONS
-----------------------------------------------------------

function editor_newScript(target, open)
	namer_typeString("script Name", "new script", mouse_getCoords(), function(x)
		editor_closeContextMenu()
		local default = { key = uuid(), enabled = true }
		scripts[default.key] = { key = default.key, public = false, name = x, filename = "scripts/" .. default.key }

		local entityScript =
			"-- Entity Script\nlocal public={}\nlocal self={} \nlocal entity \n\nfunction self.load()\n  entity = self.target \n  public = entity.public\n\nend\n\nfunction self.loop()\n  \nend \nreturn self,public"
		local roomScript =
			"-- Room Script\nlocal public={}\nlocal self={} \nlocal room \n\nfunction self.load()\n  room = self.target \n  public = room.public\n\nend\n\nfunction self.loop()\n  \nend \nreturn self,public"

		engine_writeProjectFile(target.sky and roomScript or entityScript, scripts[default.key].filename .. ".lua")

		table.insert(target.scripts, default)

		scripts[default.key].dateCreated = os.time()
		scripts[default.key].dateModified = os.time()
		scripts[default.key].dateUsed = os.time()

		if open then
			editor_openScript(default.key)
		end

		save_project()
	end)
end

function editor_openSavescriptMenu() end

function editor_openLoadscriptMenu(panel)
	local contextItems = {}
	for k, b in pairs(scripts) do
		table.insert(contextItems, {
			name = b.name,
			func = function()
				table.insert(panel.scripts, b)
				editor.openscriptsPanel(panel)
			end,
		})
	end
	editor_openContextMenu(contextItems)
end

function editor_newScriptButton(panel)
	local button = {
		x = panel.x + (panel.width - panel.row * 1.1),
		y = panel.y,
		w = panel.row,
		h = panel.row,
		text = "+",
		func = function()
			editor_newScript(panel)
		end,
	}
	editor_queueButton(button)
end

-----------------------------------------------------------
-- DRAW CALLS
-----------------------------------------------------------

function editor_drawEventTools(button)
	local col = lume.merge({ r = 0, g = 0, b = 0, a = 0 }, button.col)
	local tcol = lume.merge({ r = 1, g = 1, b = 1, a = 1 }, button.tcol or {})

	if button.hovered then
		mouse_setCursor(hand)
	end

	gfx.setColor(col.r, col.g, col.b, (button.hovered and 1 or 0.5) * col.a)
	gfx.rectangle("fill", mf(button.x + 1), mf(button.y + 1), mf(button.w - 2), mf(button.h) - 2, 2)

	buttonImages(button)

	if button.selected then
		gfx.setLineWidth(1)
		gfx.setColor(tcol.r, tcol.g, tcol.b, 2 - mean(tcol))
		gfx.rectangle("line", mf(button.x + 1), mf(button.y + 1), mf(button.w - 2), mf(button.h) - 2, 2)
	end
	gfx.setColor(tcol.r, tcol.g, tcol.b, tcol.a + (1 - mean(tcol)))
	gfx.printf(button.name, mf(button.x + 4), mf(button.y + button.h / 6), button.w - 4, button.align or "center")
end

function editor_drawPlus(plus, type)
	gfx.setColor(0.7, 0.7, 0.7, 1)
	gfx.draw(load_imageTex("PlusSign"), plus.x, plus.y + 6, 0, 0.8, 0.8)
	gfx.printf(string.upper("add " .. type), plus.x + 16, plus.y + 5, sidebar.width, "left")
end

function editor_drawCross(plus)
	gfx.setColor(1, 1, 1, plus.hovered and 1 or 0.7)
	gfx.draw(load_imageTex("CrossSign"), plus.x + 4, plus.y + 4)
end
