-----------------------------------------------------------
-- SET RESOLUTION
-----------------------------------------------------------
function setResolution(alreadySet)
	if alreadySet then return end
	print("SET RES",
		loadedWidth,loadedHeight
	)

	lwindow.setMode(
		loadedWidth, 
		loadedHeight, 
		{ 	
			minwidth 	= 480,
			minheight 	= 480,
			resizable   = developer,
			fullscreen 	= false,
			vsync 		= true,
			display		= config.window.display,
			borderless = false,
			fullscreentype = "desktop"
		} 
	)
 	

	if LOVE then 
		lwindow.setPosition( config.window.x, config.window.y, config.window.display )
		lwindow.setFullscreen( (config.launchFullscreen), "exclusive" )
	end

	setDimensions( )
end

-----------------------------------------------------------
-- SET CANVAS DIMENSIONS
-----------------------------------------------------------
function setDimensions( )
	screenWidth  	= gfx.getWidth() 
	screenHeight 	= gfx.getHeight()
	
	if game.state == "Edit" then 
		renderWidth  	= screenWidth*game.resolution
		renderHeight 	= screenHeight*game.resolution
	else
		renderWidth  	= orenderWidth  *game.resolution
		renderHeight 	= orenderHeight *game.resolution
	end

	shaders.simple_blur:send('image_size',{renderWidth, 		renderHeight})
	-- film:send("sIntensity",0.1)
	-- hqblur:send('image_size',{renderWidth, 		renderHeight})


	renderScale 	=	screenWidth/renderWidth
end

-----------------------------------------------------------
-- DRAW CANVAS
-----------------------------------------------------------
function setFrost()
	frostScale=hiSpec and 4 or 16
end

function drawCanvases()
	updateShaders()

	iscale 			= 	1/renderScale
	if game.state=="Game"  then --temp
 		canvasOffsetX	=	0--(screenWidth-mf(screenWidth/renderWidth)*renderWidth)*0.5 
		canvasOffsetY	=	(screenHeight-renderScale*renderHeight)*0.5 
	end

	gfx.setShader()
	gfx.draw(canvasMain) 	
	
end

function setDefaultCanvases()
	gfx.setCanvas(canvasMain)
	gfx.setShader()
	gfx.setColor(1,1,1,1)
end

-----------------------------------------------------------
-- PUSH DRAWS
-----------------------------------------------------------

