lua_completion = {
	[0] = {
		"io", "os", "print", "assert", "collectgarbage", "dofile", "error", "getfenv", "getmetatable", "ipairs", "load", "loadfile",
		"loadstring", "next", "pairs", "pcall", "rawequal", "rawget", "rawset", "select", "setfenv", "setmetatable",
		"tonumber", "tostring", "type", "unpack", "_VERSION", "xpcall", "math", "string", "table"
	},
	["io"] = { "close", "flush", "input", "lines", "open", "output", "popen", "read", "tmpfile", "type", "write" },
	["os"] = { "clock", "date", "difftime", "execute", "exit", "getenv", "remove", "rename", "setlocale", "time", "tmpname" },
	["table"] = { "concat", "insert", "maxn", "remove", "sort" },
	["string"] = { "byte", "char", "dump", "find", "format", "gmatch", "gsub", "len", "lower", "match", "rep", "reverse", "sub", "upper" },
	["math"] = {
		"abs", "acos", "atan", "atan2", "ceil", "cos", "cosh", "deg", "exp", "floor", "fmod", "frexp", "huge", "ldexp", "log",
		"log10", "max", "min", "modf", "pi", "pow", "rad", "random", "randomseed", "sin", "sinh", "sqrt", "tan", "tanh"
	}
};

function mgr:on_lua_completion(doc, status, helper)
	-- lua 自动补全
	-- status
	-- 0 popup
	-- 1 commit	with enter
	-- 2 typing
	-- 3 dismiss completion list
	-- 4 dismiss completion tip
	-- 5 item selected
	-- 6 commit with tab
	-- 0x1001 LSP update list
	-- print("lua complete ", status);
	-- 得到当前行
	local text = doc.get_text(doc.cursor_line, 0, doc.cursor_column) or "";
	-- 取得最后一部分
	text = text:match("([.:_%w]+)$") or "";

	if text == nil or text == "" then
		if status ~= 0 and status ~= 5 and status ~= 6 and status ~= 1 then
			helper.cancel_completion();
			lsp:cleanup_completion(doc);
			return 0;
		end;
		text = "";
	end;

	local class = text:match("([^.:]+).*");
	local context = text:match(".*[.:]([^.:]*)");

	if context == nil then
		context = class;
		class = "";
	end;

	if status == 1 or status == 6 then
		local commit_mode = 0;
		if status == 6 then
			commit_mode = 1;
		end;
		local commit_ret = lsp:commit_completion(doc, helper, commit_mode);
		if commit_ret > 0 then
			return 1;
		end;
		-- 选择当前项
		doc.select_text(doc.cursor_line, doc.cursor_column - sizeof(context), doc.cursor_line, doc.cursor_column);
		doc.set_text(helper.selected_item_text);
		helper.cancel_completion();
		return 1;
	end ;

	if status == 5 then
		lsp:update_completion_tip(doc, helper);
		return 1;
	end;

	if status == 0 then
		if lsp:do_completion(doc, helper) then
			return 1;
		end;

		helper.clear(false);
		lsp:cleanup_completion(doc);

		local info_class = lua_completion[class];
		if info_class == nil then
			info_class = lua_completion[0];
		end ;
		for i, v in pairs(info_class) do
			helper.push_back(v, 0, 0);
		end ;
		helper.sort_items();
		helper.select_item(context);
		helper.redraw();
		return 1;
	end;
	
	if status == 2 or status == 0x1001 then
		local match_state = 0;
		do
			-- 添加光标后内容, 以实现整词选择
			local tail_text = doc.get_text(doc.cursor_line, doc.cursor_column, 1024);
			if tail_text then
				local tail_part = tail_text:match([[^(.-)[-%s@#%$%%%^%&%*%.%(%)!`+=\\/?<>%[%]|:;'",].*$]]);
				tail_text = tail_part or tail_text;
				match_state = helper.select_item(context .. tail_text);
			end;
		end;
		if match_state < 0 then
			match_state = helper.select_item(context);
		end;
		-- match_state
		-- < 0 无匹配项
		-- 0 有完整匹配
		-- 1 头部匹配
		-- 2 分段匹配(如：GeLi 匹配 GetList)
		-- 3 部分匹配
		-- 4 首字母匹配
		-- 5 头部匹配(忽略大小写)
		-- 6 部分匹配(忽略大小写)
		if match_state ~= 0 and status == 2 then
			-- no full matched, update completion list
			if match_state < 0 then
				helper.set_selection_tip(nil);
			end;
			lsp:do_completion(doc, helper);
		end;
		helper.redraw();
		return 1;
	end;
	return 0;
end;
