assert(editor == nil)
editor = {
	active = false,
	room_mode = false,
	palette = {
		active = false,
		scroll = Point:new(0, 0),
	},
	multiselect = {
		active = false,
		sweeping = false,
		box = nil,
	},
	pan = { fixed = false, speed = 3 },
}

function stepEditor()

	animateTiles()

	local osweep = editor.multiselect.sweeping
	editor.multiselect.sweeping = Keybind:checkDown(Keybind.editor.entity_select)
	frameDebug("sweeping: "..tostring(editor.multiselect.sweeping))
	if editor.multiselect.sweeping and not editor.multiselect.active then
		print("multiselect enabled")
		editor.multiselect.active = true
	end
	if not osweep and osweep ~= editor.multiselect.sweeping then
		editor.multiselect.box = nil
	end
	if editor.multiselect.active then
		doEditorMultiselect()
	end

	if Keybind:checkPressed(Keybind.editor.room_mode) then
		if love.keyboard.isDown("lshift") then
			editor.room_mode = "delete"
		else
			editor.room_mode = not editor.room_mode
		end
		editor.room_points = {}
	end
	if Keybind:checkPressed(Keybind.editor.palette_mode) then
		editor.palette.active = not editor.palette.active
	end


	local cvel = Point:new(0, 0)
	if Keybind:checkDown(Keybind.editor.left) then
		cvel.x = -1
	end
	if Keybind:checkDown(Keybind.editor.right) then
		cvel.x = 1
	end
	if Keybind:checkDown(Keybind.editor.up) then
		cvel.y = -1
	end
	if Keybind:checkDown(Keybind.editor.down) then
		cvel.y = 1
	end

	cvel = cvel * editor.pan.speed
	if not editor.pan.fixed then
		cvel = cvel / game.scale
	end

	Camera.pos = Camera.pos + cvel

	if editor.palette.active then
		if Keybind:checkPressed(Keybind.editor.palette_change) then
			local next = false
			local export = nil
			for k, v in pairs(tileset) do
				if export == nil then
					export = v
				end
				if next then
					LevelData.tileset = v
					next = false
					break
				end

				if v == LevelData.tileset then
					next = true
				end
			end
			if next then
				LevelData.tileset = export
			end
			getLevelTileData()
			indexLevelTiles()
		end
	end

	if Keybind:checkPressed(Keybind.editor.save) then
		Prompt:new({
				name = "level name",
				input = "unnamed",
				func = function(name_prompt)
					if name_prompt.canceled then return end
					Prompt:new({
							name = "filename",
							input = "level.lua",
							func = function(file_prompt)
								if file_prompt.canceled then return end
								exportLevel(name_prompt.input, file_prompt.input)
							end,
					}):activate()
				end,
		}):activate()
	end
end

function scrollEditor(y)
	if editor.palette.active then
		local scr = editor.palette.scroll
		if love.keyboard.isDown("lshift") then
			scr.y = scr.y + y
		else
			scr.x = scr.x + y
		end
	else
	 	game.scale = math.max(0.1,game.scale + y/16)
	end
end

function drawEditor()
	startGameworldDraw()
	drawGameworldBackground()
	drawGridDisplay()
	drawGameworldForeground()
	endGameworldDraw()

	drawEditorRooms()
	drawSpawns()

	doEditorEdit()

	drawSelectingPaletteTile()

	if editor.palette.active then
		doEditorPalette()
	end
	if editor.multiselect.box ~= nil then
		frameDebug("drawing multiselect "..tostring(editor.multiselect.box))
		drawEditorMultiselect()
	end
end

