local player = require'cplayer'
local bezier3 = require'path2d_bezier3'

local b1 = {600, 150, 1000, 10, 550, 10, 1000, 150}
local b2 = {800, 200, 20, 600, 1000, 100, 1200, 350}
local b3 = {50, 400, 4000050, 450, 150, 450, 4000050, 400}
local b4 = {4000050, 550, 150, 500, 4000050, 500, 50, 550}

local scale = 1
local width = 0
local angle_tolerance = 0
local cusp_limit = 0

function player:on_render(cr)

	scale = self:slider{id = 'scale',
		x = 10, y = 10, w = 400, h = 24, text = 'scale',
		i1 = 100, i0 = 0.01, step = 0.01, i = scale,
	}

	width = self:slider{id = 'width',
		x = 10, y = 40, w = 400, h = 24, text = 'width',
		i1 = 200, i0 = 0, step = 1, i = width,
	}

	angle_tolerance = self:slider{id = 'angle_tolerance',
		x = 10, y = 70, w = 400, h = 24, text = 'angle tolerance',
		i1 = 90, i0 = 0, step = 0.1, i = angle_tolerance,
	}

	cusp_limit = self:slider{id = 'cusp_limit',
		x = 10, y = 100, w = 400, h = 24, text = 'cusp limit',
		i1 = 90, i0 = 0, step = 1, i = cusp_limit,
	}

	local function interpolate(x1, y1, x2, y2, x3, y3, x4, y4, ...)
		--stroke segments
		local n = 0
		cr:move_to(x1, y1)
		bezier3.interpolate(function(s, x, y) cr:line_to(x, y); n = n + 1 end,
			x1, y1, x2, y2, x3, y3, x4, y4, scale, angle_tolerance, cusp_limit)
		self:stroke(...)

		--segment endpoints
		self:dot(x1, y1, 2)
		bezier3.interpolate(function(s, x, y) self:dot(x, y, 2) end,
			x1, y1, x2, y2, x3, y3, x4, y4, scale, angle_tolerance, cusp_limit)

		--offsetting
		cr:move_to(x1, y1)
		bezier3.interpolate(function(s, x, y) cr:line_to(x, y) end,
			x1, y1, x2, y2, x3, y3, x4, y4, scale, angle_tolerance, cusp_limit)
		self:stroke((...)..'80', width)

		return n
	end

	local function draw(id, b)
		--draw draggable control points
		self:dragpoints{id = id, points = b}

		--draw faint lines to control points
		self:line(b[1], b[2], b[3], b[4], 'faint_bg')
		self:line(b[5], b[6], b[7], b[8], 'faint_bg')

		--draw with cairo first to see if there's any difference
		local x1, y1, x2, y2, x3, y3, x4, y4 = unpack(b)
		self:curve(x1, y1, x2, y2, x3, y3, x4, y4, 'error_bg')

		--bounding box
		local x, y, w, h = bezier3.bounding_box(unpack(b))
		self:rect(x, y, w, h, 'faint_bg')

		--hit -> draw hit point
		local d,x,y,t = bezier3.hit(self.mousex, self.mousey, unpack(b))
		self:dot(x, y, 4, '#00ff00')

		--split -> draw pieces with different colors
		local
			ax1, ay1, ax2, ay2, ax3, ay3, ax4, ay4,
			bx1, by1, bx2, by2, bx3, by3, bx4, by4 = bezier3.split(t, unpack(b))
		local n1 = interpolate(ax1, ay1, ax2, ay2, ax3, ay3, ax4, ay4, '#ffff00')
		local n2 = interpolate(bx1, by1, bx2, by2, bx3, by3, bx4, by4, '#ff00ff')

		--t and length
		self:label{x = x, y = y+10, text =
			string.format('t: %4.2f, len: %4.2f, segs: %d', t, bezier3.length(t, unpack(b)), n1 + n2)}
	end

	--draw curves
	draw('b1', b1)
	draw('b2', b2)
	draw('b3', b3)
	draw('b4', b4)
end

player:play()
