local lib = ...

local image
image = lib.class {

	__concat   = function(self,with) return self:blit(with) end;
	__tostring = function(self)      return self:render()   end;
	__index = {
		render = function(self)
			local str = ''
			local bracket = false
			if self.combine then
				str = string.format('[combine:%sx%s', self.w, self.h)
				for _,i in pairs(self.atop) do
					str = str .. string.format(':%s,%s=(%s)', i.at.x, i.at.y, i.img:render())
				end
			else
				for _,i in pairs(self.atop) do
					str = '(' .. i.img:render() .. ')^' .. str
				end
				if str ~= '' then
					str = str .. '('
					bracket = true
				end
				str = str .. self.string
			end
			for _,e in pairs(self.fx) do
				str = str .. '^[' .. e
				-- be sure to escape ones that take arguments
				-- correctly!
			end
			if bracket then str = str .. ')' end
			return str
		end;

		-- must be used to mark an image before
		-- the second form of blit can be used
		compound = function(self, w, h)
			return image.change(self, {
				combine = true;
				w = w, h = h;
			})
		end;

		blit = function(self, img, at)
			assert((not at) or self.combine)
			if img then return image.change(self, {
				atop = lib.tbl.append(self.atop, {{img=img, at=at}})
			}) else return self end
		end;

		multiply = function(self, color)
			return image.change(self, {
				fx = lib.tbl.append(self.fx, {'multiply:' .. tostring(color)})
			})
		end;

		paint = function(self, color, ratio)
			return image.change(self, {
				fx = lib.tbl.append(self.fx, {'colorize:' .. tostring(color) .. ':' .. ratio})
			})
		end;

		tint = function(self, color)
			if not color.hue then
				if not lib.color.id(color) then
					color = lib.color(color)
				end
				color = color:to_hsl()
			end
			return image.change(self, {
				fx = lib.tbl.append(self.fx, {
					string.format('colorizehsl:%s:%s:%s',
						color.hue, color.sat*100, color.lum*100)
				})
			})
		end;

		shift = function(self, color)
			if color.hue == nil or color.sat == nil or color.lum == nil then
				if not lib.color.id(color) then
					color = lib.color(color)
				end
				color = color:to_hsl()
			end
			return image.change(self, {
				fx = lib.tbl.append(self.fx, {
					string.format('hsl:%s:%s:%s',
						color.hue, color.sat, color.lum)
				})
			})
		end;

		rehue = function(self, hue)
			return self.shift{hue=hue, sat=0, lum=0}
		end;

		colorize = function(self, color)
			local hsl
			if color.hue then
				hsl = color
			else
				hsl = color:to_hsl()
			end
			return self:shift {
				hue = hsl.hue;
				sat = hsl.sat * 2 - 1;
				lum = hsl.lum * 2 - 1;
			}
		end;

		fade = function(self, fac)
			return image.change(self, {
				fx = lib.tbl.append(self.fx, {'opacity:' .. (255 - 255*fac)})
			})
		end;

		transform = function(self, kind)
			return image.change(self, {
				fx = lib.tbl.append(self.fx, {'transform' .. tostring(kind)})
			})
		end;

		glow = function(self,color) return self:blit(self:multiply(color)) end;
	};

	construct = function(file, w, h) return {
		string = file;
		atop = {};
		fx = {};
		combine = w and h and true or nil;
	} end;
}
return image
