
---- Fast analog circular text entry method ----
-------------------------------------------------------------------------------

TextEntry = {
	circs = { -- only for reference
		"ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_", -- 65-96
		"abcdefghijklmnopqrstuvwxyz{|}~ ", -- 33-64
		"!\"#$%&'()*+,-./0123456789:;<=>?" -- 97-128
	},
	curCirc = 481, curChar = 0,
	str = "", strPos = 0,
	drawcount = 0,
	quit = false
}

function TextEntry:fadeIn()
	for i=255, 0, -8 do
		self:draw()
		screen:flash(Color.new(0, 0, 0, i))
		screen.flip()
	end
end

function TextEntry:draw()
	self.drawcount = self.drawcount + 1
	screen:clear()
	local xs, ys = SCREEN_WIDTH2-200, SCREEN_HEIGHT2-20
	for j = -1, 1 do
		local circ = math.mod(self.curCirc+j, 3)
		for i = 0, 31, 2 do
			local v = i/16*math.pi
			local col = (i/2 == self.curChar and j == 0) and colors.red or colors.verylightgray
			Vera:print(string.char(i+33+32*circ, i+34+32*circ), 
				xs+math.sin(v)*70+(j+1)*200, 
				ys-math.cos(v)*70, Font.CENTER, col)
		end
	end
	Crystal:print("Text entry:", SCREEN_WIDTH2, 6, Font.CENTER, colors.white200)
	Crystal:print(self.str, 32, SCREEN_HEIGHT-54)
	
	local lx, ly1, ly2 = 32+16*self.strPos, SCREEN_HEIGHT-56, SCREEN_HEIGHT-34
	local sinfac =  math.sin(self.drawcount/8)*80
	local lc = Color.new(180+sinfac, 180+sinfac, 180+sinfac)
	screen:drawLine(lx, ly1, lx, ly2, lc)
	screen:drawLine(lx-1, ly1, lx-1, ly2, colors.white50)
	screen:drawLine(lx+1, ly1, lx+1, ly2, colors.white50)
	screen:fillRect(30, ly1, string.len(self.str)*16+4, ly2-ly1, colors.white50)
	
	screen:blit(0, SCREEN_HEIGHT-20, imgs.texthelp)
end

function TextEntry:control(ctrl)	
	local before, after = string.sub(self.str, 1, self.strPos), string.sub(self.str, self.strPos+1)
	if ctrl:cross() or (ctrl:circle() and self.curChar < 15) then
		local k = ctrl:cross() and 33 or 34
		self.str = before .. string.char(self.curChar*2+k+32*math.mod(self.curCirc, 3)) .. after
		self.strPos = self.strPos + 1
	elseif ctrl:square() and self.strPos > 0 then
		self.str = string.sub(before, 1, -2) .. after
		self.strPos = self.strPos - 1
	elseif ctrl:left() and self.strPos > 0 then
		self.strPos = self.strPos - 1
	elseif ctrl:right() then
		self.strPos = self.strPos + 1
		if self.strPos > string.len(self.str) then self.str = self.str .. " " end
	elseif ctrl:up() then
		self.strPos = 0
	elseif ctrl:down() and string.len(self.str) > 0 then
		self.strPos = string.len(self.str)
	elseif ctrl:l() then
		self.curCirc = self.curCirc-1
	elseif ctrl:r() then
		self.curCirc = self.curCirc+1
	end
end

function TextEntry:getString(initial)
	self.str = initial or ""
	self.strPos = string.len(self.str)
	self:fadeIn()
	self.quit = false
	local ctrl, oldctr, x, y
	repeat
		oldctrl = ctrl
		ctrl = Controls.read()	
		
		x, y = ctrl:analogX(), ctrl:analogY()
		if math.abs(x)+math.abs(y) > 30 then
			if x >= 0 then
				self.curChar = math.floor(math.atan2(x/128, -y/128)*(8/math.pi))
			else
				self.curChar = 15 - math.floor(math.atan2(-x/128, -y/128)*(8/math.pi))
			end
		end
		
		if ctrl ~= oldctrl then 
			self:control(ctrl)
		end
		
		self:draw()
		screen.flip()
		
		if ctrl:triangle() then
			Window:show(80, nil, function()
				Crystal:print("Entry finished?", SCREEN_WIDTH2, SCREEN_HEIGHT2-30, Font.CENTER)
				Vera:print("You entered: \""..self.str.."\"\nCircle to exit, X to continue.", 
					SCREEN_WIDTH2, SCREEN_HEIGHT2+4, Font.CENTER)
			end, 
			function()
				local ctrl = Controls.read()
				if ctrl:circle() then 
					self.quit = true;
					Window:close()
				end
				if ctrl:cross() then 
					Window:close() 
				end
			end)
			if not self.quit then self:fadeIn() end
		end
	until self.quit
	
	return self.str
end
