imageLoader= imageLoader or {}

function imageLoader:loadController()
	objects["_controller"] = {animations={default={bounds={t=-4.5,ox=0,r=4.5,oy=0,l=-4.5,b=4.5},size={h=9,w=9},layers={{visible=true,frames={{oy=0,x=0,ox=0,w=9,y=0,h=9,l=1,blank=false}},name="Layer 1",loop=false}},fps=24,name="default",length=1,key="default",shapes={{-0.5,-0.5,0.5,-0.5,0.5,0.5,-0.5,0.5}}}},modtime=1477547970,tags={},key="_controller",name="_controller",default="default"}

end

function imageLoader:preLoad()
	tagNames  		= lume.merge(tagNames,{Game="Game",Level="Level",Room="Room"})
	self.toLoad   = {}
	self.loaded 	= true
	lfs.remove 		("images/temp.png")
	self:loadUI()
	self:checkImages(LINK_DIR.."images","images/")
end

function imageLoader:loadGameImages(toLoad)
	for i,key in ipairs(toLoad) do
		if objects[key] and key~="_controller" then 
			self:loadSymbol(key,"Game")
			objects[key].size = 0 --lfs.getSize( LINK_DIR..objects[key].dir..objects[key].name)
		 end
	end
end

function imageLoader:checkImages(folder,path)
	if not lfs.isDir(folder) then return end
	for i,f in ipairs(lfs.getDirectoryItems(folder)) do
		local file = folder.."/"..f
		local isThing = lume.match(lfs.getDirectoryItems(file),function(x) return x:sub(1,2)==".u" end) 

		if isThing then
			local key = isThing:sub(2,-1)
			if not objects[key] then 
				self:checkSymbol({key=key,name=f})
			end
			objects[key].dir = path 
		else
			self:checkImages(file,path.."/"..f)
		end
	end
	return fileTree
end


function imageLoader:isLoading(key)
	local isLoading = false
	for i,image in ipairs(self.toLoad) do 
		if image == key then 
			return true
		end
	end
	return isLoading
end

function imageLoader:reset()
	self.toLoad 	= {}
	self.loaded 	= false
end