function pushDraw(func,arg) table.insert(drawFuncs,{f=func,z=arg and arg.z or nil,i=#drawFuncs,a=arg}) end
function pushDrawUI(func,arg) table.insert(drawFuncsUI,{f=func,z=arg and arg.z or nil,i=#drawFuncsUI,a=arg}) end
function pushRoomDraw(room,func,z,...) table.insert(room.draws,{f=func,z=z, a={...}, i=#room.draws}) end

local function funpack(t) 
		return t[2],t[3],t[4],t[5],t[6],t[7],t[8],t[9]
end
function renderOther()
	bench.push("drawFuncs")
	for i,v in ipairs(drawFuncs) do 
		if type(v.f) == "function" then 
			v.f(v.a)
		else
			gfx.draw(v.f)
		end
	end
	bench.pop("drawFuncs")
end

function renderUI(render)
	if render then 
		gfx.setBlendMode("alpha")
		for i=1, drawFuncsUI[0],1 do 
			local v = drawFuncsUI[i]
			-- local err = pcall(v.f,funpack(v.a))
			local succ = pcall(v[1],funpack(v))
			if not succ then 
				local k,f = lume.find(gfx,v[1])
				if k then 
					-- print(k,v,funpack(v.a))
					-- print(gfx.pushed,k,v.s,v.l,funpack(v.a))
				end
			end
		end
	end
	drawFuncsUI[0]=0
end

function changeRenderRes()
	game.resolution=game.newRes
		if game.prevRes ~= game.resolution then 
			setDimensions( )
			setCanvases()
		end
	game.prevRes  	= game.resolution
end

function updateShaders()
	--film:send('sCount',1000+math.sin(time)*500);
	--film:send("time",time);
	if shaders.forwardRender then 
		if LOVR then 
			for s,shader in pairs(shaders) do 
				-- shaders.forwardRender:send('screenSize',{screenWidth,screenHeight})
			end
		end
		shaders.forwardRender:send("time",time)
		if patterns.dims then 
			-- shaders.forwardRender:send("patterns",unpack(patterns.dims))
			-- shaders.deferredStatic:send("patterns",unpack(patterns.dims))
		end
	end
end

-----------------------------------------------------------
-- MAKE FRESH CANVASES
-----------------------------------------------------------
function newDepthCanvas()
	return newCanvas( renderWidth, 		renderHeight , {format = "depth24",readable=true} )
end

function setCanvases()
	
	setFrost()
	-- canvases = {	
	-- 	ui 				= newCanvas( screenWidth, 		screenHeight, {format = "normal",msaa=(hiSpec or LOVR) and 4 or 0}  ),
	-- 	main  	 	= newCanvas( renderWidth, 		renderHeight ),
	-- 	selection = newCanvas( 2, 		2 ),
	-- 	frost 		= newCanvas( renderWidth/frostScale, 		renderHeight/frostScale) ,
	-- 	frost2 		= newCanvas( renderWidth/frostScale, 		renderHeight/frostScale) ,
	-- 	picker  	= newCanvas( 1, 		1, {format = "rg16f"} )
	-- 	-- depth  		= newCanvas( renderWidth, 		renderHeight , {format = "depth16",readable=true} )
	-- }
	if canvasMain then 
		canvasMain:release()
		canvasSelection:release()
		canvasFrost:release()
		canvasFrost2:release()	
	end
	canvasMain  	 	= newCanvas( renderWidth, 		renderHeight )
	canvasSelection = newCanvas( 2, 		2 )
	-- canvasDepth  		= newCanvas( renderWidth, 		renderHeight , {format = "depth16",readable=true} )
	canvasFrost 		= newCanvas( renderWidth/frostScale, 		renderHeight/frostScale) 
	canvasFrost2 		= newCanvas( renderWidth/frostScale, 		renderHeight/frostScale) 
	
	pickerCanvas  	= newCanvas( 1, 		1, {format = "rg16f"} )
	-- pickerQuad 			= gfx.newQuad(1,1,1,1,screenWidth,screenHeight)

	if LOVE then canvasMain:setFilter("nearest","nearest")end
	if LOVE then canvasFrost:setFilter("linear","linear")end
	if LOVE then canvasFrost2:setFilter("linear","linear")end
	if LOVE then canvasSelection:setFilter("nearest","nearest")end

	canvasTable = {	
	}


end

function clearCanvases()
	for c,canvas in pairs(canvasTable ) do 
		canvas:renderTo(function()
			gfx.clear(0,0,0,0)
		end)
	end
end


function clearCanvas(c)
	local prevCanvas = gfx.getCanvas()
	gfx.setCanvas(c)
	gfx.clear()
	gfx.setCanvas(prevCanvas)
end


function copyCanvas(source,transforms)
	if not pcall(function()source:getWidth()end) then return end
	local w,h 		 		= source:getWidth(),source:getHeight()
	local tf 				= lume.merge({x=0,y=0,nw=w,nh=h,w=(transforms and transforms.scale or 1)*w,h=(transforms and transforms.scale or 1)*h,filter="nearest",scale=1},transforms or {})

	local dest 	= newCanvas(
		zero(transforms and (transforms.scale and transforms.scale*w or transforms.w) or tf.nw),
		zero(transforms and (transforms.scale and transforms.scale*h or transforms.h) or tf.nh),
		{
			format=source:getFormat(),
			msaa=source:getMSAA(),
		}
	)

	gfx.push("all")
	gfx.setCanvas(dest)
	gfx.setShader()

	gfx.clear(0,0,0,0)
  gfx.setColor(1,1,1,1)
  gfx.setBlendMode('alpha','premultiplied')
  if tf.nx and tf.ny then
  	print("copy1")
	  gfx.draw(source,gfx.newQuad(tf.nx,tf.ny,tf.nw,tf.nh,w,h),tf.x,tf.y)
	else
		gfx.push()
		if LOVR then 
			gfx.scale(1,-1)
			gfx.translate(0,-tf.h+tf.y)
		end
		gfx.draw(source,zero(tf.x),zero(tf.y),0,tf.w/w,tf.h/h)
		gfx.pop()
	end
	gfx.pop()

	if transforms and transforms.release then 
		-- source:getTexture()=nil 
		source = nil
		collectgarbage("collect")
	end
	gfx.setFilter( dest,tf.filter )
	
	return dest
end


function clipCanvas( source, od,padding,indexed)
	local f 	= {h=source:getHeight(),w=source:getWidth()}
	local bounds = {t=1,b=f.h,l=1,r=f.w}
	local data 	= source:newImageData()
	local set 	= false
	local od 	= od or false
	local padding = padding or 0

	-- loop through pixels Y form top then from bottom
	-- loop through pixels X form left then from right
	for y=0, f.h-1 do for x=1, f.w-1 do local r, g, b, a = data:getPixel( x, y ) local t = indexed and r or a if t ~= 0 then  bounds.t=y set = true break end end if set then break end end set = false
	for x=0, f.w-1 do for y=1, f.h-1 do local r, g, b, a = data:getPixel( x, y ) local t = indexed and r or a if t ~= 0 then  bounds.l=x set = true break end end if set then break end end set = false
	for x=f.w-1, 0, -1  do for y=1, f.h-1  do local r, g, b, a = data:getPixel( x, y ) local t = indexed and r or a if t ~= 0 then  bounds.r=x set = true break end end if set then break end end set = false
	for y=f.h-1, 0, -1  do for x=1, f.w-1  do local r, g, b, a = data:getPixel( x, y ) local t = indexed and r or a if t ~= 0 then  bounds.b=y set = true break end end if set then break end end

	local offs = {}

	offs.xoff = ((f.w-bounds.r) - (bounds.l))/2
	offs.yoff = ((f.h-bounds.b) - (bounds.t))/2
	offs.pxoff = offs.xoff/f.w
	offs.pyoff = offs.yoff/f.h
	offs.wdiff = f.w/(bounds.r-bounds.l+2)
	offs.hdiff = f.h/(bounds.b-bounds.t+2)

	f.w = bounds.r-bounds.l+2+padding
	f.h = bounds.b-bounds.t+2+padding

	

	local clipped = newCanvas(f.w,  f.h, source:getFormat())
	local oldCanvas = gfx.getCanvas()
	gfx.setFilter(clipped,animationPanel.filter)
	
	gfx.setShader()
	clipped:renderTo(function()
		gfx.setBlendMode('alpha','premultiplied')
		gfx.setColor(1,1,1,1)
		gfx.draw(	source,	1-bounds.l,	1-bounds.t 	)
	end)
	log("booons",bounds.l)

	source = clipped

	if od then 
		return clipped, offs, f, bounds
	else
		return clipped
	end
end

function dataToCanvas(data)
	local dataCanvas = newCanvas(data:getWidth(),data:getHeight())
	gfx.setCanvas(dataCanvas)
	gfx.setColor(1,1,1,1)
    gfx.setBlendMode('alpha','premultiplied')
	gfx.draw(gfx.newImage(data))
	return dataCanvas
end

function renderBlur()
	if LOVR then return end
	if hiSpec and (not editor.slowDraw) and  (editingLevel or game.state=="Menu") and not config.flatUI and ((mf((time*60)%(hiSpec and 4 or 10))==1 and frostCalled) or editor.resized>0)  then 
	 	shaders.simple_blur:send('image_size',{renderWidth/frostScale,renderHeight/frostScale})
		gfx.setShader(shaders.simple_blur)
	 	gfx.setCanvas(canvasFrost2)
		gfx.draw(canvasMain, 0,0,0,1/frostScale,1/frostScale)
		gfx.setCanvas(canvasFrost)
		gfx.draw(canvasFrost2)
	end
end

function renderGame()
	bench.push("render")
	
	gfx.reset()

 	renderBlur()

	gfx.reset()


  gfx.setCanvas()

  if LOVR then 
  	if not _flipView then 
	  	gfx.draw( renderSelection and canvasSelection or canvasMain,canvasOffsetX,canvasOffsetY,0,renderScale,renderScale)
	  end
  else
		gfx.draw( renderSelection and canvasSelection or canvasMain,canvasOffsetX,canvasOffsetY,0,renderScale,renderScaleY or renderScale)
	end

	renderUI(not resizingWindow)

	gfx.reset()
	
	if editor.testCanvas then 
		-- gfx.draw(editor.testCanvas)
	end

	--trace(selectedEntities[1] and selectedEntities[1].key)
	--gfx.draw(selectedEntities[1] and selectedEntities[1].img or getImage(),100,100)


	bench.pop("render")
end