function doEditorEdit()
	local mouse_x = love.mouse.getX()
	local mouse_y = love.mouse.getY()
	local horizontal = 1+math.floor(((mouse_x/game.scale) / tile_properties.width) + (Camera.pos.x / tile_properties.width))
	local vertical = 1+math.floor(((mouse_y/game.scale) / tile_properties.height) + (Camera.pos.y / tile_properties.height))
	local expand_h = 0
	local expand_v = 0
	local level_width = getLevelTileWidth()
	local level_height = getLevelTileHeight()

	if horizontal > level_width then
		 expand_h = horizontal-level_width
	elseif horizontal < 0 then
		 expand_h = horizontal
	end
	if vertical > level_height then
		 expand_v = vertical-level_height
	elseif vertical < 0 then
		 expand_v = vertical
	end
	love.graphics.setColor(100, 100, 100, 0.8)
		drawTextBox(
		 	"Coords: [" ..
			horizontal .. "," .. vertical .. "] (tile)\t[" ..
			math.floor(mouse_x / game.scale + Camera.pos.x) .. "," .. math.floor(mouse_y / game.scale + Camera.pos.y).."] (pixel)\n" ..
			 "Level size: [" ..	level_width .. ", " .. level_height .. "] +(" .. expand_h .. "," .. expand_v .. ")",
			0,
			0
		)

	if editor.room_mode then
		local rx = horizontal * tile_properties.width
		local ry = vertical * tile_properties.height
		local r = editor.room_points
		if Keybind:checkPressed(Keybind.generic.rclick) then
			editor.room_points = {}
		elseif Keybind:checkPressed(Keybind.generic.lclick) then
			if editor.room_mode == "delete" then
				for i, room in ipairs(LoadedObjects.Rooms) do
					if room:containsPoint(rx, ry) then
						table.remove(LoadedObjects.Rooms, i)
					end
				end
			else
				table.insert(r, { x = rx, y = ry })
			end
		end
		if #editor.room_points == 2 then
			table.insert(LoadedObjects.Rooms, Collision:new(r[1].x-tile_properties.width,r[1].y-tile_properties.height,r[2].x,r[2].y))
			editor.room_points = {}
		end
		if editor.room_mode == "delete" then
			drawTextBox("Select room to delete", 0, 20)
		elseif #editor.room_points == 0 then
			drawTextBox("Select top left of new room", 0, 20)
		else
			drawTextBox("Select bottom right of new room", 0, 20)
		end
	elseif not editor.palette.active then
		if 	LevelTiles[vertical] ~= nil
		and LevelTiles[vertical][horizontal] ~= nil
		and love.keyboard.isDown("lshift") ~= true
		and love.keyboard.isDown("lctrl") ~= true
		then
			if selecting_tile ~= nil then
				if Keybind:checkDown(Keybind.editor.tile_set) then
					setTile(vertical,horizontal,selecting_tile)
				elseif Keybind:checkDown(Keybind.editor.tile_remove) then
					setTile(vertical,horizontal,0)
				end
				reloadLevelTiles()
			else
				if Keybind:checkDown(Keybind.editor.entity_select) then
					deselectSpawns()
					if editor.multiselect.box then
						selectSpawns(editor.multiselect.box)
					end
				end
				if Keybind:checkDown(Keybind.editor.entity_move) then
					moveSpawns(mouse_x,mouse_y)
				end
				if Prompt.active_prompt == nil then
					if Keybind:checkDown(Keybind.editor.entity_modify_archetype) then
						promptSpawnArchetype()
					elseif Keybind:checkDown(Keybind.editor.entity_modify_data) then
						promptSpawnArgs()
					elseif Keybind:checkDown(Keybind.editor.entity_remove) then
						deleteSpawn()
					elseif Keybind:checkDown(Keybind.editor.entity_new) then
						promptSpawnNew()
					end
				end
			end
		elseif Keybind:checkPressed(Keybind.generic.lshift) then
			expandLevelCanvas(math.sign(expand_h),math.sign(expand_v))
			reloadLevelTiles()
		elseif Keybind:checkPressed(Keybind.generic.lctrl) then
			reduceLevelCanvas(math.sign(expand_h),math.sign(expand_v))
			reloadLevelTiles()
		end
	end
end

function drawSelectingPaletteTile()
	if selecting_tile ~= nil and selecting_tile ~= 0 then

		local mouse_x = love.mouse.getX()
		local mouse_y = love.mouse.getY()
		local horizontal = math.floor(((mouse_x/game.scale) / tile_properties.width) + (Camera.pos.x / tile_properties.width))
		local vertical = math.floor(((mouse_y/game.scale) / tile_properties.height) + (Camera.pos.y / tile_properties.height))
		local draw_x = tile_properties.width * horizontal - Camera.pos.x
		local draw_y = tile_properties.height * vertical - Camera.pos.y

		love.graphics.draw(
			LevelData.tileset,
			TileIndex[selecting_tile],
			draw_x,
			draw_y
		)
	end