function imageLoader:loadLoop()
	while #self.toLoad>0 do
		imageLoader:loadSymbol(self.toLoad[#self.toLoad],"Game")
		print("loadloop",self.toLoad[#self.toLoad])
		table.remove(self.toLoad,#self.toLoad)
	end
	self.loaded = true
end

function imageLoader:newSymbol()
	local default = (level.isAnim and "Cut 1" or "default")
	local name  			= "Untitled "..tostring(self:getNextUntitled())
	local key 				= uuid()
	local filename 		= (ZIP_MODE and LINK_DIR or GAME_DIR).."images/"..name.."/frames/"..key..".png"

	mkdir((ZIP_MODE and LINK_DIR or GAME_DIR).."images",name,"frames")

	-- local file = LOVR and lfs.read("png") or imgFile:getString()
	-- if ZIP_MODE then 
	-- 	bitser.dumpLoveFile(filename,file)
	-- else
	-- 	loader:writeFile 	(filename,file)
	-- end

	self:loadSymbol 	(key,"Game",name)
	loader:saveDef 		("objects",objects)

	return key
end


function imageLoader:getNextUntitled()
	local nextUntitled = 0
	for k,v in pairs(objects) do 
		local n = tonumber(v.name:sub(10))
		if v.name:sub(1,9) == "Untitled " and type(n)=="number" and n>nextUntitled then 
			nextUntitled = n
		end
	end
	return nextUntitled+1
end


function imageLoader:loadSymbol(key, folder, name)
	local ext  					= ".png"
	local name 					= objects[key] and objects[key].name or name or key
	local folderString 	= folder=="Game" and ("images/") or "images/"..folder.."/"
	local fullpath 			= (folder=="Game" and LINK_DIR or "")..folderString..name
	
	allSymbols[key] = allSymbols[key] or {
		fullpath  = fullpath..ext,
		folder 		=	folder,
		key 			= key,
		name 			=	name
	}

	local sym = allSymbols[key]

	if folder~="Game" then 
		sym.data  			= limage.newImageData( sym.fullpath )
	end

	if key=="_controller"then 
		sym.image 			= newCanvas(1,1)
	
	elseif folder=="Game"  then 

		print("\n path for ",key)

		sym=self:checkSymbol 	(sym)

		sym.image = sym.image  or {}
		sym.path  = sym.path   or {}
		print(key,".path =",inspect(sym.path))

		for a,anim in pairs(sym.animations) do 
			for l,layer in ipairs(anim.layers) do 
				if layer.format=="normal"  then 
					for f,frame in ipairs(layer.frames) do 
						print("texframe")
						sym.path [frame.id] = sym.path	[frame.id] or 
							string.format("%s%s%s/frames/%s.png", LINK_DIR, sym.dir, name, frame.id)
						sym.image[frame.id] = sym.image	[frame.id] or gfx.newImage(sym.path[frame.id])
					end
				end
			end
		end

		allSymbols[key].image = sym.image
		allSymbols[key].path = sym.path

		print(key,".path =",inspect(sym.path))
		print("")

	else 
		sym.image 			= gfx.newImage( sym.fullpath )
	end
             
	self:tagBrushesTextures(folder,key)

	return allSymbols[key]
end

function imageLoader:postLoad()
	-- if lume.count(objects)>0 then
	-- 	for i,o in pairs(objects) do 
	-- 		if allSymbols[o.key]==nil then 
	-- 			objects[o.key]=nil
	-- 			os.remove(GAME_DIR.."images".."/"..o.key..".png")
	-- 			lfs.remove("thumbnails/"..o.key..".png")
	-- 			log("removed "..o.key)
	-- 		end
	-- 		if getImage(o.key) == allSymbols.checkers.image then
	-- 			objects[o.key]=nil
	-- 		end
	-- 	end
	-- end

	loader:saveDef("objects",objects)
end

function imageLoader:checkSymbol(obj)
	local modtime = 1--tonumber(lfs.getLastModified(obj.fullpath),10)

	if objects[obj.key] then 
		local object = objects[ obj.key ]
		
		if obj.key~="_controller" and lfs.exists(LINK_DIR..object.dir..obj.name.."/."..obj.key) then 
	
			object.animations = object.animations or lfs.load(LINK_DIR..object.dir..obj.name.."/."..obj.key)()		

			object.size = lfs.getSize( LINK_DIR..object.dir..obj.name)

			if lfs.exists(LINK_DIR..object.dir..obj.name.."/.models") then 
				object.models = object.models or {}
				for m, model in ipairs(lfs.getDirectoryItems( LINK_DIR..object.dir..obj.name.."/.models/")) do 
					if model~=".DS_Store" then 
						print("LOAD MODEL",model)
						local filename = LINK_DIR..object.dir..obj.name.."/.models/"..model
						local mod =  loadstring(lfs.read(filename) )  ()		
						object.models[mod.id] = mod
					end
				end
			end
		end
		
		object.key 		= obj.key
		object.name 	= obj.name

		local garbage = collectgarbage ("count")
		local chunkedFrames={}
		local dir = LINK_DIR.."images/"..object.name.."/frames/"
		print(obj.name)
		for a,anim in pairs(object.animations) do
			for l,layer in ipairs(anim.layers) do
				layer.type = layer.type or "drawing"
				for f,frame in lume.ripairs(layer.frames) do
					local loaded = lfs.load(dir..frame)
					 print(frame)
					layer.frames[f] = (loaded and loaded()) 
					local frame = layer.frames[f]
					if not frame then 
						table.remove(layer.frames,f)
					else
						frame.tris	= frame.tris	 or {} 							_no_copy[frame.tris]	= true
						frame.verts	= frame.verts	 or {{},{},{},{}} 	_no_copy[frame.verts]	= true				
					end
				end
			end
		end
		print("addiff: ",collectgarbage ("count")-garbage)

	else 
		
		objects[ obj.key ] = {
			key  				= obj.key,
			name 				= obj.name,
			modtime 		= modtime,
			dir     		= obj.dir or "images/",
			tags 				= {},
			default 		= "default",
			splitFrames = true,
			animations 	= {
				default = {	
					key 		= "default",
					name 		= "default",
					fps 		= 24,
					length 	= 1,
					shapes 	= { {-1/2,-1/2,	1/2,-1/2, 1/2,1/2, -1/2,1/2}},
					layers  = {
						{ 	
							name 	= "Layer 1", 
							visible = true, 
							vector  = false,
							loop 	= false, 
							resolution = editor.drawingResolution or config.drawingResolution or 1,
							length 	= 1,							
							line 	= {color = {r=0,g=0,b=0,h=0,s=0,v=0,a=1},width=1},
							fill 	= {color = {r=0,g=0,b=0,h=0,s=0,v=0,a=1}},
							frames 	= {  
								{ 
									symbols = {},
									strokes = {},
									fills 	= {},
									position= {x=0,y=0,z=0},
									orientation= {x=0,y=0.001,z=0,w=1},
									scale= {x=1,y=1,z=1},
									blank=false, 
									x=0 , 
									y=0 , 
									w=obj.w or 4, 
									h=obj.h or 4, 	
									ox=0,
									oy=0,	
									l=1 
								}   
							}
						}
					}
				}
			}
		}
	end

	tagImage(objects[ obj.key ])

	return objects[ obj.key ]
end


function imageLoader:tagBrushesTextures(folder,key)
	if folder=="Brushes" then 
		table.insert(brushes,key)
	elseif folder=="Textures" then 
		table.insert(textures,key)
	end
end

function imageLoader:cacheThumbnail(img)

end

function imageLoader:tagImages()
	prepareTags()
	for k,obj in pairs(objects) do
		tagImage(obj)
	end
end

function releaseImage(image,d)
	local d = d or 1
	if canRelease(image) then 
		image:release() 
		image=nil
		log("RELEASE")
	elseif type(image) == "table" and d<16 then 
		for k,v in pairs(image) do 
			releaseImage(v,d+1)
		end
	end
	image=nil
end

function getImage(key)				return getValue(key,"image") 	end
function getImagePath(key)	 	return getValue(key,"path") 	end
function getImageName(key)		return getValue(key,"name")		end
function getImageThumb(key)		return getValue(key,"thumb")	end
function getImageData(key)		return getValue(key,"data") 	end
function getImageRaw(key)			return getValue(key,"rawimage")	end
function getImageType(key)		return getValue(key,"folder")	end
function getImageMip(key,n)		return getValueMip(key,"mips",n)end

function getValue(key,val)
	if key and allSymbols[key]~=nil then
		return allSymbols[key][val]
	else
		return allSymbols["checkers"][val] 
	end
end

function getValueMip(key,val,n)
	return allSymbols[key][val][n]
end

function tagImage(obj)
	if lume.count(tags)~=lume.count(tagNames) or #tags==0 then 
		prepareTags()
	end
	obj.tags = obj.tags or {}
	for t,tag in lume.ripairs(obj.tags) do
		if tagNames[tag] then 
			if not tags[tag] then 
				tags[tag] = {}
			end
			table.add(tags[tag],obj.key)
		else
			obj.tags[t]=nil
		end
	end
	table.add(tags.Game,obj.key)
end

function prepareTags()
	tags.Game 	= tags.Game or {}
	tags.Level 	= tags.Level or {}
	tags.Room 	= tags.Room or {}
	for k,v in pairs(tagNames) do
		tags[k]=tags[k] or {}
	end
end


function PremultiplyGammaPixel(x, y, r, g, b, a)
   r, g, b = mth.gammaToLinear(r, g, b)
   r = r * (a)
   g = g * (a)
   b = b * (a)
   r, g, b = mth.linearToGamma(r, g, b)
   return r, g, b, a
end

function UnmultiplyGammaPixel(x, y, r, g, b, a)
   r, g, b = mth.gammaToLinear(r, g, b)
   r = (r / a)
   g = (g / a)
   b = (b / a)
   r, g, b = mth.linearToGamma(r, g, b)
   return r, g, b, a
end

function UnmultiplyPixel(x, y, r, g, b, a)
   r = (r / a)
   g = (g / a)
   b = (b / a)
   return r, g, b, a
end

function PremultiplyPixel(x, y, r, g, b, a)
   r = r * a
   g = g * a
   b = b * a
   return r, g, b, a
end


function imageLoader:loadUI()
	interface_images = 0
	for f,folder in pairs({
		Brushes={
			"circlebrush",
			"square",
			"stippled",
			"stippledsoft",
			"trianglebrush",
		}, 
		Cursors={
			"scale_hCursor",
			"scale_d1Cursor",
			"scale_d2Cursor",
			"scale_wCursor",
			"rotateCursor",
			"fillCursor",
			"grabCursor",
			"handCursor",
			"moveCursor",
			"plusCursor",
		}, 
		Interface={
			"bigPlus",
			"blankPixel",
			"BodyCenter",
			"BoundingBox",
			"checkers",
			"checkersRounded",
			"CheckIcon",
			"circleFill8",
			"circleLine8",
			"circleFill12",
			"circleLine12",
			"ContextShadow",
			"ContextShadowShort",
			"CrossSign",
			"depthIcon",
			"depthXIcon",
			"Dial",
			"eyedrop",
			"falloff_constant",
			"falloff_linear",
			"falloff_sharp",
			"falloff_smooth",
			"falloff_sphere",
			"hidden",
			"Hue",
			"link",
			"linkbroken",
			"loop",
			"loopClip",
			"missing",
			"moveIcon",
			"onionIcon",
			"orbit",
			"panelShadowH",
			"pathLoop",
			"pathRepeat",
			"pathReverse",
			"pen",
			"pivot_bound",
			"pivot_cursor",
			"pivot_origins",
			"playIcon",
			"PlusSign",
			"proportional_connected",
			"proportional_disabled",
			"proportional_distance",
			"reload",
			"remodel",
			"rotateXIcon",
			"rotateYIcon",
			"rotateZIcon",
			"scaleIcon",
			"script",
			"seeThru",
			"SelectorWhite",
			"tools_brush",
			"tools_erase",
			"tools_fill",
			"tools_move",
			"tools_pen",
			"tools_select",
			"transform_global",
			"transform_local",
			"transform_normal",
			"unlit",
			"wallClosed",
			"wallGaps",
			"wallOpen",
			"wireframe",
		}, 
		Textures={
			"grass",
			"noise",
		}
	}) 
	do 
		for i, image in ipairs(folder) do 
			imageLoader:loadSymbol(image,f)
			interface_images = interface_images + 1
		end
	end
end