local abort = false
local r, g, b, alpha, h, s, l

--@TBCONFIG SLIDER: Number of fills, 8.0
--@TBCONFIG SLIDER: Random Seed, 0
--@TBCONFIG SLIDER: Coverage, 66
--@TBCONFIG STYLE: FillStyle, 4,Black,White,Transparent,Random,Color1,Color2,Color3,Color4

local NumFills = math.floor(sliderVal1 * 1000 )
math.randomseed(sliderVal2 * 100)
local Coverage = sliderVal3 
local fillMode  = styleVal1

-- ===============================================================
-- ===  fill code
-- ===============================================================
 -- from http://en.wikipedia.org/wiki/Flood_fill
 -- Flood-fill (node, target-color, replacement-color):
 -- 1. Set Q to the empty queue.
 -- 2. If the color of node is not equal to target-color, return.  (target color is the color to be replaced - here origRGB
 -- 3. Add node to Q.
 -- 4. For each element n of Q:
 -- 5.  If the color of n is equal to target-color:
 -- 6.   Set w and e equal to n.
 -- 7.   Move w to the west until the color of the node to the west of w no longer matches target-color.
 -- 8.   Move e to the east until the color of the node to the east of e no longer matches target-color.
 -- 9.   Set the color of nodes between w and e to replacement-color.
 -- 10.   For each node n between w and e:
 -- 11.    If the color of the node to the north of n is target-color, add that node to Q.
       -- If the color of the node to the south of n is target-color, add that node to Q.
 -- 12. Continue looping until Q is exhausted.
 -- 13. Return.
 
local tol = 0.01
local StackLimit = 1000
local StackPos = 0 
local stX = {}
local stY = {}

function fillStackPush(X, Y)
	-- if StackPos < StackLimit and Y >= 0 and Y <= width then
	if StackPos < StackLimit  then
		stX[StackPos] = X
		stY[StackPos] = Y
		StackPos = StackPos + 1 
	end
end
function fillStackPop()
local X,Y
	StackPos = StackPos - 1
	X = stX[StackPos]
	Y = stY[StackPos]
	return X, Y
end
function ColorsSame(x, y, origR, origG, origB)
local  a, b, c
local thisR, thisG, thisB = get_rgb(x, y)		-- get the exact color
	-- apply a tolerance of 1% to allow for aliasing effects
	a = CheckTolerance(thisR, origR, tol)
	b = CheckTolerance(thisG, origG, tol)
	c = CheckTolerance(thisB, origB, tol)
	if a == true and b == true and c == true then
		return true
	else
		return false
	end
	
end
function CheckTolerance(a, b, tol)
local  p
	if b > a then 
	p = a; a = b; b = p  -- swap over so that a is always larger (or equal)
	end
	if a > b then 
		p = (a - b) / a
	else
		p = 0 
	end
	if p < tol then 
		return true
	else
		return false
	end
end
 -- 6.   Set w and e equal to n.
 -- 7.   Move w to the west until the color of the node to the west of w no longer matches target-color.
 -- 8.   Move e to the east until the color of the node to the east of e no longer matches target-color.
 -- 9.   Set the color of nodes between w and e to replacement-color.
function scanLine(x, y, origR, origG, origB, newR, newG, newB, newA )
local thisR, thisG, thisB ,west, east
		-- scan left replacing orig col with new color until hit boundary
		west = x
		while west > 0 do 
			if ColorsSame(west, y, origR, origG, origB)  then 
				set_rgba(west, y, newR, newG, newB, newA )
				west = west - 1
			else
				break
			end 
		end
		looptest = 0
		east = x + 1  
		while east < width do 
			if ColorsSame(east, y, origR, origG, origB)  then 
				set_rgba(east, y, newR, newG, newB, newA )
				east = east + 1
			else
				break
			end 
		end		
		flush()  -- update the buffer with this new info
		return west + 1  ,east - 1
end
	
function fill(x, y, newR, newG, newB, newA )  -- Fill background with given color
local left, e,w, dy, looptest
local origR, origG, origB
local r,g,b, i, j, ChangeBelow, ChangeAbove, dd, doffset
	 -- 1. Set Q to the empty queue.
	 StackPos = 0

	 -- 2. If the color of node is the same as target-color, return.
	origR, origG, origB = get_rgb(x, y)  -- get the target color
	-- optimisation: if the color is already set then stop
	if ColorsSame(x, y, newR, newG, newB) then return end

	 for  dd = 1,2 do 
	 	 -- 3. Add starting node to Q.
		if dd == 1 then 
			doffset = 1	-- move down the screen
			fillStackPush(x,  y )  -- set the starting position
		else
			doffset = -1  -- move up the screen
			fillStackPush(x,  y - 1)  -- set the starting position
		end
		-- 4. For each element n of Q:
		while StackPos > 0 do -- if there is something on the stack process it.
		if is_escape() > 0 then 
			abort = true; return 
		end
			if StackPos >= StackLimit then break end 
			x,y = fillStackPop()  --  get the next node from the stack to process
			-- 10.   For each node n between w and e:
			-- 11.    If the color of the node to the north of n is target-color, add that node to Q.
			--         If the color of the node to the south of n is target-color, add that node to Q.
			-- 12. Continue looping until Q is exhausted.
			-- scan left and right to find the ends of this line. fill in the color as we go 
			e,w = scanLine(x,y, origR, origG, origB, newR, newG, newB, newA )
			ChangeBelow = 0  -- 0 means always
			for i = e, w do 
					if ColorsSame(i, y + doffset, origR, origG, origB)  then  -- color is to be replaced
						if ChangeBelow == 0 or ChangeBelow == 1  then 
							fillStackPush(i,  y + doffset )
							ChangeBelow = -1
						end
					else  -- color is a boundary color and is not to be replaced
							ChangeBelow = 1
					end
			end
			ChangeAbove = 0  -- 0 means always
			for i = e, w do 
					if ColorsSame(i, y - doffset, origR, origG, origB)  then  -- color is to be replaced
						if ChangeAbove == 0 or ChangeAbove == 1  then 
							fillStackPush(i,  y - doffset)
							ChangeAbove = -1
						end
					else  -- color is a boundary color and is not to be replaced
							ChangeAbove = 1
					end
			end
		end 
	end 
end
-- ===============================================================
-- ===  end of fill code
-- ===============================================================
function ToRGB1(rm1, rm2, Hue)
	if (Hue > 360) then  Hue = Hue - 360 end
	if (Hue < 0) then Hue = Hue + 360 end
	if (Hue < 60) then rm1 = rm1 + ((rm2 - rm1) * Hue ) / 60 
	elseif (Hue < 180) then rm1 = rm2
	elseif (Hue < 240) then rm1 = rm1 + ((rm2 - rm1) * (240 - Hue) ) / 60
	end
	return rm1 
end

function ToRGB(hue,luminance,saturation)
local red,green,blue, rm1, rm2
	if (saturation == 0.0) then --  Grauton, einfacher Fall
		red = luminance * 255; green = red; blue = red
	else
		if (luminance <= 0.5) then 
			rm2 = luminance + luminance * saturation
		else
			rm2 = luminance + saturation - luminance * saturation
		end
		rm1 = 2 * luminance - rm2
		red = ToRGB1(rm1, rm2, hue + 120)
		green = ToRGB1(rm1, rm2, hue)
		blue = ToRGB1(rm1, rm2, hue - 120)
	end
	return red, green , blue 
end

function SetFillColor()

	alpha = 1
	if fillMode == 1 then		-- black
		r = 0; g = 0; b = 0
	elseif fillMode ==2 then 	-- white
		r = 1; g = 1; b = 1
	elseif fillMode ==3 then	-- transparent
		r = 0; g = 0; b = 0; alpha = 0
	elseif fillMode ==4 then	-- Random
		h = math.random() * 360; s = 0.5; l = 1
		r,g,b = ToRGB(h,s,l)
	elseif fillMode ==5 then	-- color 1
		r, g, b = get_color1()
	elseif fillMode ==6 then	-- color 2
		r, g, b = get_color2()
	elseif fillMode ==7 then	-- color 3
		r, g, b = get_color3()
	elseif fillMode ==8 then	-- color 4
		r, g, b = get_color4()
	end			
end

local iter, testX, testY
local baseX = width * ( 1 - Coverage) / 2
local baseY = height * ( 1 - Coverage) / 2
for iter = 0, NumFills do 
	SetFillColor()
	testX = math.random() * width * Coverage + baseX
	testY = math.random() * height * Coverage + baseY
	if ColorsSame(testX, testY, 1, 1, 1) == true then 
		fill ( testX, testY , r,g,b,alpha)
	end
	if abort == true then break end
end