end

function doEditorPalette()
	local width = LevelData.tileset:getPixelWidth()/tile_properties.width
	local height = LevelData.tileset:getPixelHeight()/tile_properties.height
	local mouse_x = love.mouse.getX()
	local mouse_y = love.mouse.getY()
	local hovering = nil
	local hov_x = nil
	local hov_y = nil
	local output = ""

	love.graphics.setColor(0,0,0,1)
	love.graphics.rectangle(
		"fill",
		(editor.palette.scroll.x + 1) * (tile_properties.width+1),
		(editor.palette.scroll.y + 1) * (tile_properties.height+1),
		1 + LevelData.tileset:getPixelWidth() * ((tile_properties.width+1) / tile_properties.width),
		1 + LevelData.tileset:getPixelHeight()* ((tile_properties.height+1) / tile_properties.height)
	)
	love.graphics.setColor(1,1,1,1)

	local position_x = 1
	local position_y = 1
	for i = 1, #TileIndex-width-1 do

		local tile_x = (editor.palette.scroll.x + position_x) * (tile_properties.width+1)
		local tile_y = (editor.palette.scroll.y + position_y) * (tile_properties.height+1)

		love.graphics.draw(
			LevelData.tileset,
			TileIndex[i],
			tile_x,
			tile_y,
			0,
			1,
			1
		)

		if 	mouse_x > (tile_x) * game.scale
		and mouse_x < (tile_x + tile_properties.width) * game.scale
		and mouse_y > (tile_y) * game.scale
		and mouse_y < (tile_y + tile_properties.height) * game.scale
		then
			hovering =  position_x + ((position_y-1) * width)
			hov_x = tile_x
			hov_y = tile_y
			if Keybind:checkDown(Keybind.generic.lclick) then
				selecting_tile = hovering
			end
		end

		if Keybind:checkDown(Keybind.generic.rclick) then
			selecting_tile = nil
		end

		if selecting_tile ~= nil and selecting_tile ~= 0 and i == selecting_tile then
			love.graphics.setColor(1,0,1,1)
			love.graphics.rectangle(
				"line",
				tile_x,
				tile_y,
				tile_properties.width,
				tile_properties.height
			)
			love.graphics.setColor(1,1,1,1)
		end

		position_x = position_x + 1

		if position_x > width then
			position_x = position_x - width
			position_y = position_y + 1
		end
	end


	love.graphics.rectangle(
		"line",
		(editor.palette.scroll.x + 1) * (tile_properties.width+1),
		(editor.palette.scroll.y + 1) * (tile_properties.height+1),
		1 + LevelData.tileset:getPixelWidth() * ((tile_properties.width+1) / tile_properties.width),
		1 + LevelData.tileset:getPixelHeight()* ((tile_properties.height+1) / tile_properties.height)
	)

	local tile = "none"
	if selecting_tile ~= nil then
		tile = "#"..selecting_tile
	end
	output = output .. "Selected: " .. tile

	if hovering ~= nil then
		output = output .. " \nHovering: #".. hovering .. "\nImage coords: " .. hov_x .. ", " .. hov_y
	end

	drawTextBox(
		output,
		(editor.palette.scroll.x + 1+width) * (tile_properties.width+1),
		(editor.palette.scroll.y + 1) * (tile_properties.height+1)
	)
end


function drawEditorRooms()
	for _, room in pairs(LoadedObjects.Rooms) do
		love.graphics.setColor(0,0,1,1)
		room:asRect():draw("line")
	end
end

function drawEditorMultiselect()
	love.graphics.setColor(0,1,1,1)
	editor.multiselect.box:draw("line")
end

function doEditorMultiselect()
	local mousept = Camera:mouseGamePos()
	if editor.multiselect.box == nil then
		editor.multiselect.box = Rect:fromPoints(mousept, mousept)
	elseif editor.multiselect.sweeping then
		editor.multiselect.box.max = mousept
	end
end
